直接引用maven测试报错
主要原因是引入不了dll
java.lang.UnsatisfiedLinkError: 找不到指定的模块。
at com.sun.jna.Native.open(Native Method)
at com.sun.jna.NativeLibrary.loadLibrary(NativeLibrary.java:288)
at com.sun.jna.NativeLibrary.getInstance(NativeLibrary.java:427)
at com.sun.jna.Library$Handler.<init>(Library.java:179)
at com.sun.jna.Native.loadLibrary(Native.java:569)
at com.sun.jna.Native.loadLibrary(Native.java:544)
at net.sourceforge.tess4j.util.LoadLibs.getTessAPIInstance(LoadLibs.java:85)
at net.sourceforge.tess4j.TessAPI.<clinit>(TessAPI.java:42)
at net.sourceforge.tess4j.Tesseract.init(Tesseract.java:427)
at net.sourceforge.tess4j.Tesseract.doOCR(Tesseract.java:223)
at net.sourceforge.tess4j.Tesseract.doOCR(Tesseract.java:195)
at TestOcr.main(TestOcr.java:23)
官网
http://tess4j.sourceforge.net/
下载包
https://sourceforge.net/projects/tess4j/
下载解压后截图
lib 包下面有 libtesseract3051.dll
将这个文件放到 目录 C:\Windows\System32 下面
这是个老版本, 实际上应该安装
参考 https://blog.csdn.net/gs80140/article/details/103938651
安装后,使用java程序调用就可以了???
在Linux使用了3.4.8的版本报乱码, 换新版本试试, 新版本 411的也一样的问题
一堆问题, 跑通了得到的文字也是乱的, 没有的文字乱七八糟的文字都出来了, 但是使用原生的 Tesseract 命令行解析出来的文字就还可以, 一直处在奔溃的边缘,但是没有放弃, 看到了一个easyocr的项目
https://github.com/ushelp/EasyOCR
不过此项目已经找不到开源的代码了,号称很厉害, 于是搜索了以前的旧的代码
https://github.com/HighCWu/EasyOCR 这个是找回的历史版本, 在这个版本中看到了 maven依赖, 于是立即尝试
<dependency>
<groupId>cn.easyproject</groupId>
<artifactId>easyocr</artifactId>
<version>3.0.4-RELEASE</version>
</dependency>
<dependency>
<groupId>cn.easyproject</groupId>
<artifactId>easyocr-linkbold-plugin</artifactId>
<version>3.0.3-RELEASE</version>
</dependency>
参考代码
EasyOCR e=new EasyOCR();
//直接识别图片内容
System.out.println(e.discern("images/demo_eurotext.png"));
直接报错, 但是分析一下源码发现,原来这个项目也是使用的
下面的代码还没有尝试过, 下面的代码应该可以使用, 原理已经掌握, 就是调用命令嘛, 这个也是我期望的结果
EasyOCR ocr = new EasyOCR();
System.out.println("###### 中文会议通知内容识别 ######");
ocr.setAmendPath("amend_chi.txt"); // 中文识别修正
ocr.setLanguage(Language.CHI_SIM); // 中文语言
String res=ocr.discern("images/bank/notice.tif");
System.out.println(res);
System.out.println("###### 多语言混合识别 ######");
ocr.setLanguage(Language.multiLanguage(Language.ENG,Language.CHI_SIM)); // 多语言识别
String res2=ocr.discern("images/bank/bill2.tif");
System.out.println(res2);
System.out.println("###### 基于ETD模板的中文银行票据识别 ######");
ocr.setLanguage(Language.CHI_SIM); // 中文识别
ocr.setTextMode(TextMode.UNIFORM_TEXT); // 统一大小
List<String> res3=ocr.discernByTemplate("images/bank/bill3.jpg", "images/bank/bill.etd", ImageType.BILL_NORMAL);
System.out.println(res3);
System.out.println("###### 带图片的清理数字内容识别 ######");
ocr.setLanguage(Language.ENG); // 英文识别
ocr.setCharList("0123456789"); // 字符限定API
ocr.setTextMode(TextMode.SINGLE_LINE_TEXT); // 单行文本识别
String res4=ocr.discernAutoCleanImage("images/bank/example4.jpg",ImageType.TEXT_BOLD_BLAK);
System.out.println(res4);
经过上面的分析,开始写代码,直接调用命令, 这个命令的调用, windows机器,Linux机器分别安装最新版本的Tesseract并且确保在命令行里面能直接使用命令 tesseract ,语言包也相应放对位置即可
分享一下直接调用命令的程序, 再次感谢EasyOCR的启发, tess4j的乱码问题留待以后吧, 直接调用命令的效率还是挺快的, 比用tess4j快多了, 在windows机器上, 识别一个图片,tess4j要10几秒, 命令行1-2秒就出结果了,而且还不乱
@NacosValue("${tesseract.execute.dir}")
private String tesseractExecuteDir = "D:/data";
/**
* 此时本机要安装tesseract,并且放入path中,执行命令可以直接运行这个命令
* @return
*/
public String doTesseractOCR(byte[] bytes) throws Exception
{
//定义根目录
File execFolder = new File(tesseractExecuteDir);
String currentIndex = UUID.randomUUID().toString();
String imgName = currentIndex+".jpg";
File imageFile = new File(execFolder,imgName);
File resultFile = null;
try
{
//将bytes数组写入文件
FileImageOutputStream imageOutput = new FileImageOutputStream(imageFile);
imageOutput.write(bytes, 0, bytes.length);
imageOutput.close();
// 存放命令行参数的数组
List<String> cmd = new ArrayList<>();
ProcessBuilder pb = new ProcessBuilder();
pb.directory(execFolder);
cmd.add("tesseract");
cmd.add("-l");
cmd.add("chi_sim");
cmd.add(imgName);
cmd.add(currentIndex);
// 执行命令行
pb.command(cmd);
// 通知进程生成器是否合并标准错误和标准输出,把进程错误保存起来。
pb.redirectErrorStream(true);
// 开始执行进程
Process process = pb.start();
// 当前进程停止,直到process停止执行,返回执行结果.
int w = process.waitFor();
// 0代表正常退出
if (w == 0)
{
resultFile = new File(execFolder,currentIndex+".txt");
if(resultFile.exists())
{
return FileUtil.readUtf8String(resultFile);
}
}
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 accessing files. There may be wrong filename.错误码:"+w;
}
throw new Exception(msg);
}
}
finally {
FileUtil.del(imageFile);
FileUtil.del(resultFile);
}
return "";
}