Tess4J文字识别过程记录-未完成...
考虑到产品未来可能需要对图片中的文字进行识别分析,所以抽空我做了一点初步的尝试。暂且写下来做个记录吧。
选型
经过一番寻找,锁定了tesseract。tesseract是一个开源的OCR引擎,支持中文识别。Tess4J提供了tesseract面向java的api封装。
安装
使用tess4j必须先安装tesseract,我的系统环境是centos,可以很方便的使用yum安装。为了识别中文还需要安装中文datafile。
sudo yum install tesseract
sudo yum install tesseract-langpack-chi_sim.noarch //简体中文支持其他操作系统,需要参考tesseract的说明安装。
然后在java项目中,通过maven引入tess4j。目前3.x版本里最新的是3.4
<dependency>
<groupId>com.sun.media</groupId>
<artifactId>jai_imageio</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>net.sourceforge.tess4j</groupId>
<artifactId>tess4j</artifactId>
<version>3.4.0</version>
</dependency>
测试
在word里用
微软雅黑 小四 加粗
写了一段文字 ,截成图片。说实话,考试难度已经很低了,真实场景很难有这么高质量的图片参考官网的示例源码写了测试代码。在这段测试代码里分别用了三种处理方式:第一个println方法打印的是官网的示例源码,直接doOCR的结果,第二个println方法是做了二值化处理后,再doOCR的结果,第三个println是截取一小块再doOCR的结果。后来还尝试过把png格式转成tiff格式再识别,识别率没有变化。
import net.sourceforge.tess4j.ITesseract;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.util.ImageHelper;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
/**
* @author fang
* @creatdate 17-8-2
*/
public class TesseractExample {
public static void main(String[] args) {
//读取图片
File imageFile = new File("/home/fang/img/test4.png");
ITesseract instance = new Tesseract(); // JNA Interface Mapping
instance.setDatapath("/usr/share/tesseract/tessdata"); //必须设置,或者写到环境变量里
//instance.setPageSegMode(1); //识别分页的模式,在我们这里用不到
instance.setOcrEngineMode(0); //这个应该就是默认值,可以不设置
instance.setLanguage("chi_sim+eng"); //中英文混检
try {
String result = instance.doOCR(imageFile);
System.out.println(result);
System.out.println("----------------------");
//二值化
BufferedImage grayImage = ImageHelper.convertImageToBinary(ImageIO.read(imageFile));
ImageIO.write(grayImage, "png", new File("/home/fang/img/", "test41.png"));
File imageFile2 = new File("/home/fang/img/test41.png");
String result2 = instance.doOCR(imageFile2);
System.out.println(result2);
System.out.println("----------------------");
//截取一小块
Rectangle rectangle = new Rectangle(0, 0, 100, 20);
String result3 = instance.doOCR(grayImage,rectangle)
.replace(" ",".").replace(",","");
System.out.println(result3);
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}结果很囧。
println 1
软(懦必然要变化的′变化是常态;有变化就需要堆护′随盲时间的惟移′维护
成本会远远超过才刃期开发的成本′占据成本的大头;因此′在钦件开发中′昌重
要的昌要馏氏维沪成本 雌护成本正比于系统的复茅篝呈度 所以要降低维护咸本 ′
系统的薏掰十就应当追求简单渲晰。 井println 2
软(懦必然要变化的′变化是常态;有变化就需要堆护′随盲时间的惟移′维护
成本会远远超过才刃期开发的成本′占据成本的大头;因此′在钦件开发中′昌重
要的昌要馏氏维沪成本 雌护成本正比于系统的复茅篝呈度 所以要降低维护咸本 ′
系统的薏掰十就应当追求简单渲晰。 \println 3
蜱(缘「皂必俩菩
识别率在70%左右。这个样本里全部都是中文,如果里面有英文,识别率会再降。不过,如果懂图像处理,比如把图像放大了再识别或者加粗,应该能提高识别率,或者找到自己应用场景下的样本去做训练。可以参考这篇文章。
结论
由于图像处理这方面毫无经验,另考虑到我们的业务场景不仅图像质量参差不齐,而且还有医生手写体…我基本断了使用开源的心思,下次找一些商业的OCR API来试一下。