Techeek's Studio.

深入浅出了解OCR识别票据原理

字数统计: 2.3k阅读时长: 7 min
2017/12/20

本文翻译自dzoneIvan Ozhiganov 所发文章Deep Dive Into OCR for Receipt Recognition 文中版权、图像代码等数据均归作者所有。为了本土化,翻译内容略作修改。

​ 光学字符识别技术(OCR)目前被广泛利用在手写识别、打印识别及文本图像识别等相关领域。小到文档识别、银行卡身份证识别,大到广告、海报。因为OCR技术的发明,极大简化了我们处理数据的方式。

​ 同时,机器学习(ML)和卷积神经网络(CNN)的快速发展也让文本识别出现了巨大的飞跃!我们在本文的研究中也将使用卷积神经网络CNN技术来识别零售店的纸质票据。为了方便演示,我们本次将仅采用俄语版的票据进行测试。

​ 我们的目标是项目开发一个客户端来识别来获取相关文档,在有服务器端去识别解析数据。准备好了吗?让我们一起去看看怎么做吧!

预处理

​ 首先,我们需要接收图像相关数据,使其水平竖直方向垂直,接下来使用算法进行检测是否为票据,最终二值化方便识别。

旋转图像识别收据

​ 我们有三种方案来识别票据,下文对这三种方案做了测试。

       1.	高阈值的自适应二值化技术。
 2.	卷积神经网络(CNN)。
   3.Haar特征分类器。

自适应二值化技术

​ 首先,我们看到,图中图像上包含了完整的数据,同时票据又与背景有些差距。为了能更好识别相关数据,我们需要将图片进行旋转。使其水平沿竖直方向对齐。

​ 我们使用Opencv中的自适应阈值化函数adaptive_threshold和scikit-image框架来调整收据数据。利用这两项函数,我们可以在高梯度区域保留白色像素,低梯度区域保留黑色像素。这使得我们获得了一个高反差的样本图片。这样,通过裁剪,我们就能得到票据的相关信息了。

使用卷积神经网络(CNN)

​ 起初我们决定使用CNN来做相关位置检测的接收点,就像我们之前做对象检测项目一样。我们使用判断角度来拾取相关关键点。这种方案虽然好用,但是和高阈值对比检测裁剪更差。

​ 因为CNN只能找到文本的角度坐标,而文字的角度变化很大,这就意味着CNN模型不是很精准。详情请参考下面CNN测试的结果。

使用Haar特征分类器来识别收据

​ 作为第三种选择,我们尝试使用Haar特征分类器来做分类筛选。然而经过一周的分类训练和改变相关参数,我们并没有得到什么比较积极的结果,甚至发现CNN都比Haar表现好得多。

二值化

​ 最终我们使用opencv中的adaptive_threshold方法进行二值化,经过二值化处理,我们得到了一个不错的图片。

文本检测

​ 接下来我们来介绍几个不同的文本检测组件。

通过链接组件检测文本

​ 首先,我们使用Opencv中的find Contours函数找到链接的文本组。大多数链接的组件是字符,但是也有二值化留下来嘈杂的文本,这里我们通过设置阈值的大小来过滤相关文本。

​ 然后,我们执行合成算法来合成字符,如: Й和=。通过搜索最临近的字符组合合成单词。这种算法需要你找到每个相关字字母最临近的字符,然后从若干字母中找到最佳选择展示。

​ 接下来文字形成文字行。我们通过判断文字是否高度一致来判断文本是否属于同一行。

​ 当然,这个方案的缺点是不能识别有噪声的文本。

使用网格对文本进行检测

​ 我们发现几乎所有票据都是相同宽度的文本,所以我们设法在收据上画出一个网格,并利用网格分割每个字符:

​ 网格一下子精简了票据识别的难度。神经网络可以精准识别每个网格内的字符。这样就解决了文本嘈杂的情况。最终可以精确统计文本数量。

​ 我们使用了以下算法来识别网格。

​ 首先,我在二值化镜像中使用这个连接组件算法。

​ 然后我们发现图中左下角有些是真,所哟我们通过二维周期函数来调整网格识别。

