java截图+中文图片识别

  • Post author:
  • Post category:java




1、pom文件

<dependency>
            <groupId>net.sourceforge.tess4j</groupId>
            <artifactId>tess4j</artifactId>
            <version>4.5.4</version>
        </dependency>

        <dependency>
            <groupId>org.bytedeco.javacpp-presets</groupId>
            <artifactId>tesseract-platform</artifactId>
            <version>4.0.0-1.4.4</version>
        </dependency>



2、ImageUtil.class,做降噪处理

import java.awt.*;
import java.awt.image.BufferedImage;

/**
 * @author ZhaoXu
 * @date 2021/11/25 15:21
 */
public class ImageUtil {

    public static BufferedImage grayImage(BufferedImage bufferedImage) throws Exception {

        int width = bufferedImage.getWidth();
        int height = bufferedImage.getHeight();

        BufferedImage grayBufferedImage = new BufferedImage(width, height, bufferedImage.getType());
        for (int i = 0; i < bufferedImage.getWidth(); i++) {
            for (int j = 0; j < bufferedImage.getHeight(); j++) {
                final int color = bufferedImage.getRGB(i, j);
                final int r = (color >> 16) & 0xff;
                final int g = (color >> 8) & 0xff;
                final int b = color & 0xff;
                int gray = (int) (0.3 * r + 0.59 * g + 0.11 * b);
                int newPixel = colorToRGB(255, gray, gray, gray);
                grayBufferedImage.setRGB(i, j, newPixel);
            }
        }

        return grayBufferedImage;

    }

    /**
     * 颜色分量转换为RGB值
     *
     * @param alpha
     * @param red
     * @param green
     * @param blue
     * @return
     */
    private static int colorToRGB(int alpha, int red, int green, int blue) {

        int newPixel = 0;
        newPixel += alpha;
        newPixel = newPixel << 8;
        newPixel += red;
        newPixel = newPixel << 8;
        newPixel += green;
        newPixel = newPixel << 8;
        newPixel += blue;

        return newPixel;

    }

    public static BufferedImage binaryImage(BufferedImage image) throws Exception {
        int w = image.getWidth();
        int h = image.getHeight();
        float[] rgb = new float[3];
        double[][] zuobiao = new double[w][h];
        int black = new Color(0, 0, 0).getRGB();
        int white = new Color(255, 255, 255).getRGB();
        BufferedImage bi= new BufferedImage(w, h,
                BufferedImage.TYPE_BYTE_BINARY);;
        for (int x = 0; x < w; x++) {
            for (int y = 0; y < h; y++) {
                int pixel = image.getRGB(x, y);
                rgb[0] = (pixel & 0xff0000) >> 16;
                rgb[1] = (pixel & 0xff00) >> 8;
                rgb[2] = (pixel & 0xff);
                float avg = (rgb[0]+rgb[1]+rgb[2])/3;
                zuobiao[x][y] = avg;

            }
        }
        //这里是阈值,白底黑字还是黑底白字,大多数情况下建议白底黑字,后面都以白底黑字为例
        double SW = 192;
        for (int x = 0; x < w; x++) {
            for (int y = 0; y < h; y++) {
                if (zuobiao[x][y] < SW) {
                    bi.setRGB(x, y, black);
                }else{
                    bi.setRGB(x, y, white);
                }
            }
        }



        return bi;
    }
    // 自己加周围8个灰度值再除以9,算出其相对灰度值
    public static double getGray(double[][] zuobiao, int x, int y, int w, int h) {
        double rs = zuobiao[x][y] + (x == 0 ? 255 : zuobiao[x - 1][y]) + (x == 0 || y == 0 ? 255 : zuobiao[x - 1][y - 1])
                + (x == 0 || y == h - 1 ? 255 : zuobiao[x - 1][y + 1]) + (y == 0 ? 255 : zuobiao[x][y - 1])
                + (y == h - 1 ? 255 : zuobiao[x][y + 1]) + (x == w - 1 ? 255 : zuobiao[x + 1][y])
                + (x == w - 1 || y == 0 ? 255 : zuobiao[x + 1][y - 1])
                + (x == w - 1 || y == h - 1 ? 255 : zuobiao[x + 1][y + 1]);
        return rs / 9;
    }

