vin码识别所涉及的知识
如果要实现vin码识别,最简化的步骤是什么?获取图片->图片识别。重点在于图片识别,限于自身的知识和技术限制,我优先想到的是使用开源的第三方库来实现。要找到第三方开源库,首先得知道在识别过程中用到的技术是什么。
经过一番搜索学习,我发现vin码识别属于光学字符识别技术(Optical Character Recognition, 即OCR)。OCR是指对文本资料的图像文件进行分析识别处理,获取文字及版面信息的过程。
那么OCR的具体过程是什么呢?大的步骤我们可以分为:图片预处理、特征提取和降维、分类器设计、训练和实际识别、后处理。
- 图片预处理
预处理阶段是对包含文字的图像进行处理以便后续进行特征提取、学习。因为图片输入可能是五花八门的环境和效果,所以这个过程的主要目的是减少图像中的无用信息,以便方便后面的处理。
在这个步骤通常有:灰度化(如果是彩色图像)、降噪、二值化、字符切分以及归一化这些子步骤。经过二值化后,图像只剩下两种颜色,即黑和白,其中一个是图像背景,另一个颜色就是要识别的文字了。降噪在这个阶段非常重要,降噪算法的好坏对特征提取的影响很大。字符切分则是将图像中的文字分割成单个文字——识别的时候是一个字一个字识别的。如果文字行有倾斜的话往往还要进行倾斜校正。归一化则是将单个的文字图像规整到同样的尺寸,在同一个规格下,才能应用统一的算法。
- 特征提取和降维
特征是用来识别文字的关键信息,每个不同的文字都能通过特征来和其他文字进行区分。对于数字和英文字母来说,这个特征提取是比较容易的,因为数字只有10个,英文字母只有52个,都是小字符集。对于汉字来说,特征提取比较困难,因为首先汉字是大字符集,国标中光是最常用的第一级汉字就有3755个;第二个汉字结构复杂,形近字多。
在确定了使用何种特征后,视情况而定,还有可能要进行特征降维,这种情况就是如果特征的维数太高(特征一般用一个向量表示,维数即该向量的分量数),分类器的效率会受到很大的影响,为了提高识别速率,往往就要进行降维,这个过程也很重要,既要降低维数吧,又得使得减少维数后的特征向量还保留了足够的信息量(以区分不同的文字)。
- 分类器设计、训练和实际识别
分类器是用来进行识别的,就是对于第二步,对一个文字图像,提取出特征给,丢给分类器,分类器就对其进行分类,告诉你这个特征该识别成哪个文字。
- 后处理
后处理是用来对分类结果进行优化的:
第一个,分类器的分类有时候不一定是完全正确的(实际上也做不到完全正确),比如对汉字的识别,由于汉字中形近字的存在,很容易将一个字识别成其形近字。后处理中可以去解决这个问题,比如通过语言模型来进行校正——如果分类器将“在哪里”识别成“存哪里”,通过语言模型会发现“存哪里”是错误的,然后进行校正。
第二个,OCR的识别图像往往是有大量文字的,而且这些文字存在排版、字体大小等复杂情况,后处理中可以尝试去对识别结果进行格式化,比如按照图像中的排版排列什么的,举个栗子,一张图像,其左半部分的文字和右半部分的文字毫无关系,而在字符切分过程中,往往是按行切分的,那么识别结果中左半部分的第一行后面会跟着右半部分的第一行诸如此类。
vin码识别所用的开源库
OpenCV
通过上面的OCR识别步骤的介绍,我们可以发现OCR涉及技术量很庞大。不管是预处理阶段的各种图像处理技术还是后面的文字特征提取,都涉及到大量的图像算法知识,同时分类器设计和训练还涉及到机器学习、人工智能相关技术及应用,我们不可能从基础算法上去完全编写这些处理步骤,大多数人也不会机器学习、深度学习和人工智能,所以最快捷的方法是使用现有OCR相关的开源库。
经过一番搜索,我发现了OpenCV满足我的要求。OpenCV是Intel®开源计算机视觉库。它由一系列 C 函数和少量 C++ 类构成,实现了图像处理和计算机视觉方面的很多通用算法。OpenCV 拥有包括 300 多个C函数的跨平台的中、高层 API。它不依赖于其它的外部库——尽管也可以使用某些外部库。OpenCV可用于开发实时的图像处理、计算机视觉以及模式识别程序。
OpenCV的主要模块不仅包括计算机视觉基础算法的核心功能,还有图像处理、食品分析、物体检测、深度学习神经网络、机器学习、多维空间的聚类和搜索等等非常多的模块,使用OpenCV完全可以实现OCR的一整套处理流程,但同时工作量也很大还需要自己去进行分类器设计、训练和机器学习。那么有没有可以直接用的训练好的识别库呢?果然有,Tesseract。
OpenCV官网 https://opencv.org
Tesseract
Tesseract是Ray Smith于1985到1995年间在惠普布里斯托实验室开发的一个OCR引擎,曾经在1995 UNLV精确度测试中名列前茅。但1996年后基本停止了开发。2006年,Google邀请Smith加盟,重启该项目。目前项目的许可证是Apache 2.0。该项目目前支持Windows、Linux和Mac OS 等主流平台。但作为一个引擎,它只提供命令行工具。目前,Tesseract可以识别超过100种语言。也可以用来训练其它的语言。
经过了解发现这是一个完整的OCR工具啊,能不能不用OpenCV然后完全使用OCR啊。理论上讲是可以的,但是需要大数据、机器学习、深度学习相关的技术,我们自己去定制训练相关场景的字库,由于我们提供了更加详细的场景和海量的数据,这样训练的结果还可以提高图像的识别率。然而受限于知识技能。。 。
Tesseract Github地址 https://github.com/tesseract-ocr/tesseract
vin码识别实践
既然不会机器学习相关的知识,那么最终我选择了使用Tesseract自带提供的英文字库训练包来做文字识别,即实现OCR的特征提取和降维、分类器设计和训练、实际识别和后处理几个步骤。使用OpenCV来进行图像预处理,对图像灰度化、降噪、二值化等来为文字识别提供黑底白字干净文字图像。
OpenCV提供iOS框架,Tesseract也由一位国外开源作者封装了iOS第三方库,因此在工程的Podfile文件中引入:
pod 'OpenCV'
pod 'TesseractOCRiOS'
就可以直接使用两个库了。
经过一系列实践调整之后,最终我将图像处理划分为了一下几个步骤:
- 图像灰度化
- 均衡直方图
- 高斯模糊去噪
- 图像二值化
- 计算面积较小噪点阈值(噪点和文字的色度界限值),去除面积较小噪点
- 计算面积较大干扰项特征值阈值(选择宽高比、周长、面积作为特征),去除面积较大干扰项
- 再一次高斯模糊去噪之后进行边缘检测,矫正图像使文字出于水平位置
- 经过腐蚀、膨胀提取文字区域并进行图像裁剪,得到比较纯的文字图像
- 将文字图像输入给Tesseract进行文字识别
在文字处理过程中,干扰比较大的两项就是计算面积较小噪点阈值和计算面积较大干扰项特征值阈值,因为这两项是保证文字图像干净完整的关键步骤,计算值不准确就会导致获取的图像不准确,也就没法进行进一步的文字识别。
计算面积较小噪点的阈值,我采用的是选取文字大致的连通域,并对连通域内色度求取文字色度平均值,并扩展为上限和下限。然后对每个像素求取周围八个像素在界限内的个数,当个数超出某个值的时候即视为噪点,可以进行该点像素的删除。
计算面积较大干扰项的特征值阈值,主要选取了连通域矩形轮廓的宽高比、面积和周长三种特征,通过5张图片的特征计算,求取了这些特征上限和下限,并引入了图片拍摄距离的影响。最后对满足特征的连通域轮廓再进行数量统计、位置分析,选取位置最接近的17个连通域作为文字。如果这一步除了问题,那么获取的17个文字中必然有错误部分。
改进方向:
1.使用大量图片提取噪点筛选的特征值阈值,如此才能精准处理图片。
2.使用深度学习来训练文字库,提高识别准确率。
demo地址 https://github.com/Justin-ZhengYi/VINOCRDemo