C++ - Tesseract 令人失望的性能

标签 c++ performance ocr tesseract

我所在的公司正在考虑将其当前的 OCR 引擎(Nuance 的 OmniPage)转换为开源替代方案,例如 Tesseract。

为了获得一些性能基准(执行速度和准确性)来比较两者,我得到了一个非常简单的程序,只是为了了解 Tesseract 3.2 C API 的性能如何。

我的初步观察(其中一些可能不正确,请随时在评论中更正我的解释):

  • 准确度很高。它与我们当前的引擎相比非常好。
  • 输出格式仅提供已识别的文本,而不是文本在原始图像中的位置的预览。 采用 hOCR 格式并将其转换为其他更具视觉吸引力的格式的可能性,但我未能在 Windows 上找到适合商业用途的开源转换器(我找不到来自 ExactCODE's hocr2pdf 的源代码或可执行文件)。我可以编写一个简单的脚本来转换检测到的每个段落的 bbox,并添加一个 style 元素来设置 left HTML 标签的右边widthheightposition 属性,所以这个限制很小。
  • Leptonica(Tesseract 使用的图像库)appears not to support reading complex PDF files .虽然这确实会为迁移增加一个小的开发开销(因为它不是开箱即用的),但这并不是什么大问题,因为我们的产品中已经有模块可以从 PDF 文件中提取图像。
  • 执行速度极慢(至少与 Nuance 的 OmniPage 相比)。 Tesseract 在我的机器上花费了 2 分钟多一点来转换这个问题末尾的文件。 Nuance 的 OmniPage 只需不到 3 分 30 秒就可以转换 10 个大型文档(包括提供的图像)。 (我不记得具体多长时间了,但显然仅提供的图像不到 15 秒)

如果仅考虑其他因素,迁移可能没有太大问题。然而,这种性能限制是致命的。

然后,我心想:与其商业同类产品相比,Tesseract 的性能怎么会这么差? Google 肯定会力求性能。

所以,我几乎可以肯定问题出在我身上。我要么没有以正确的方式使用 API,要么没有更改我应该更改的设置,要么我现在缺少的其他内容。

这是我的测试程序中与 Tesseract 相关的部分:

#include "baseapi.h"
#include "allheaders.h"

// ...
// Tesseract initialization
tesseract::TessBaseAPI api;
api.Init("", "eng+deu+fra");
api.SetPageSegMode(tesseract::PageSegMode::PSM_AUTO_OSD);
api.SetVariable("tessedit_create_hocr", "1"); // for the hOCR output

// ...
// OCR
PIX* pixs = pixRead(image_path.c_str());
STRING result;
api.ProcessPages(image_path.c_str(), NULL, 0, &result);

// ... write the result to a file

我尝试了不同的页面分割模式并且没有激活 hocr 格式的创建,结果和以前一样失望。我还尝试对图像应用一些预处理脚本,看看它是否对检测有一点帮助,但没有成功。为了测试目的,我只尝试了一本字典,但它对性能没有太大影响。我在处理多页 TIF 文件和单页 TIF 图像时也遇到了同样的性能问题,还没有尝试其他格式。

使用 VerySleepy 对应用程序进行快速分析表明,大部分执行时间花在了与边界框相关的 newdelete 上。

我真的希望我们迁移到开源库而不是商业产品,所以如果有人可以帮助我使用 API 实现更好的性能,我将不胜感激。除非我能够获得与当前引擎相似的性能结果的显着改进,否则迁移不会发生。

非常感谢您抽出宝贵的时间。

这是我的测试集的一张图片:

Sample OCR image

最佳答案

我认为您对此无能为力。没错,与 OmniPage 或 ABBYY 等商业引擎相比,Tesseact 非常慢。每个比较测试都表明了这一点。这些公司以从事 OCR 为生,并且非常重视速度、准确性和其他因素。

关于C++ - Tesseract 令人失望的性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17599728/

相关文章:

c++ - 为什么我需要在成员初始化列表中重复我的基类的模板参数?

c++ - # 符号作为 strcmp() 参数的含义

performance - 可根据应用程序级别指标扩展的一些应用程序用例是什么?

java - 了解 Fastutil 内部的资源

c# - 如何读取扫描支票的支票号码和银行路由号码

elasticsearch - 使用德语的简单Elasticsearch PDF文本搜索

c++ - 根据字符串中的索引在 C++ 中对字符串 vector 进行排序

c++ - 如何将目录符号链接(symbolic link)复制为指向目标的链接?

python - 从第三个数组中的两个数组中有效地获取每对元素的最小值

c# - 使用EmguCV从图像中检测文本区域