来自Dropbox的OCR最佳实践-利用机器学习和计算机视觉打造一个 OCR 解决方案

利用机器学习和计算机视觉打造一个 OCR 解决方案

本系列围绕着 Drobox 的移动端文档扫描仪的APP的开发:介绍了 OCR 技术的调研、生产系统研发、调优等技巧。

https://blogs.dropbox.com/tech/2017/04/creating-a-modern-ocr-pipeline-using-computer-vision-and-deep-learning/

http://a1a.in/developing-a-standard-ocr-pipeline-the-utilization-of-pc-imaginative-and-prescient-and-deep-discovering-out/

https://blogs.dropbox.com/tech/2016/08/fast-and-accurate-document-detection-for-scanning/

https://blogs.dropbox.com/tech/2016/08/fast-document-rectification-and-enhancement/

https://blogs.dropbox.com/tech/2016/10/improving-the-responsiveness-of-the-document-detector/

本文中我们会给大家介绍我们如何为移动端的文档扫描仪构建宇宙领先的 OCR 系统的全过程。我们用到了计算机视觉和诸如LSTM 、CTC、CNN、等深度学习技术。另外,我们还将介绍怎么样让 OCR 系统实实在在的运用到 Drobox 这样量级的生产系统中去。

在前一篇文章中我们介绍了 Drobox 的移动端文档扫描仪的原理。移动端文档扫描仪使得你通过智能手机拍照,然后就可以扫描收据、发票等文档。我们的文档扫描仪只能输出图片,图片中的任何文字对于计算机来说都只是一些像素点,不能复制-黏贴,搜索或者其他针对文本的一些处理动作。

因此就需要用到OCR。这个过程会从我们扫描得到的文档图片中提取准确的文字。一旦OCR系统运行起来,Dropbox Business 用户就能拥有如下特性:

提取扫描件中的所有文本,并对其进行索引,后面你就能检索的到

保存成 pdf,然后你可以从中复制粘贴文本

我们在构建第一版移动文档扫描仪的时候,为了完成产品验证,在自己创建基于机器学习的OCR系统之前,我们使用了一款商用的OCR库。也就是说要把商用软件和我们的扫描流程整合起来,提供上面的两大特性给我们的business user,看看他们是否能够从OCR 之中得到帮助。对于移动扫描仪和OCR来说,一旦我们确认了的确存在很强烈的用户需求,出于以下原因,我们便着手开始开发自己的 OCR 系统。

首先,是基于成本的考虑:由于商用OCR是根据扫描数量进行收费,自研的 OCR 系统会给我们剩下一大笔费用。

其次,商用的OCR系统是根据平板扫描仪所针对的传统图像进行调优的,而我们的场景则更为复杂,因为智能手机拍照更加不受限制,会存在很多卷曲和不平整、带阴影的光线不均匀和模糊以及反光的文档图片。

因此,我们需要对识别准确率进行提升。

事实上,计算机视觉领域所发生的翻天覆地的变化给我们带来了契机。以往来说,OCR系统是严重依赖人为构建和调优的模块,其中预设很多前置条件都满足的情况下,针对平板扫描仪所采集的文档图片。比如,其中一个模块用于检测文本行,下一个模块用于检测文本行中的单字并进行切分,另外一个模块用于对单个字符/单字采用多种不同技术进行识别。大多数方法在前期依赖输入图像二值化后的结果,而二值化过程难以控制,会遗漏一些重要的细节。构建这些 OCR 系统是非常专业化,非常费时劳力的,这些系统也只能处理那些平板扫描仪所采集的有限范围内的文档图片。

过去的几十年里,深度学习技术已经被应用到计算机视觉的诸多领域,对于我们来说,构建 OCR 系统的时候可以利用很多新工具,无需重复以往繁复的依赖人力的过程,取而代之的,我们需要大量的数据让我们的系统能够自动学习到之前需要手动设计过程的特征。

可能最重要的原因是自研的系统我们自主权更大,我们可以在以后尝试更多创新的点。