    /**
     * 降噪,以1个像素点为单位(实际使用中可以循环降噪,或者把单位可以扩大为多个像素点)
     * @param image
     * @return
     */
    public static BufferedImage denoise(BufferedImage image){
        int w = image.getWidth();
        int h = image.getHeight();
        int white = new Color(255, 255, 255).getRGB();

        if(isWhite(image.getRGB(1, 0)) && isWhite(image.getRGB(0, 1)) && isWhite(image.getRGB(1, 1))){
            image.setRGB(0,0,white);
        }
        if(isWhite(image.getRGB(w-2, 0)) && isWhite(image.getRGB(w-1, 1)) && isWhite(image.getRGB(w-2, 1))){
            image.setRGB(w-1,0,white);
        }
        if(isWhite(image.getRGB(0, h-2)) && isWhite(image.getRGB(1, h-1)) && isWhite(image.getRGB(1, h-2))){
            image.setRGB(0,h-1,white);
        }
        if(isWhite(image.getRGB(w-2, h-1)) && isWhite(image.getRGB(w-1, h-2)) && isWhite(image.getRGB(w-2, h-2))){
            image.setRGB(w-1,h-1,white);
        }

        for(int x = 1; x < w-1; x++){
            int y = 0;
            if(isBlack(image.getRGB(x, y))){
                int size = 0;
                if(isWhite(image.getRGB(x-1, y))){
                    size++;
                }
                if(isWhite(image.getRGB(x+1, y))){
                    size++;
                }
                if(isWhite(image.getRGB(x, y+1))){
                    size++;
                }
                if(isWhite(image.getRGB(x-1, y+1))){
                    size++;
                }
                if(isWhite(image.getRGB(x+1, y+1))){
                    size++;
                }
                if(size>=5){
                    image.setRGB(x,y,white);
                }
            }
        }
        for(int x = 1; x < w-1; x++){
            int y = h-1;
            if(isBlack(image.getRGB(x, y))){
                int size = 0;
                if(isWhite(image.getRGB(x-1, y))){
                    size++;
                }
                if(isWhite(image.getRGB(x+1, y))){
                    size++;
                }
                if(isWhite(image.getRGB(x, y-1))){
                    size++;
                }
                if(isWhite(image.getRGB(x+1, y-1))){
                    size++;
                }
                if(isWhite(image.getRGB(x-1, y-1))){
                    size++;
                }
                if(size>=5){
                    image.setRGB(x,y,white);
                }
            }
        }

        for(int y = 1; y < h-1; y++){
            int x = 0;
            if(isBlack(image.getRGB(x, y))){
                int size = 0;
                if(isWhite(image.getRGB(x+1, y))){
                    size++;
                }
                if(isWhite(image.getRGB(x, y+1))){
                    size++;
                }
                if(isWhite(image.getRGB(x, y-1))){
                    size++;
                }
                if(isWhite(image.getRGB(x+1, y-1))){
                    size++;
                }
                if(isWhite(image.getRGB(x+1, y+1))){
                    size++;
                }
                if(size>=5){
                    image.setRGB(x,y,white);
                }
            }
        }

        for(int y = 1; y < h-1; y++){
            int x = w - 1;
            if(isBlack(image.getRGB(x, y))){
                int size = 0;
                if(isWhite(image.getRGB(x-1, y))){
                    size++;
                }
                if(isWhite(image.getRGB(x, y+1))){
                    size++;
                }
                if(isWhite(image.getRGB(x, y-1))){
                    size++;
                }
                //斜上下为空时,去掉此点
                if(isWhite(image.getRGB(x-1, y+1))){
                    size++;
                }
                if(isWhite(image.getRGB(x-1, y-1))){
                    size++;
                }
                if(size>=5){
                    image.setRGB(x,y,white);
                }
            }
        }

        //降噪,以1个像素点为单位
        for(int y = 1; y < h-1; y++){
            for(int x = 1; x < w-1; x++){
                if(isBlack(image.getRGB(x, y))){
                    int size = 0;
                    //上下左右均为空时,去掉此点
                    if(isWhite(image.getRGB(x-1, y))){
                        size++;
                    }
                    if(isWhite(image.getRGB(x+1, y))){
                        size++;
                    }
                    //上下均为空时,去掉此点
                    if(isWhite(image.getRGB(x, y+1))){
                        size++;
                    }
                    if(isWhite(image.getRGB(x, y-1))){
                        size++;
                    }
                    //斜上下为空时,去掉此点
                    if(isWhite(image.getRGB(x-1, y+1))){
                        size++;
                    }
                    if(isWhite(image.getRGB(x+1, y-1))){
                        size++;
                    }
                    if(isWhite(image.getRGB(x+1, y+1))){
                        size++;
                    }
                    if(isWhite(image.getRGB(x-1, y-1))){
                        size++;
                    }
                    if(size>=8){
                        image.setRGB(x,y,white);
                    }
                }
            }
        }

        return image;
    }

    public static boolean isBlack(int colorInt)
    {
        Color color = new Color(colorInt);
        if (color.getRed() + color.getGreen() + color.getBlue() <= 300)
        {
            return true;
        }
        return false;
    }

    public static boolean isWhite(int colorInt)
    {
        Color color = new Color(colorInt);
        if (color.getRed() + color.getGreen() + color.getBlue() > 300)
        {
            return true;
        }
        return false;
    }

    public static int isBlack(int colorInt, int whiteThreshold) {
        final Color color = new Color(colorInt);
        if (color.getRed() + color.getGreen() + color.getBlue() <= whiteThreshold) {
            return 1;
        }
        return 0;
    }
}



3、EmobileLdMonitor.class

import net.sourceforge.tess4j.*;
import org.bytedeco.javacpp.BytePointer;
import org.bytedeco.javacpp.lept;
import org.bytedeco.javacpp.tesseract;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.List;

import static org.bytedeco.javacpp.lept.pixDestroy;
import static org.bytedeco.javacpp.lept.pixRead;


