专栏首页用户2442861的专栏Tesseract ocr文字识别

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 条评论
登录 后参与评论

相关文章

  • Java任务调度框架Quartz教程实例

    http://blog.csdn.net/yuebinghaoyuan/article/details/9045471

    bear_fish
  • python下载百度音乐

    我把百度音乐的网页代码稍微分析了一下,如果要求不高,下载普通音质的歌曲是不需要登陆的(当然如果你用浏览器打开下载的话,普通音质也是要求登陆下载的)

    bear_fish
  • java IO流之四 使用转换流InputStreamReader和OutputStreamWriter

    http://blog.csdn.net/a107494639/article/details/7586744

    bear_fish
  • Android 基于IntentService的文件下载的示例代码

    文件下载这种事情是很耗时的。之前使用AsyncTask这样的异步类来做下载,然后切到后台就被干掉。所以打算试试Service。(不过按目前那些系统的尿性,其实S...

    砸漏
  • Spark GenericUDF动态加载外部资源

    文章1中提到的动态加载外部资源,其实需要重启Spark任务才会生效。受到文章2启动,可以在数据中加入常量列,表示外部资源的地址,并作为UDF的参数(UDF不能输...

    mikeLiu
  • 微博订阅评论

    参考:http://open.weibo.com/wiki/%E7%A4%BA%E4%BE%8B%E4%BB%A3%E7%A0%81

    week
  • 语音识别 | Java 实现 AI 人工智能技术 - 语音识别功能

    说到语音识别、语音翻译、图像识别、人脸识别等等,现在已经非常非常非常普及了,看过‘最强大脑’的朋友,也应该对‘小度’这个机器人有所了解,战胜国际顶尖的‘大脑’-...

    码神联盟
  • xml与数据库中数据的导入导出

    这是我一个晚上做出来的,因为要去做其他的项目,所以只实现了对特定数据库的xml操作,不过我觉得这是学习xml挺不错的参考代码和文档

    SmileNicky
  • RocketMQ详解(10)——Consumer详解

    DefaultMQPushConsumer主要功能实现在DefaultMQPushConsumerImpl中,消息处理逻辑是在pullMessage()方法的P...

    张申傲
  • angular2 路由问题

    杭州前端工程师

扫码关注云+社区

领取腾讯云代金券