大多数商用的机器学习项目包含如下三个步骤:

调研、搭建原型看看是否靠谱

将1中得到的模型产品化,提供给实际的终端用户。

对上线的系统进行优化

我们按照这三个顺序进行介绍

1

调研&&原型

一开始我们的目标是看看能不能搭出来一个 state of art 的 OCR 系统。

首先要收集一些具有代表性的文档图片,主要是用户可能会上传的一些收据、发票和信件等。为了收集到这些数据,我们询问了一小部分用户是否愿意捐献一些他们的文件图片用于我们测试算法。Dropbox对用户隐私十分重视,也就是说用户捐不捐是完全自主的,如果捐献的话,文件本身会进行安全和隐私处理。比如,永远不会对捐献的数据进行本地化存储,记录审计日志,严格限制访问授权等等。

另外一块对于机器学习来说 就是对数据的标注。当今大多数机器学习技术都是有监督学习,也就是说需要明确的手动标注的数据,这样算法才能自己学习来进行预测。一般来说,标注工作是外包出去的,比如Amazon’s Mechanical Turk (MTurk). 但使用这样的平台有个缺点,标注人员可以看到数据,但我们不希望标注人员看到用户捐献的数据。

因此,我们为这些捐献的数据搭建了自己的标注平台,取名为DropTurk,这个平台既可以把标注任务提交到 MTurk,也可以分发给我们雇的一小撮专门标注用户捐献数据的人员。我们和这些标注人员都签订了极为严格的NDA来保证他们不会也不能保留或者分享他们所要进行标注的任何数据。DropTurk 中有一些标注任务UI模板,我们可以针对不同的数据集、标注任务快速组合,这样子标注速度会尤为快速。

比如,如下图所示的 UI 中,要对每个单词的图片进行标注,标注人员要完成以下几项:

誊写图片中真实的文字

标记是否单词朝向是否不正确

标记文本是不是英文

标记是不是看不清楚还是没有文字

DropTurk系统中包含了dashboard,你可以查看既往标注任务的概况,当下进行的标注任务的进展,安全的获取标注结果。另外,我们可以对标注人员效率进行评估,甚至于监控到个体当下正在标注的任务,这样子就可以及时了解一些潜在的问题:

利用DropTurk,我们收集了一个单词级别的数据集,其中包含了每个单词以及其标注文本的图片数据集,同时也得到了一个文档级别的数据集,其中包含了文档的图片以及全部的文本。我们利用文档图像数据集对已有的 state-of-art的 OCR系统进行了评估,这样子在自研的时候,我们就可以知道自己的目标该怎么设置。

针对这个数据集,我们期望准确率达到95%.首要的任务是确认是否OCR的问题是一个合理时间内可以解决的问题。我们把OCR的问题分成两部分来看待。第一部分首先使用计算机视觉的技术将文档图片切割成文本行、单字,也就是说做一个 Word Detector;另一部分是将每个词的图片喂给一个深度网络从而得到实际的文字,我们称之为 Word Deep Net

Word Deep Net

Word Deep Net 整合了在计算机视觉和语音识别系统中用到的神经网络架构。切割好的单词图片喂给 Convolutional Neural Net (CNN) with several convolutional layers.CNN提取到的特征再以sequence的形式喂给a Bidirectional LSTM (Long Short Term Memory),最后利用Connectionist Temporal Classification (CTC) 层来做文本预测。

一旦我们选定使用这样的网络结构来实现单词图片到文本的转换,我们就需要分析怎么样才能拿到用于训练这个网络的数据 。深度学习系统需要巨量的数据来达到一个比较好的识别效果。事实上,眼下的此类系统训练数据的规模是最主要的瓶颈。一般来说都需要人工采集和标注此类数据,是一个耗时耗力又烧钱的过程。

