Tesseract:开源光学字符识别引擎

作者:Anthony Kay

我经常摆弄开源 OCR(光学字符识别)软件包。我上次尝试是在几年前,当时我买了一台平板电脑,想扫描一些课程书籍,这样上学时就可以只带一样东西。我尝试了我能找到的每一个软件包,但没有一个效果好到值得考虑使用。最终我使用了商业版的 Adobe Acrobat,它允许你使用扫描页作为视觉效果(保留数学书中的方程式等),但它对文本应用 OCR,这样你就可以搜索。结果证明它非常方便,我有点难过,因为我无法从开源产品中获得任何结果。

诚然,这个问题非常困难。字体变化、图像噪声和对齐问题使得设计一种能够可靠地将文本图像转换为实际文本的算法极其困难。

最近,我再次查找,发现了一个名为 Tesseract 的项目。Tesseract 是 20 世纪 80 年代末和 90 年代初惠普研究成果的产物。惠普和 UNLV 于 2005 年将其放在 SourceForge 上,目前正在迁移到 Google Code(见资源)。

它目前缺少诸如布局识别和多列支持等功能;然而,最困难的部分,即实际的字符识别,非常出色。

如何安装

在撰写本文时,1.03 版是最新版本,构建和安装过程仍然需要一些工作。此外,与 libtiff 的集成(这将允许您使用压缩 TIFF 作为输入)默认配置,但它无法正常工作。您可以尝试使用 libtiff 进行配置,因为这将允许压缩 TIFF 图像输入

# ./configure

如果您稍后发现它无法识别文本,请在不使用 libtiff 的情况下重新配置它

# ./configure --without-libtiff

构建按预期完成

# make

版本 1.03 的配置也表明make install已损坏。我设法通过反复试验弄清楚了安装的基本知识。

首先,将可执行文件从 ccmain/tesseract 复制到您路径中的目录(例如,/usr/local/bin)

# cp ccmain/tesseract /usr/local/bin

然后,将 tessdata 目录及其所有内容复制到与可执行文件相同的位置(例如,/usr/local/bin/tessdata/...)

# cp -r tessdata /usr/local/bin/tessdata

最后,确保您的 shell PATH 包括前者 (/usr/local/bin)。

如何使用

首先,您需要访问扫描仪或扫描页。Sane 在大多数 Linux 发行版中都可用,并且有一个名为 xsane 的漂亮 GUI 界面。(我在本文末尾附近会更详细地讨论扫描。)

Tesseract 没有布局分析,因此它无法检测多列格式或图形。此外,损坏的 libtiff 支持意味着它只能读取未压缩的 TIFF。这意味着您必须对扫描文档做一些工作才能获得最佳结果。幸运的是,这些步骤非常简单;最常见的步骤可以自动化,并且结果非常值得。

这是您需要做的

  1. 使用阈值函数来消除光照变化并将图像转换为黑白。

  2. 擦除任何图形或图像(可选,但如果您跳过此步骤,识别器将在这些区域给出大量乱码文本)。

  3. 将任何多列文本分解为更小的单列图像。

我建议使用图形程序,例如 GIMP,来感受需要做什么。最重要的一步是第一步,因为它将大大提高 OCR 的准确性。

GIMP 有一个很棒的功能,可以轻松消除除最坏情况外的所有光照变化。

首先,转到“图像”→“模式”菜单,并确保图像处于 RGB 或灰度模式。阈值处理不适用于索引图像。接下来,选择菜单“工具”→“颜色工具”→“阈值”。此工具允许您删除比指定截止值更亮的像素,并将所有其他像素转换为黑色。一个弹出窗口(图 1)允许您选择阈值。确保图像预览已打开,以便了解它如何影响图像。左右滑动阈值滑块以选择白色和黑色之间的截止点。您可能无法在不损坏文本的情况下消除所有不均匀的光照。为文本找到一个好看的结果,然后用绘画工具擦除其余的噪点。图 2 中从第一部分到第二部分的过渡显示了此步骤的典型结果。

Tesseract: an Open-Source Optical Character Recognition Engine

图 1. GIMP 中的阈值对话框。左右滑动三角形以选择哪些像素应为白色,哪些像素应为黑色。