/**
 * @author ZhaoXu
 * @date 2021/11/24 16:27
 */
public class EmobileLdMonitor {
    static String language = "chi_sim";
    final static Logger LOGGER = LoggerFactory.getLogger(EmobileLdMonitor.class);
    static int pictureLength = 600;
    static int pictureHeight = 568;
    static int atX;
    static int atY;
    static String langPath = "src/main/resources/tessdata";
    static String imageUrl = "src/main/resources/screens/test.png";
    static String ldName = "陈小龙";

    public static void main(String[] args) throws Exception {
        Robot robot = new Robot();
        // 获取屏幕的尺寸
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        int width = (int) (screenSize.getWidth() / 1);
        int height = (int) (screenSize.getHeight() / 1);
        atX = width - 235;
        atY = height - 185;
        while (true) {
            EmobileLdMonitor.screen();
//            String ocr = ocrTesseractOCR();
            List<Word> words = ocrTess4j();
            words.forEach(word -> {
                System.out.print(word.getText());
                int x = word.getBoundingBox().x;
                int y = word.getBoundingBox().y;
                if (ldName.contains(word.getText())) {
                    robot.mouseMove(atX + 1, atY + 1);
                    //按下和释放鼠标左键,选定工程
                    robot.mousePress(KeyEvent.BUTTON1_MASK);
                    robot.mouseRelease(KeyEvent.BUTTON1_MASK);
                }
            });
            System.out.println();
            Thread.sleep(3000);
        }
    }

    /**
     * 识别图片中的中文
     *
     * @return
     * @throws TesseractException
     * @throws IOException
     */
    public static List<Word> ocrTess4j() throws TesseractException, IOException {
        ITesseract instance = new Tesseract();
        // 指定为中文识别
        instance.setLanguage(language);
        // 指定训练数据集合的路径
        instance.setDatapath(langPath);
        instance.setOcrEngineMode(1);
        instance.setTessVariable("user_defined_dpi", "1080");
        // 指定识别图片
        File imgDir = new File(imageUrl);
        BufferedImage bufferedImage = ImageIO.read(imgDir);
        int level = ITessAPI.TessPageIteratorLevel.RIL_SYMBOL;
//        String s = instance.doOCR(imgDir);
        List<Word> result = instance.getWords(bufferedImage, level);
        for (int i = 0; i < result.size(); i++) {
            Word word = result.get(i);
            Rectangle boundingBox = word.getBoundingBox();
            int x = boundingBox.x;
            int y = boundingBox.y;
        }
        return result;
    }

    /**
     * 识别图片中的中文 TesseractOCR
     *
     * @return
     * @throws TesseractException
     * @throws IOException
     */
    public static String ocrTesseractOCR() throws IOException {
        //创建字节容器。
        BytePointer outtext;
        //启动识别器
        tesseract.TessBaseAPI ocrapi = new tesseract.TessBaseAPI();
        //初始化识别器的语言包
        if (ocrapi.Init(langPath, language) != 0) {
            System.out.println("Could not initialize tesseract");
            return null;
        }
        //读取源图片
        lept.PIX image = pixRead(imageUrl);
        //识别器装入图片
        ocrapi.SetImage(image);
        ocrapi.set_min_orientation_margin(1.0);
        //识别器识别进行段。
        outtext = ocrapi.GetUTF8Text();
        try {
            return outtext.getString("utf-8");
        } finally {
            //最后释放资源
            ocrapi.End();
            outtext.deallocate();
            pixDestroy(image);
        }
    }

    /**
     * 截屏幕,右下角
     *
     * @throws IOException
     * @throws AWTException
     */
    public static void screen() throws Exception {

        // 截取屏幕
        BufferedImage textImage = new Robot().createScreenCapture(new Rectangle(atX, atY, 150, 150));
//        BufferedImage textImage = new Robot().createScreenCapture(new Rectangle(screenSize));

        textImage = ImageUtil.grayImage(textImage);
        textImage = ImageUtil.binaryImage(textImage);
        textImage = ImageUtil.denoise(textImage);

        // 设置日期格式,作为目录名
        DateFormat dfDirectory = new SimpleDateFormat("yyyyMMdd");
        // 创建一个用于保存图片的文件夹
        File screenCaptureDirectory = new File("src/main/resources/screens");
        if (!screenCaptureDirectory.exists()) {
            screenCaptureDirectory.mkdirs();
            System.out.println("The directory " + screenCaptureDirectory.getName() + " is created.");
        }

        // 设置日期格式,作为图片名
        DateFormat dfImageName = new SimpleDateFormat("yyyyMMddhhmmss");
        // 指定路径,并以特定的日期格式作为图片的名称
        File imageFile = new File(screenCaptureDirectory, ("test.png"));

        // 以指定的图片格式将截取的图片写到指定的文件
        ImageIO.write(textImage, "png", imageFile);
        ImageUtil.reduceImg(imageUrl, pictureLength, pictureHeight);


        // 自动打开图片
//        if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.OPEN)) {
//            Desktop.getDesktop().open(imageFile);
//        }
    }
}



版权声明:本文为qq_39898191原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。