另外一种选择是人工合成训练数据。但对于大多数计算机视觉要解决的问题来说,很难合成用于训练算法的接近真实数据的训练数据。要想有效的模仿真实世界中图片环境的多样性和多变性是很困难的。但针对我们自己的OCR场景则是很适合使用人工合成训练数据的,因为与自然场景的对象或者大多数人造的对象不同,我们所要合成的文档图片范围有限,单词的范围多样性也是很有限的。

我们的合成数据流程包含三部分:

单词词表

字体集

几何、光学变换来仿真真实世界

合成算法随机从其中选择一个来生成训练样本。

单词词表是利用 Project Gutenberg 上的电子书整理得到的,收集了大约1000种字体,加上旋转、下划线和模糊等失真手段。最终生成了大约100万单词图片,训练得到的模型然后进行准确性测试,最终大概在 79%,不太理想,但也还行。

通过多轮迭代,我们对利用合成数据的流程每个环节进行了改进以提高识别正确率。比如:

观察发现收据的效果很一般,在词表中增加了Uniform Product Code (UPC) database中的词,比如 “24QT TISSUE PAPER”

观察发现我们的网络没法很好的处理那些断开的字符。也就是说:那些打印的时候选取 thermal font出来的收据,通过会存在斑点、断开以及墨水覆盖的字符,但我们的网络训练的时候遇到的都是一些连接很完整的(比如激光打印机)、lightly bit-mapped characters (截屏的图片)。为了解决这个问题,我们联系到一家供应商,愿意给我们一种极具代表性的古老的 thermal printer fonts.

期初我们选择的字体的过程过于天真。最终我们人工选定了其中2000种字体。并没有平等的对待所有字体。于是我们研究了最常用的50种字体,并对字体使用的频率进行了记录,这样子常用字体采样频率会更高,也不会拉下那些比较罕见的字体。另外,其中一些字体的符号用错了,变成了方框,或者大小写错了。我们不得不人肉过了一遍这2000种字体,保证我们没有把错误的符号、数字、框喂给我们的网络。

将 Word Detector 调优至 高召回低精度。这样子就不会错过任何可能是文本的情况。对于识别网络来说,就需要处理很多只是噪声的空白图片。这样我们在训练数据中就加入了一些空白图片,比如常见的文字纹理背景, like wood, marble countertops。

从合成的单词直方图我们发现一些符号的数量远远不足,比如 / or &. 然后人工对这些字符出现频率进行了调整,比如合成了一些 dates, prices, URLs, etc.

新增了很多转换手段,比如 warping, fake shadows, and fake creases, and much more.

数据对于最终的模型至关重要,所以我们花费了大量的时间对数据合成过程进行了优化。后续我们会开放这部分源代码,供大家训练和测试自己的系统之用。

我们利用 Amazon EC2 G2 GPU instances 训练我们的网络模型,并行的做很多实验。所有实验代码都归结在一份notebook中,其中包含了重现实验的所有内容。比如用 git hash 来控制所用到的代码,S3中保存合成的数据集、结果、评估结果、图形以及实验目标的概述。

在合成数据,训练模型的过程中,我们会造了一些轮子,比如可视化字体的工具,调试网络预测结果的工具等等

早期实验的时候,我们记录了 Deep word net 处理 单个单词图片的结果怎么样,我们称之为SWA 单词准确率。准确指的是网络识别出多少个单词。另外,我们也记录了网络的 precision and recall 。

注:

精确率/准确率(Precision)是指在所有系统判定的“真”的样本中,确实是真的的占比,就是TP/(TP+FP)。

召回率/查全率(Recall)是指在所有确实为真的样本中,被判为的“真”的占比,就是TP/(TP+FN)。

FPR(False Positive Rate),又被称为“Probability of False Alarm”,就是所有确实为“假”的样本中,被误判真的样本,或者FP/(FP+TN)

每周我们都记录实际的进展。我们将数据集分成好几类,比如 (receipts), , , 等,根据不同的分类计算每种分类对应的准确率和所有数据的准确率。下图是一开始我们的跑的一个 Word Detector和 Word Deep Net的效果,其实还蛮糟糕的 。

