Tesseract ocr文字识别

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/haluoluo211/article/details/77776697

前面很早做了图片的文字识别主要用到了开源框架Tesseract,当然做OCR之前先要定位图片文字。先上个图:

工作中项目组一般使用java因此代码,下面贴出java代码,最简单的图片识别:

package com.recognition;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.text.DecimalFormat;

import net.sourceforge.tess4j.*;
import org.bytedeco.javacpp.opencv_core.Mat;
import org.bytedeco.javacpp.opencv_core.Rect;

import static cv.skindetect.CvConvertHelper.matToImg;

/**
 * Created by DW_xiongyu on 2016/11/21.
 */
public class TesseractExample {

    public static String getRectWord(BufferedImage img, Rect rect) throws TesseractException {

        ITesseract instance = new Tesseract();  // JNA Interface Mapping
        String fontPath = "E:/char_recongition/Tesseract-OCR/tessdata";
        instance.setDatapath(fontPath);
        instance.setLanguage("chi_sim");

        long start = System.currentTimeMillis();
        Rectangle rectangle = new Rectangle(rect.x(), rect.y(), rect.width(), rect.height());
        String result = instance.doOCR(img, rectangle);
        long end = System.currentTimeMillis();


        DecimalFormat form = new DecimalFormat("0.00");
        //float xRatio = (float)rect.width() / img.getWidth();
        //float yRatio = (float)rect.height() / img.getHeight();
        //String strRatio = " xRatio " + form.format(xRatio) + " yRatio :" + form.format(yRatio);

        System.out.println(" result: " + result+" time consume :"+(float)(end-start)/1000 + "S");

        return result;
    }

    public static void main(String[] args) {
        String path = "F:/img_test/online_sample_img/10.jpg";


        File imageFile = new File(path);
        ITesseract instance = new Tesseract();  // JNA Interface Mapping

        try {
            String fontPath = "E:/char_recongition/Tesseract-OCR/tessdata";
            instance.setDatapath(fontPath);

            instance.setLanguage("chi_sim");

            long start = System.currentTimeMillis();
            String result = instance.doOCR(imageFile);
            long end = System.currentTimeMillis();
            System.out.println("Tesseract time consume :"+(float)(end-start)/1000 + "S");
            System.out.println(result);
        } catch (TesseractException e) {
            System.err.println(e.getMessage());
        }
    }
}

图片文字提取,原理相信会opencv的大致要看下结合上面的截图应该看得明白:

package cv.wordExtract;

import com.recognition.TesseractExample;
import com.thrift.ocrimg.DetectLetter;
import net.sourceforge.tess4j.TesseractException;
import org.apache.commons.collections.CollectionUtils;
import org.bytedeco.javacpp.opencv_core.Point;
import org.bytedeco.javacpp.opencv_core.Scalar;
import org.bytedeco.javacpp.opencv_core.MatVector;
import org.bytedeco.javacpp.opencv_core.Size;
import org.bytedeco.javacpp.opencv_core.Mat;
import org.bytedeco.javacpp.opencv_core.Rect;
import org.junit.Test;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

import static cv.skindetect.CvConvertHelper.imgToMat;
import static cv.skindetect.CvConvertHelper.matToImg;
import static org.bytedeco.javacpp.opencv_core.putText;
import static org.bytedeco.javacpp.opencv_core.FONT_HERSHEY_PLAIN;
import static org.bytedeco.javacpp.opencv_core.rectangle;
import static org.bytedeco.javacpp.opencv_highgui.*;
import static org.bytedeco.javacpp.opencv_imgproc.*;

/**
 * Created by DW_xiongyu on 2016/11/29.
 */
public class DetectLetters {

    //the minimum width and height of detected rect
    private final static int MIN_WH = 20;
    private final static int MINIMUM_AREA = 1000;
    private final static float HW_RATIO = 2.85F;
    //private final static double MINIMUM_AREA = 400;
    private final static int DETECT_COUNT_THREAD = 12;
    private final static boolean DEBUG = true;
    //private final static boolean DEBUG = false;
    private final static boolean SAVE = true;