您应该进行实验,并在调整阈值时放大图像的某个部分,以便您可以更近距离地看到像素级别。这使您可以更多地了解 Tesseract 将看到的内容,并让您更好地了解如何获得最佳结果。如果您无法识别字符,Tesseract 肯定也无法识别。

此页面有手写笔记、下划线和一部分光照,阈值无法在不损害图像其余部分的情况下消除。使用画笔涂抹任何易于修复的区域。我不建议在无关信息(图形、噪点等)与文本有一定距离的情况下花费太多时间;Tesseract 可能会插入一些乱码字符,但这些字符通常在文本编辑器中更快地修复。结果图像应看起来像图 2 的第三部分。

Tesseract: an Open-Source Optical Character Recognition Engine

图 2. 图像准备的放大视图,从左到右:原始扫描图像,应用阈值后的图像,以及应用阈值和一些手动清理后的图像。

现在,将图像切换到索引模式(使用菜单选择“图像”→“模式”→“索引”),然后选择黑白(一位调色板)。此外,确保抖动已关闭。将图像另存为未压缩的 TIFF 图像,您就可以进行识别了。

识别部分很容易

$ tesseract image.tif result

第三个参数是输出文件的基本名称。Tesseract 会自动添加 txt 扩展名,因此在本例中,识别的文本将位于 result.txt 中。

本例中的下划线最终显着影响了 OCR。一些行识别得相当好,但其中两行在处理后完全无法理解。这突出了在可能的情况下使用干净源的重要性。手动删除下划线大大提高了识别率,但这比简单地手动输入文本花费了更多时间。

Tesseract 的工作效果如何?

我当然想做一些实验,以便了解 Tesseract 的能力。我还想将这些结果与另一个开源 OCR 系统 ocrad 进行比较。

我首先运行了一些测试,以查看 Tesseract 的表现如何。我的初始测试拍摄了一个 200dpi 的屏幕截图,其中包含粗体和斜体字体。显然,屏幕截图完全没有任何物理扫描仪引入的噪声或错误。

Tesseract 表现完美,识别了 100% 的字符。它甚至空格也正确。不幸的是,ocrad 的表现不如人意。它遗漏了几个空格(导致单词错误地连接在一起),并且遗漏了几个字母。在完美输入的情况下,ocrad 的总体识别率为 95%。

接下来,我决定尝试一些压力测试,看看 Tesseract 在更不利的条件下表现如何。我曾使用 Adobe Acrobat 对扫描文档进行 OCR,它需要 150 DPI。它可以修复诸如变化的光照(就像我们之前在 GIMP 中所做的那样)和线性失真(例如,由于书本装订将纸张边缘从扫描仪上拉开)之类的问题。它还可以处理页面倾斜的情况,即页面在扫描仪平台上未对齐。

因此,我找到了一张 72dpi 的扫描图像,其中包含大多数这些缺陷。请注意,72dpi 仅为 Acrobat 甚至尝试使用的分辨率的一半。左边距是深灰色,并渗入到字母中,并且行的左边缘是弯曲的。原始图像未倾斜。

我尝试了未更改的图像,结果很差。然后我使用 GIMP 阈值处理来消除光照变化,并按上述方式保存它。我没有做任何事情来纠正弯曲的线条,也没有以任何方式提高 dpi。

令我惊讶的是,Tesseract 的识别率达到了 97%!许多错误是将 e 误认为 c(这在原始图像中对我来说很难区分),并且许多错误发生在最严重的线性失真区域附近。

接下来,我使用 GIMP 尽可能地旋转图像,而不会裁剪文本。这对应于有人在扫描仪上随意放置页面,而几乎不考虑对齐。令人惊讶的是,Tesseract 仍然达到了 96% 的识别率。事实上,旋转无意中帮助解决了线性失真问题,并且识别错误比以前更少聚集。

现在我很好奇 ocrad 的表现如何。它的表现不佳。事实上,它彻底失败了。ocrad 在最佳质量输入下的表现比 Tesseract 在最差质量输入下的表现还要差。结果和比较见表 1。

表 1. Tesseract 与 ocrad 结果

