Tess4J简介
Tesseract-OCR支持中文识别,并且开源和提供全套的训练工具,是快速低成本开发的首选。而Tess4J则是Tesseract在Java PC上的应用。在英文和数字识别中性能还是不错的,但是在中文识别中,无论速度还是识别率还是较弱,建议有条件的话,针对场景进行训练,会获得较好结果。
项目地址:https://github.com/tesseract-ocr
语言包下载地址:https://github.com/tesseract-ocr/tessdata
Demo
下面附上我自己的测试过程:
(1)新建一个SpringBoot工程,我用的版本是2.5.10。
(2)后端相关类和配置:
1、引入pom.xml配置:
Maven依赖
<!-- ocr -->
<dependency>
<groupId>net.sourceforge.tess4j</groupId>
<artifactId>tess4j</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.11.0</version>
</dependency>
2、相关Utils工具类:
ImgFileUtils
package com.ocr.utils;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
public class ImgFileUtils {
/**
* 存为PNG格式
*/
public static void saveToFile(BufferedImage subimage, File file) throws IOException {
ImageIO.write(subimage, "png", file);
}
/**
* 存为PNG格式
*/
public static void saveAsPNG(BufferedImage subimage, File file) throws IOException {
ImageIO.write(subimage, "png", file);
}
/**
* 存为JPEG格式图像文件
*/
public static void saveAsJPEG(BufferedImage subimage, File file) throws IOException {
ImageIO.write(subimage, "JPEG", file);
}
/**
* 写入一个OutputStream
*/
public static void write(BufferedImage subimage, OutputStream out) throws IOException {
ImageIO.write(subimage, "png", out);
}
}
ImgUtils
package com.ocr.utils;
import java.awt.image.BufferedImage;
public class ImgUtils {
/**
* 裁剪图片:去掉黑边
*/
public static BufferedImage clipImage(BufferedImage srcImage) {
return srcImage.getSubimage(8, 5, srcImage.getWidth() - 20, srcImage.getHeight() - 10);
}
/**
* 灰度化
*/
public static BufferedImage grayImage(BufferedImage srcImage) {
return copyImage(srcImage, new BufferedImage(srcImage.getWidth(), srcImage.getHeight(), BufferedImage.TYPE_BYTE_GRAY));
}
/**
* 二值化
*/
public static BufferedImage binaryImage(BufferedImage srcImage) {
return copyImage(srcImage, new BufferedImage(srcImage.getWidth(), srcImage.getHeight(), BufferedImage.TYPE_BYTE_BINARY));
}
public static BufferedImage copyImage(BufferedImage srcImage, BufferedImage destImage) {
for (int y = 0; y < srcImage.getHeight(); y++) {
for (int x = 0; x < srcImage.getWidth(); x++) {
destImage.setRGB(x, y, srcImage.getRGB(x, y));
}
}
return destImage;
}
}
OCRUtils
package com.ocr.utils;
import net.sourceforge.tess4j.ITesseract;
import net.sourceforge.tess4j.Tesseract;
import java.awt.image.BufferedImage;
import java.io.File;
public class OCRUtils {
public static String DEFAULT_LANG="eng";
public static String DATA_PATH="D:/temp/test_data/";
/**
* 根据图片文件进行识别
*
* @param imageFile 图片文件
* @param lang 指定语言库
* @return 识别文本信息
*/
public static String doOCRFromFile(File imageFile,String lang) throws Exception {
ITesseract instance = new Tesseract();
instance.setDatapath(DATA_PATH); //指定语言库目录
instance.setTessVariable("user_defined_dpi", "300");
instance.setLanguage(lang);
String result = instance.doOCR(imageFile);
return result;
}
public static String doOCRFromFile(File imageFile) throws Exception {
return doOCRFromFile(imageFile,DEFAULT_LANG);
}
/**
* 根据图片流进行识别
*/
public static String doOCRFromImgBuffer(BufferedImage bufferedImage,String lang) throws Exception {
ITesseract instance = new Tesseract();
instance.setDatapath(DATA_PATH);
instance.setTessVariable("user_defined_dpi", "300");
instance.setLanguage(lang);
String result = instance.doOCR(bufferedImage);
return result;
}
public static String doOCRFromImgBuffer(BufferedImage bufferedImage) throws Exception {
return doOCRFromImgBuffer(bufferedImage,DEFAULT_LANG);
}
}
WindowsUtils
package com.ocr.utils;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.RECT;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
public class WindowsUtils {
/**
* 截图:指定屏幕区域
* 参数为截图左上角坐标(x1,y1)+右下角坐标(x2,y2)
*/
public static BufferedImage captureImg(int x1, int y1, int x2, int y2) throws Exception {
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Rectangle screenRectangle = new Rectangle(screenSize);
Robot robot = new Robot();
BufferedImage image = robot.createScreenCapture(screenRectangle);
BufferedImage subimage = image.getSubimage(x1, y1, x2, y2);
return subimage;
}
/**
* 截图:指定窗口(使用AWT)
*/
public static BufferedImage captureWindowAndActive(HWND hWnd) throws AWTException, IOException {
RECT r = new RECT();
Rectangle rect;
User32.INSTANCE.GetWindowRect(hWnd, r);
User32.INSTANCE.ShowWindow(hWnd, User32.INSTANCE.SW_SHOWNORMAL); //如果最小化,恢复显示
User32.INSTANCE.SetForegroundWindow(hWnd); //激活显示
rect = r.toRectangle();
Robot robot = new Robot();
BufferedImage image = robot.createScreenCapture(rect);
return image;
}
}
3、测试Demo
Demo
package com.ocr;
import com.ocr.utils.ImgFileUtils;
import com.ocr.utils.ImgUtils;
import com.ocr.utils.OCRUtils;
import com.ocr.utils.WindowsUtils;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef;
import java.io.File;
public class DemoOCR {
private static String WIN_TITLE="测试OCR.txt - 记事本";
private static String PICTURE_PATH = System.getProperty("user.dir")+"/picture";
/**
* 测试OCR:指定窗口截图&OCR识别
*/
public static void testCapture() throws Exception {
// 截图保存的路径
File imgFile = new File(PICTURE_PATH + "/capture.png");
if (!imgFile.getParentFile().exists()) {
imgFile.getParentFile().mkdirs();
}
// 第一个参数是Windows窗体的窗体类,第二个参数是窗体的标题。
WinDef.HWND hWnd = User32.INSTANCE.FindWindow(null, WIN_TITLE);
System.out.println("找到窗体:"+hWnd);
if(hWnd==null){
System.out.println("未找到窗口");
}else{
// 保存截图
ImgFileUtils.saveAsPNG(ImgUtils.clipImage(WindowsUtils.captureWindowAndActive(hWnd)), imgFile); //Active解决有些窗口截图不正常
//String ocrRs = OCRUtils.doOCRFromFile(imgFile);
String ocrRs = OCRUtils.doOCRFromImgBuffer(ImgUtils.clipImage(ImgUtils.grayImage(WindowsUtils.captureWindowAndActive(hWnd)))); // 灰化效果
System.out.println("识别窗体文本信息:"+ocrRs); //OCR识别,图像转文本。
}
}
/**
* main method
*/
public static void main(String[] args) {
System.out.println("OCR文字识别已启动!");
try {
//设置训练库的位置
OCRUtils.DATA_PATH=System.getProperty("user.dir")+"/config";
OCRUtils.DEFAULT_LANG="chi_sim"; //eng :英文 chi_sim :简体中文
//测试OCR:指定窗口截图&OCR识别
WIN_TITLE="测试OCR.txt - 记事本"; //用记事本打开测试文本
testCapture();
//测试识别图片
String ocrText = OCRUtils.doOCRFromFile(new File(PICTURE_PATH+"/capture1.png")); // 灰化效果
System.out.println("识别文本信息:"+ocrText); //OCR识别,图像转文本
} catch (Exception e) {
e.printStackTrace();
}
}
}
在项目根目录新建两个文件夹:
1.
2.
1.
picture
用于存放用于识别的图片;2.
config
用来存放你下载的语言包;