    public List<Rect> getLetterRectLst(Mat srcMat, int i) throws IOException {
        List<Rect> rectList = new LinkedList<Rect>();

        Mat matGray = new Mat();
        cvtColor(srcMat, matGray, COLOR_RGB2GRAY);

        if (DEBUG) {
            imshow("matGray", matGray);
        }

        Mat matSobel = new Mat();
        Sobel(matGray, matSobel, 0, 1, 0, 3, 1, 0, BORDER_DEFAULT);
        if (DEBUG) {
            imshow("matSobel", matSobel);
        }


        Mat matThreshold = new Mat();
        threshold(matSobel, matThreshold, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY);
        if (DEBUG) {
            imshow("matSobel2matThreshold", matThreshold);
        }

        Mat exElement = getStructuringElement(MORPH_RECT, new Size(17, 3));

        morphologyEx(matThreshold, matThreshold, CV_MOP_CLOSE, exElement);

        if(i > 0 && SAVE){
            String savePath = "F:/img_test/online_sample_img/extract_tmp/tmp/"+i+"mor.jpg";
            mat2ImgFile(matThreshold, savePath);
        }

        if (DEBUG) {
            imshow("matThreshold2morphologyEx", matThreshold);
        }
        //waitKey(0);

        MatVector matVector = new MatVector();
        findContours(matThreshold, matVector, RETR_EXTERNAL, CHAIN_APPROX_NONE);
        //findContours(matThreshold, matVector, RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

        MatVector matVectorCopy = new MatVector(matVector.size());
        int len = (int) matVector.size();
        Mat matTmp;
        for ( i = 0; i < len; i++) {
            matTmp = matVector.get(i);
            approxPolyDP(matTmp, matVectorCopy.get(i), 3, true);
            Rect appRect = boundingRect(matVectorCopy.get(i));
            if (isWordRect(appRect)) {
                rectList.add(appRect);
                //System.out.println("nomal area: "+ appRect.area());
                //System.out.println("min area: "+ minAreaRect(matVectorCopy.get(i)).boundingRect().area());
            }
        }

        return rectList;
    }

    public void mat2ImgFile(Mat mat, String path) throws IOException {
        BufferedImage image  = matToImg(mat);
        ImageIO.write(image, "jpg", new File(path));
    }


    public void doExtract(String path) throws TesseractException, IOException {

        Mat imgMat = imread(path);
        System.out.println(" width: " + imgMat.cols() + " height: " + imgMat.rows());
        BufferedImage img = matToImg(imgMat);
        System.out.println(" width: " + img.getWidth()+ " height: " + img.getHeight());

        List<Rect> lstRect = getLetterRectLst(imgMat, -1);
        if (CollectionUtils.isNotEmpty(lstRect)){
            int count = 1;
            StringBuffer stringBuf = new StringBuffer();
            for (Rect rect:lstRect){
                rectangle(imgMat, rect, new Scalar(0, 255, 0, 0),  3, 8, 0);
                putText(imgMat, String.valueOf(count), new Point(rect.x(), rect.y()), FONT_HERSHEY_PLAIN, 2.8, new Scalar(0,0,0, 0));
                System.out.print("num: " + String.valueOf(count++) + " ");
                String str = TesseractExample.getRectWord(img, rect);
                stringBuf.append(str);
            }
            System.out.print("recognition result: " + stringBuf.toString().replaceAll("\n", ""));
        }

        imshow("imgMat", imgMat);
        waitKey(0);
        destroyAllWindows();
    }


    public static void main(String[] args) throws TesseractException, IOException {
        DetectLetters detectLetters = new DetectLetters();

        String path = "F:/huaya.jpg";
        path = "F:/img_test/online_sample_img/53.jpg";
        detectLetters.doExtract(path);
    }
}

代码在个人github

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏HansBug's Lab

1648: [Usaco2006 Dec]Cow Picnic 奶牛野餐

1648: [Usaco2006 Dec]Cow Picnic 奶牛野餐 Time Limit: 5 Sec  Memory Limit: 64 MB Subm...

35070
来自专栏算法修养

HOJ 2091 Chess(三维简单DP)

Chess My Tags (Edit) Source : Univ. of Alberta Local Contest 1999.10.16 ...

380100
来自专栏ml

hduoj---Tempter of the Bone

Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 6553...

30060
来自专栏ml

hdu----(5047)Sawtooth(大数相乘+数学推导)

Sawtooth Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (...

31350
来自专栏码匠的流水账

reactor-netty的TcpClient如何往eventLoop提交task

本文主要研究一下reactor-netty的TcpClient如何往eventLoop提交task

51720
来自专栏WindCoder

Intro to Python Image Processing in Computational Photography

Computational photography is about enhancing the photographic process with compu...

18810
来自专栏ml

hdu 3172 Virtual Friends (映射并查集)

Virtual Friends Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32...

30380
来自专栏小樱的经验随笔

HDU 1010 Tempter of the Bone【DFS经典题+奇偶剪枝详解】

Tempter of the Bone Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 6553...

34140
来自专栏数据结构与算法

BZOJ 3053: The Closest M Points(K-D Tree)

17400
来自专栏深度学习与数据挖掘实战

Graph application with Python, Neo4j, Gephi & Linkurious.js

I love Python, and to celebrate Packt Python week, I’ve spent some time developi...

14420

扫码关注云+社区

领取腾讯云代金券