​ 修正网格失真背后主要的思想是利用图形峰值点找到非线性几何失真,换句话说,我们必须找到这个函数的最大值的和。另外,我们还需要一个最佳失真值才行。

​ 我们使用ScipyPython模块中的RectBivariateSpline函数来参数化几何失真。并用Scipy函数进行优化。得到如下结果:

​ 总而言之,这个方法缓慢且不稳定,所以坚决不打算使用这个方案。

光学字符识别

​ 我们通过组连接识别发现文本,并识别完整的单词。

识别通过连接组发现的文本

​ 对于文本识别,我们使用卷积神经网络(CNN)接收相关字体进行培训。输出部分,我们通过对比来提升概率。我们那个几个最初的几个选项多对比,发现有99%的准确识别率后。又通过对比字典来提高准确度,并消除相关类似的字符,如”З” 和 “Э”造成的错误。

​ 然而,当涉及嘈杂的文本时,该方法性能却十分低下。

识别完整的单词

​ 当文本太嘈杂的时候,需要找到完整的单词才能进行单个字母的识别。我们使用下面两个方法来解决这个问题:

  • LSTM网络
  • 图像非均匀分割技术

LSTM网络

​ 您可以阅读这些文章,以更加深入了解使用卷积神经网络识别序列中的文本 ,或我们可以使用神经网络建立与语言无关的OCR吗? 为此,我们使用了OCRopus库来进行识别。

​ 我们使用了等宽的字体来作为人工识别样本进行训练。

​ 训练结束后,我们由利用其他数据来测试我们的神经网络,当然,测试结果非常积极。这是我们得到的数据:

​ 训练好的神经网络在简单的例子上表现十分优秀。同样,我们也识别到了网格不适合的复杂情况。

​ 我们抽取的相关的训练样本,并让他通过神经网络进行训练。

​ 为了避免神经网络过度拟合,我们多次停止并修正训练结果,并不断加入新数据作为训练样本。最后我们得到以下结果:

​ 新的网络擅长识别复杂的词汇,但是简单的文字识别却并不好。

​ 我们觉得这个卷积神经网络可以细化识别单个字符来使文本识别更加优秀。

图像非均匀分割技术

​ 因为收据字体是等宽的字体,所以我们决定按照字符分割字体。首先,我们需要知道每个字母的宽度。因此,字符的宽度尤为重要,我们需要估计每个字母的长度,利用函数,我们得到下图。选择多种模式来选取特定的字母宽度。

​ 我们得到一个单词的近似宽度,通过除以字符中的字母数,给出一个近似分类:

区分最佳的是:

这种分割方案的准确度是非常高的:

当然,也有识别不太好的情况:

分割后我们在使用CNN做识别处理。

从收据中提取含义

​ 我们使用正则表达式来查找收据中购买情况。所有收据都有一个共通点:购买价格以XX.XX格式来撰写。因此,可以通过提取购买的行来提取相关信息。个人纳税号码是十位数,也可以通过正则表达式轻松获取。同样,也可以通过正则表达式找到NAME / SURNAME等信息。

总结

  1. 不论你选择什么方法,LSTM或者其他更加复杂的方案,都没有错误,有些方法很难用,但是有些方法却很简单,因识别样本而异。
  2. 我们将继续优化这个项目。目前来看,在没有噪声的情况下,系统性能更加优秀。
CATALOG
  1. 1. 预处理
    1. 1.1. 旋转图像识别收据
      1. 1.1.1. 自适应二值化技术
      2. 1.1.2. 使用卷积神经网络(CNN)
      3. 1.1.3. 使用Haar特征分类器来识别收据
    2. 1.2. 二值化
  2. 2. 文本检测
    1. 2.1. 通过链接组件检测文本
    2. 2.2. 使用网格对文本进行检测
  3. 3. 光学字符识别
    1. 3.1. 识别通过连接组发现的文本
    2. 3.2. 识别完整的单词
      1. 3.2.1. LSTM网络
      2. 3.2.2. 图像非均匀分割技术
  4. 4. 从收据中提取含义
  5. 5. 总结