到了一定阶段我们合成数据的处理流程在我们的OCR 测试基线数据集上,SWA单字准确率达到了88-89%以上,我们认定这部分工作差不多了。于是收集了近2万张单词的真实图片(我们前面用了大概100万人工合成的单词图片),用这些真实图片对 Word Deep Net 进行调优。最后差不多 SWA 能达到95%左右。

这样子我们就形成了一个能处理单词图片的系统,但真正的 OCR 系统要处理的是整个文档的图片。下一步我们将重点关注文档级别的 Word Detector 单词检测

Word Detector

这里我们选择了非DL的方法。类似可选的方法主要是对象检测系统中使用的诸如RCNN, 用于检测定位猫猫狗狗的位置,大多数图片中对象实例数不超过5个。

但大多数文档中的字数不止几个,多大数百上千个。数量远超大多数基于神经网络的对象检测系统所能处理的数量级。我们并不能保证此类算法适用于我们的 OCR 系统。

另外一个考虑是传统的计算机视觉的方法所采用的特征检测方法更易于调试,神经网络的方法难于理解和解释。

最终我们选择了经典的图形学算法 Maximally Stable Extremal Regions (MSERs), 用了 OpenCV 库中的实现.

MSER 算法根据不同的权重/阈值寻找图片中的连通区域。也就是说检测图片中的区块,特别适合文本的检测。

注:更多可阅读

https://zhuanlan.zhihu.com/p/30602214

我们的 Word Detector首先检测图片中的 MSER 特征,然后将其整合起来形成单词检测和行数据检测,有一点需要注意的是我们的Deep Word net只吃固定大小的单词图片的输入。因此 word detector 有时候需要在一个检测框里包含多个单词,有时候单词太长又需要对单词进行切割。切割的信息需要在整个处理流程中进行传递,这样子才能对最终的结果进行整合。另外一点就是MSER 检测工具需要同时处理浅色文字背景很暗和深色文字浅色背景的图片。

Combined End-to-End System

一旦我们把 Word Detector 调优至一定程度,就可以把它与 Word Deep Net整合起来对整个文档图片而不是单词的图片进行测试。但当我们第一次跑完之后发现效果只有44%,非常糟糕。

主要原因是图片中空格和噪声产生的垃圾文本。有时候会把两个单词合并成一个,比如 “helloworld”, 或者将单词错误的切割开来,比如“wo rld”.

采用的解决方案是修改网络中的 CTC 层来给最终预测的文本输出一个置信度。然后根据置信度来进行相应处理:

假如置信度很高,保留预测结果

2.假如置信度很低,将预测结果过滤出来,提示可能存在噪声

3.如果不上不下,则对检测得到的单词区域进行各种不同转换,尝试合并或切割看看结果是不是能在牛津英语字典中找到

另外需要处理的一个点是前面提到的Word Deep Net需要固定大小的图片输入。也就是说一个单词的窗宽实际上可能会有多个单词或者只是一个很长单词的一部分。因此,我们用了一个叫 Wordinator的模块,它能够输出每个识别后单词的具体的bouding box 也就是上下左右的坐标位置。

例如下面的调试中你可以看到在使用 Wordinator之前我们检测到的单词bouding box

Wordinator 可以将一些bouding box 分成 单个单词的bouding box 比如“of” 和 “Engineering”。

最终,我们的系统可以运行了,我们利用1千万人工合成的数据,尽可能多次数的迭代来训练我们的模型,以期达到最好的效果。最终准确率、召回率都达到了 state of art的水准。

2

生产系统

这时候,我们有了Python 和Lua封装的 Torch 实现的原型,准确率已经达到了state of art的水准。但要最终完成一个用户可以使用的可靠性、性能、工程化还有很长一段距离。我们需要构建一个系统,能够支撑百万级的用户。另外还需要考虑无需破坏现有的使用商用 OCR SDK 的系统。

如下图所示是整个 OCR 生产系统的处理流程:

