草庐IT

Java的开源文字识别Tess4j与Tesseract-OCR

郑学学 2023-09-02 原文

提示:本文中部分内容图片节选自互联网,无意冒犯。如有侵权请私信联系作者即可删除、更改。

原因

由于项目需要,要求项目可以识别简单的图片,客户不想使用付费的大厂接口,于是我在查看资料后决定使用Tesseract-OCR,因为Tesseract-OCR可以在特定场景下训练语言识别提高正确率。但是在配置和使用过程中遇到各式各样的错误,经过一天的探索终于完成了Tesseract-OCR接口的基本使用。
本文在旨在使读者能够掌握Tesseract-OCR并能使用Java代码进行简单的图像文字识别,以项目实战为例展示Tesseract-OCR的使用。以下是项目运行的识别结果(有点不准确,因为这是官网的语言包没有经过训练。所以识别正确率不是太高,语言识别训练可以观看我的下一篇文章,这篇文章主要讲解Tesseract-OCR的配置事项)


项目搭建过程:

Tesseract-OCR 是一款开源OCR引擎,由Google维护。相比于其他的开源OCR来说Tesseract-OCR 的好处就是可以通过场景训练语言库提高识别效率。Tesseract-OCR 可以集成多种语言进行图像识别、文字提取等操作。
Java使用Tesseract是通过Tess4j作为桥梁进行调用的。所以Java要使用Tesseract进行OCR识别,需要使用Tess4j作为Jar包调用Tesseract-ocr的语言库。

Tesseract-ocr是安装包,Tess4j是Java调用Tesseract进行识别的jar包。如果只是单纯使用Java调用OCR不牵扯语言训练的话本机无需安装Tesseract-ocr.exe。只需要下载搭建Tesseract-ocr的语言包,并在项目中导入Tess4依赖即可运行,当然识别效果不太好。但是本章节主要讲解Tess4j的项目配置。具体使用Tesseract-ocr并进行语言训练的请参考我的本专栏下另一篇文章Tesseract-OCR 配置与语言训练。

下边是Java调用Tess4j 的步骤:

  1. 下载Tesseract语言包,解压到本地目录,并在项目中配置语言包运行测试。
  2. 下载Tess4j的Demo,并使用其中的Jar包对自己的项目进行配置。

注意:一定要使用官方Demo中的jar进行配置,因为自己搭建环境可能导致Jar的版本冲突导致各的错误。本人曾亲身经历各种麻烦。

详细的使用步骤如下:

  1. 进入Tesseract的GitHub官网进行语言包下载

    点击图片中的高亮的Download ZIP会下载语言包的压缩文件,将下载好的压缩文件放入磁盘的根目录下,如本例中解压到E盘根目录下:

  2. 登录Tess4j官网下载最新的Tess4j Demo(点击前边的Tess4j Demo文字即可跳转目的地。Tess4j网站语言包下载页面:https://sourceforge.net/projects/tess4j/)
    点击Download页面会出现下载等待的提示,等待一会浏览器就会下载,将下载后的文件夹解压缩后文件的目录结构如下:

    你需要做的就是新建一个Java项目并将,上图中高亮的dist和lib文件夹中的所有jar文件复制到项目中的lib文件夹中并添加到项目依赖,新建的项目如下:

这个项目的页面自己使用Swing做的一个能类似于QQ进行划区域截图,并对提取文字的小工具,工具能在后台运行并通过监听window快捷键进行划区域截图完成文字提取,并将识别得文字自动复制到剪贴板。想要此工具源码和源码解析的小伙伴请参考本专栏的另一篇文章:java工具OCR。工具的运行界面如下:

  1. 创建测试类Test,代码如下:
public class Test {
    public static void main(String[] args) throws TesseractException {
        ITesseract instance = new Tesseract();
        //指定语言包的位置就是步骤1中解压的语言包路径
        instance.setDatapath("E:\\tessdata");
        // 我们需要指定识别语种+代表使用多语言识别
        instance.setLanguage("eng+chi_sim");
        // 指定识别图片
        File imgDir = new File("d:\\001.jpg");
        String ocrResult = instance.doOCR(imgDir);
        // 输出识别结果
        System.out.println(ocrResult);
    }
}

运行即可。

运行中出现的问题

如果运行中出现如下错误:

Failed loading language ‘eng’ Tesseract couldn’t load any languages!
Exception in thread “main” java.lang.Error: Invalid memory access

是自己的语言包位置没有导入,请检查setDatapath();方法传入的路径是否与自己的语言路径一至。
如运行中出现如下错误:

Unable to load library ‘libtesseract351’: ÕҲ»µ½ָ¶¨

类似于这种得错误是tess4j中得libtesseract3051.dll文件没有被正确加载,这种情况就比较复杂了,这个文件是Java通过JNI调用其他语言得接口,一般在运行项目时Tess4j会将其另存在另一个存储目录由Java调用。出现调用不了得情况有可能是Java项目配置得Jar不对(所以要严格使用官网得jar包),也有可能是libtesseract3051.dll的文件路径不对(文件路径不对可以对源码调试,不过一般不是这种情况)。

如果使用中还有其他问题欢迎私信我,一起探讨解决。

有关Java的开源文字识别Tess4j与Tesseract-OCR的更多相关文章

  1. ruby - 如何使用文字标量样式在 YAML 中转储字符串? - 2

    我有一大串格式化数据(例如JSON),我想使用Psychinruby​​同时保留格式转储到YAML。基本上,我希望JSON使用literalstyle出现在YAML中:---json:|{"page":1,"results":["item","another"],"total_pages":0}但是,当我使用YAML.dump时,它不使用文字样式。我得到这样的东西:---json:!"{\n\"page\":1,\n\"results\":[\n\"item\",\"another\"\n],\n\"total_pages\":0\n}\n"我如何告诉Psych以想要的样式转储标量?解

  2. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  3. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  4. ruby - 字符串文字中的转义状态作为 `String#tr` 的参数 - 2

    对于作为String#tr参数的单引号字符串文字中反斜杠的转义状态,我觉得有些神秘。你能解释一下下面三个例子之间的对比吗?我特别不明白第二个。为了避免复杂化,我在这里使用了'd',在双引号中转义时不会改变含义("\d"="d")。'\\'.tr('\\','x')#=>"x"'\\'.tr('\\d','x')#=>"\\"'\\'.tr('\\\d','x')#=>"x" 最佳答案 在tr中转义tr的第一个参数非常类似于正则表达式中的括号字符分组。您可以在表达式的开头使用^来否定匹配(替换任何不匹配的内容)并使用例如a-f来匹配一

  5. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  6. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  7. Observability:从零开始创建 Java 微服务并监控它 (二) - 2

    这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/

  8. 【Java 面试合集】HashMap中为什么引入红黑树,而不是AVL树呢 - 2

    HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候

  9. 【Java入门】使用Java实现文件夹的遍历 - 2

    遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg

  10. java - 为什么 ruby​​ modulo 与 java/other lang 不同? - 2

    我基本上来自Java背景并且努力理解Ruby中的模运算。(5%3)(-5%3)(5%-3)(-5%-3)Java中的上述操作产生,2个-22个-2但在Ruby中,相同的表达式会产生21个-1-2.Ruby在逻辑上有多擅长这个?模块操作在Ruby中是如何实现的?如果将同一个操作定义为一个web服务,两个服务如何匹配逻辑。 最佳答案 在Java中,模运算的结果与被除数的符号相同。在Ruby中,它与除数的符号相同。remainder()在Ruby中与被除数的符号相同。您可能还想引用modulooperation.

随机推荐