从截图中提取低分辨率文本的OCR
我正在写一个OCR(光学字符识别)应用程序,目的是从截图中读取字符。目前,我只专注于数字。我部分参考了这篇博客文章:http://blog.damiles.com/2008/11/basic-ocr-in-opencv/。
我可以通过一些聪明的阈值处理成功提取每个单独的字符。但是,匹配字符的时候就有点棘手了。即使字体和大小固定,背景颜色和字距等因素也会导致同一个数字在形状上略有不同。例如,下面的图片分成了三部分:
- 顶部:我从截图中成功提取的目标数字
- 中间:模板:我训练集中的一个数字
- 底部:顶部和中间图片之间的误差(绝对差异)
这些部分都经过缩放(两条绿色水平线之间的距离代表一个像素)。
你可以看到,尽管顶部和中间的图片都清晰地表示了数字2,但它们之间的误差却很大。这在匹配其他数字时会导致误判——比如,一个放置得当的7可能比中间的数字更容易与上面的目标数字匹配。
目前,我通过为每个数字准备一堆训练图像,并逐个与目标数字进行匹配来处理这个问题。我尝试过取训练集的平均图像,但这并没有解决问题(其他数字的误判)。
我有点不愿意使用偏移模板进行匹配(这基本上和我现在做的差不多)。有没有比简单的绝对差异更好的方法来比较这两张图片?我在想,也许可以用EMD(地球搬运工距离,http://en.wikipedia.org/wiki/Earth_mover的距离)在二维空间中进行比较:基本上,我需要一种比较方法,它对全局偏移和小的局部变化不那么敏感(比如,靠近白色像素的像素变成白色,或靠近黑色像素的像素变成黑色),但对全局变化敏感(比如,远离白色像素的黑色像素变成黑色,反之亦然)。
有没有人能建议一种比绝对差异更有效的匹配方法?
我在使用OpenCV和C风格的Python包装器(import cv
)进行所有这些操作。
3 个回答
根据我的经验和阅读的一些关于字符分类的论文,我可以告诉你,开始学习的一个好方法是了解主成分分析(PCA)、Fisher线性判别分析(LDA)和支持向量机(SVM)。这些都是非常有用的分类方法,特别是在光学字符识别(OCR)方面。而且,OpenCV这个库已经包含了很棒的PCA和SVM的实现,你可以在这里和这里找到相关信息。我没有看到OpenCV的OCR代码示例,但你可以用一些修改过的人脸分类代码来进行字符分类。关于OpenCV人脸识别代码的一个很好的资源是这个网站。
我还推荐一个Python库叫“scikits.learn”。把cvArrays发送到scikits.learn并在你的数据上运行机器学习算法非常简单。使用SVM进行OCR的一个基本示例可以在这里找到。
还有一个更复杂的示例,使用流形学习来识别手写字符,可以在这里查看。
在嘈杂的图像上进行文字识别可不是件简单的事,所以一些简单的方法效果并不好。
我建议你使用HOG来提取特征,然后用支持向量机(SVM)来进行分类。HOG看起来是描述形状的一个非常有效的方法。
整个处理流程可以在OpenCV中实现,不过我不太清楚Python版本中的函数名称。你应该可以使用最新的haartraining.cpp进行训练,它实际上支持的不仅仅是Haar,还包括HOG和LBP。
而且我觉得最新的代码(来自主干)比官方发布的版本(2.3.1)有了很大的改进。
HOG通常只需要其他识别方法所用训练数据的一小部分,但如果你想分类那些部分被遮挡(或者缺失)的形状,确保在训练中包含一些这样的形状是很重要的。
我建议你可以看看Haar级联。这是一种用于人脸检测和头部追踪的技术。我用过它,效果不错。如果你有足够的'2'、'3'、'4'等等的数据,应该可以建立起一套相当不错的级联模型。