我们为不同的OCR 引擎(我们自研的还有商用的)创建了一层封装,采用了自研的Stormcrow.这样我们就无需对现有的服务百万用户的线上 OCR 系统进行调整即可引入新的处理流程。

同时我们也把基于 Torch 的模型迁移到TensorFlow 。原因主要有以下几点,其一是我们线上已经有标准化的 TensorFlow的系统,这样子易于我们模型的管理和部署。其二是倾向于Python而不是Lua,TensorFlow的Python库更加好用。

在新的处理流程中,移动端上传拍照扫描的文档图片到我们的异步队列中。当上传动作完成以后,我们将图片通过一个RPC调用发送给运行 OCR 服务的服务器集群。

OCR 服务用到了 OpenCV 和 Tensorflow,都是使用 C++ 编写的,依赖库也很复杂,因此安全是一个考虑因素。我们利用诸如 LXC, CGroups, Linux Namespaces, and Seccomp的技术实现 OCR 服务的隔离,容器之间通过IPC来交互。

这样的架构使得我们可以在初始时很快的构建,比如加载训练好的模型,然后复制这些资源供单个OCR请求来使用。

一旦我们得到了字符的位置坐标以及识别好的文本结果,我们会将其整合在一个PDF里。用户拿到的这个PDF中既有原始的图片也有识别好的文字。识别的文字也会添加到 Dropbox的搜索索引中去。用户可以在PDF中高亮、复制粘贴文本。也可以对文本内容进行搜索。

性能调优

到了这一步,我们已经有了一个真正能跑起来的工程化的系统,但性能可能还存在一些问题。

第一点是在预测阶段我们要不要使用 GPU 。训练比预测耗时长得多,训练的时候使用GPU是很常见的,但预测的时候到底要不要使用 GPU呢则很难抉择。

首先是 对于像 Dropbox这样的企业来说生产系统还没有大量用GPU。另外GPU的价格也更贵。对于 Word Detector,我们在 CPU vs GPU 上进行了测试,发现即使跑在CPU上,性能差异和GPU的机器差不太多,成本也更低。

决定了既然要用 CPU, 就需要对系统进行优化。Word Detector 是我们的一大瓶颈,后来我们OpenCV’s C++ MSER 的实现。

这些都搞完了,系统就可以支撑一小波人使用了。下一个阶段就是进一步提升

3

优化提升

当我们新系统和原来的商用OCR系统同时跑在线上的时候,我们想知道新系统在真实的用户数据上是不是效果真的更好。Dropbox 我们十分重视用户隐私,不可能随便拿用户的数据出来测。我们还是沿用了前面提到的用户捐献数据的流程来获取数据。然后用这些图片数据来做端到端的定量分析,最终发现效果的确是和之前的商用OCR SDK一样或更好,因此我们把线上新系统服务用户的比例扩展到100%。

然后,我们测试了使用用户真实调优的模型是不是比我们人工选定的数据调优的效果更好,结果是二者不相上下。

另一个优化点是旋转检测,一开始我们的系统没有这个特性。移动端拍照得到的图片可能是90度或者180度旋转的。我们采用 Inception Resnet v2网络构建了一个检测器,将最后一层修改成预测方向。并将此整合到 OCR 处理流程中。只有很少一部分图片是真正存在旋转的,我们需要确保没有对大部分不存在旋转进行处理。 In addition, we had to solve various tricky issues in combining our upright rotated images with the different ways the PDF file format can apply its own transformation matrices for rotation.

最后,我们发现在 Apple自带的 Preview应用程序中 我们生成的带OCR结果文字的PDF 会有一些bug。出于复制粘贴的目的,大多数 PDF渲染工具会考虑空格,但 Apple自带的 Preview应用程序使用自己的逻辑来确定字符的位置,这时候从PDF中复制文本就会出现所有的词都粘在一起。

于是我们得把 PDF渲染工具都测试一遍 ,有问题就需要进行修复。

总体上来看,整个调研、生产上线,优化的过程耗时8个月,最终我们得到了一个 state-of-art的OCR 系统。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181202G038QS00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券