测试条件ocradTesseract
200dpi,非常干净,包括斜体/粗体95%100%
72dpi,黑白,干净0%97%
72dpi,轻微线性失真0%97%
72dpi,轻微线性失真,倾斜 2 度 0% 96%
获得最佳结果

上面的测试表明,我看到的 Acrobat 推荐输入非常合理。我建议以 150dpi 或更高的分辨率扫描您的文档。您也可以尝试将扫描仪设置为黑白模式;您扫描仪中的阈值例程实际上可能会比本文中描述的手动阈值处理提供更好的结果。

完美的对齐似乎不会显着影响识别率,但书本装订造成的失真似乎确实会引起一些小问题。许多专业的扫描公司会在可能的情况下从装订中移除页面。

自动化流程

GIMP 使您可以非常精细地控制图像编辑,但是如果您有持续的扫描环境和大量页面,您真的会希望尽可能地自动化图像清理。

我建议为此目的使用 Netpbm,最好是 10.34 或更高版本,因为这些版本带有更强大的阈值过滤器。不幸的是,这不被认为是超级稳定的版本,因此许多系统将具有较旧的版本。

如果您使用的是较旧的版本,您可以使用如下命令管道获得可接受的结果

$ tifftopnm < scanned_image.tif | \
  pamditherbw -threshold -value 0.8 | \
  pamtopnm | pnmtotiff > result.tif

这四个命令链将调色板减少为黑白,并将结果另存为未压缩的 TIFF 图像。传递给 pamditherbw 的 -value 参数的数字默认为 0.5,范围为 0 到 1,它对应于之前在 GIMP 中使用的滑块。在这种情况下,数字越大,图像越暗。

Netpbm 10.34 及更高版本包含更高级的阈值实用程序 pamthreshold,它可以更好地处理页面上光照变化的图像。在这种情况下,命令链将是

$ tifftopnm < scanned_image.tif | \
  pamthreshold -local=20x20 | \
  pamtopnm | pnmtotiff > result.tif

pamthreshold 的选项有多种替代方案。-local 选项允许您指定每个像素周围的矩形区域,以确定局部光照条件,从而尝试适应图像中不断变化的光照条件。您也可以尝试

$ tifftopnm < scanned_image.tif | \
  pamthreshold -threshold=0.8 | 
  pamtopnm | pnmtotiff > result.tif

以获得类似于旧抖动实用程序的结果。有关更多详细信息,请参阅 Netpbm 文档。

如果您的输入图像是 TIFF 以外的格式,您当然可以在管道中替换适当的 Netpbm 工具(例如 jpegtopnm)

$ jpegtopnm < scanned_image.jpg | \
  pamthreshold -threshold=0.8 | 
  pamtopnm | pnmtotiff > result.tif

Netpbm 还包括允许您剪切图像部分的实用程序。请注意,大多数多列格式在定位列方面非常一致,这意味着您也可以非常轻松地自动化多列文本的翻译。例如,如果您有一篇以 200dpi 扫描的双列文章,您可以使用 GIMP 找到列边界的 x 坐标。假设第一列大约从 200 开始到 700 结束,第二列从 800 开始到 1200 结束。您可以将以下内容添加到您的处理管道中

$ tifftopnm < input.tif | \
  pamcut -left 150 -right 750 | ...
  pnmtotiff > output_left.tif

$ tifftopnm < input.tif | \
  pamcut -left 750 -right 1250 | ...
  pnmtotiff > output_right.tif

并自动化列的提取。将组合放在带有某些循环的 shell 脚本中,您可以非常快速地处理大量页面。

总结

Tesseract 是一个简单的 OCR 引擎。构建过程有点古怪,并且该引擎需要一些附加功能(例如布局检测),但核心功能,即文本识别,比我从开源社区尝试过的任何其他功能都要好得多。使用扫描仪和一些图像工具(例如 GIMP 和 Netpbm)就可以轻松获得出色的识别率。

Tesseract 团队目前正在努力集成诸如布局分析和 GUI 界面之类的功能。看起来商业质量的开源 OCR 解决方案终于指日可待了。

Anthony Kay 一直是一名系统程序员、编程讲师、技术作家和应用程序开发人员。他目前是俄勒冈州尤金市俄勒冈大学的计算机科学研究生。

加载 Disqus 评论