美文网首页
Tesseract做图片验证码识别

Tesseract做图片验证码识别

作者: Joshua1919 | 来源:发表于2017-12-28 09:40 被阅读0次

    linux下的安装参考这里

    转载请标明出处:https://www.jianshu.com/p/c9cd23ea84fa

    环境准备

    yum -y update
    yum -y install libstdc++ autoconf automake libtool autoconf-archive pkg-config gcc gcc-c++ make libjpeg-devel libpng-devel libtiff-devel zlib-devel

    安装leptonica这里下载

    tar -zvxf leptonica-1.74.4.tar.gz
    cd leptonica-1.74.4
    ./autobuild
    ./configure
    make
    make install

    安装tesseract这里下载

    unzip tesseract-master.zip
    cd tesseract-master
    (1)./autogen.sh
    (2)PKG_CONFIG_PATH=/usr/local/lib/pkgconfig LIBLEPT_HEADERSDIR=/usr/local/include ./configure –with-extra-includes=/usr/local/include –with-extra-libraries=/usr/local/lib
    (3)LDFLAGS=”-L/usr/local/lib” CFLAGS=”-I/usr/local/include” make
    (4)make install

    下载数据这里下载

    cd /usr/local/share/
    上传eng.traineddata

    到此就安装完成了。

    Windows下的安装

    windows上的安装就不介绍了,注意安装好了以后要添加环境变量:

    (1)path中添加:D:\Program Files (x86)\Tesseract-OCR\tessdata
    (2)新建TESSDATA_PREFIX:D:\Program Files (x86)\Tesseract-OCR\tessdata

    使用

    tesseract image1.jpg out –psm 7 -l eng

    image1.jpg:是输入文件名
    out:识别出来的文字存放在out.txt这个文件中
    -l:代表文字的类型,eng就是英文。
    –psm:代表不同的切割方式

    • 0 Orientation and script detection (OSD) only.
    • 1 Automatic page segmentation with OSD.
    • 2 Automatic page segmentation, but no OSD, or OCR.
    • 3 Fully automatic page segmentation, but no OSD. (Default)
    • 4 Assume a single column of text of variable sizes.
    • 5 Assume a single uniform block of vertically aligned text.
    • 6 Assume a single uniform block of text.
    • 7 Treat the image as a single text line.
    • 8 Treat the image as a single word.
    • 9 Treat the image as a single word in a circle.
    • 10 Treat the image as a single character.
    • 11 Sparse text. Find as much text as possible in no particular order.
    • 12 Sparse text with OSD.
    • 13 Raw line. Treat the image as a single text line, bypassing hacks that are Tesseract-specific.

    为了提高识别率可以做灰度化二值化等处理.

    JAVA代码如下

    public class OCRUtil {
        private static final String EOL = System.getProperty("line.separator");
        public static String recognizeText(byte[] image) throws Exception {
            //图片预处理,灰度化+二值化
            image = preHandleImage(image);
            //把字节数组保存到临时目录
            String tempDir=System.getProperty("java.io.tmpdir");
            String uuid = UUIDUtil.uuid();
            String tempFileName = uuid +".jpg";
            String resultFileName = uuid;
            File tempFile = new File(tempDir, tempFileName);
            File resultFile = new File(tempDir, resultFileName);
            IOUtil.saveInputStream(new ByteArrayInputStream(image), new FileOutputStream(tempFile));
            //生成操作系统命令
            List<String> cmd = new ArrayList<String>();
            if(OSUtil.isUnixLikeSystem()) {
                cmd.add("tesseract");
            }else {
                cmd.add("cmd");
                cmd.add("/c");
                cmd.add("tesseract.exe");
            }
            cmd.add(tempFile.getAbsolutePath());
            cmd.add(resultFile.getAbsolutePath());
            cmd.add("-l");
            cmd.add("eng");
            cmd.add("--psm");
            cmd.add("7");
            FileInputStream fin = null;
            BufferedReader in = null;
            try {
                //调用操作系統命令
                StringBuffer sb = new StringBuffer();
                ProcessBuilder pb = new ProcessBuilder();
                pb.directory(new File(tempDir));
                pb.command(cmd);
                pb.redirectErrorStream(true);
                Process process = pb.start();
                int w = process.waitFor();
                if (w == 0){// 0代表正常退出
                    fin = new FileInputStream(resultFile.getAbsolutePath() + ".txt");
                    in = new BufferedReader(new InputStreamReader(fin, "UTF-8"));
                    String str = null;
                    while ((str = in.readLine()) != null) {
                        sb.append(str).append(EOL);
                    }
                    return sb.toString().replaceAll("(?is)\\s+", "");
                } else {
                    String msg;
                    switch (w) {
                    case 1:
                        msg = "Errors accessing files. There may be spaces in your image's filename.";
                        break;
                    case 29:
                        msg = "Cannot recognize the image or its selected region.";
                        break;
                    case 31:
                        msg = "Unsupported image format.";
                        break;
                    default:
                        msg = "Errors occurred.";
                    }
                    throw new RuntimeException(msg);
                }
            }finally {
                IOUtil.close(in,fin);
                if(tempFile != null) {
                    tempFile.delete();
                }
                if(resultFile != null) {
                    resultFile.delete();
                    File file = new File(resultFile.getAbsolutePath()+".txt");
                    if(file!=null && file.exists()) {
                        file.delete();
                    }
                }
            }
        }
        public static byte[] preHandleImage(byte[] imgBytes) throws IOException {
            if(imgBytes == null) {
                return null;
            }
            BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(imgBytes));
            int h = bufferedImage.getHeight();
            int w = bufferedImage.getWidth();
            // 灰度化
            int[][] gray = new int[w][h];
            for (int x = 0; x < w; x++) {
                for (int y = 0; y < h; y++) {
                    int argb = bufferedImage.getRGB(x, y);
                    // 图像加亮(调整亮度识别率非常高)
                    int r = (int) (((argb >> 16) & 0xFF) * 1.1 + 30);
                    int g = (int) (((argb >> 8) & 0xFF) * 1.1 + 30);
                    int b = (int) (((argb >> 0) & 0xFF) * 1.1 + 30);
                    if (r >= 255) {
                        r = 255;
                    }
                    if (g >= 255) {
                        g = 255;
                    }
                    if (b >= 255) {
                        b = 255;
                    }
                    gray[x][y] = (int) Math.pow(
                            (Math.pow(r, 2.2) * 0.2973 + Math.pow(g, 2.2) * 0.6274 + Math.pow(b, 2.2) * 0.0753), 1 / 2.2);
                }
            }
            // 二值化
            int threshold = ostu(gray, w, h);
            BufferedImage binaryBufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY);
            for (int x = 0; x < w; x++) {
                for (int y = 0; y < h; y++) {
                    if (gray[x][y] > threshold) {
                        gray[x][y] |= 0x00FFFF;
                    } else {
                        gray[x][y] &= 0xFF0000;
                    }
                    binaryBufferedImage.setRGB(x, y, gray[x][y]);
                }
            }
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ImageIO.write(binaryBufferedImage, "jpg", out);
            out.close();
            return out.toByteArray();
        }
        private static int ostu(int[][] gray, int w, int h) {
            int[] histData = new int[w * h];
            // Calculate histogram
            for (int x = 0; x < w; x++) {
                for (int y = 0; y < h; y++) {
                    int red = 0xFF & gray[x][y];
                    histData[red]++;
                }
            }
            // Total number of pixels
            int total = w * h;
            float sum = 0;
            for (int t = 0; t < 256; t++)sum += t * histData[t];
            float sumB = 0;
            int wB = 0;
            int wF = 0;
            float varMax = 0;
            int threshold = 0;
            for (int t = 0; t < 256; t++) {
                wB += histData[t]; // Weight Background
                if (wB == 0)    continue;
                wF = total - wB; // Weight Foreground
                if (wF == 0)    break;
                sumB += (float) (t * histData[t]);
                float mB = sumB / wB; // Mean Background
                float mF = (sum - sumB) / wF; // Mean Foreground
                // Calculate Between Class Variance
                float varBetween = (float) wB * (float) wF * (mB - mF) * (mB - mF);
                // Check if new maximum found
                if (varBetween > varMax) {
                    varMax = varBetween;
                    threshold = t;
                }
            }
            return threshold;
        }
    }
    

    相关文章

      网友评论

          本文标题:Tesseract做图片验证码识别

          本文链接:https://www.haomeiwen.com/subject/zotuuxtx.html