基于学习的OCR字符识别
2018-09-17肖坚
肖坚
摘 要: OCR(Optical CharacterRecognition)是通过检测字符每个像素亮度的模式确定其形状,然后用字符识别方法将形状翻译成计算机文字的过程。文章利用Java语言实现OCR步骤,包括像素二值化,图像分割,训练识别和输出等。测试开发是在web验证码识别场景中进行的,web验证码是将一串随机产生的符号,生成为图片,再加上一些干扰线,使之能有效防止恶意注册和灌水。通过测试表明,该方法可行、有效;拒识率、误识率低;识别速度快,具有一定的实用意义。
关键词: OCR; 验证码; 文字识别; 干扰线; 拒识率; 误识率
中图分类号:TP3 文献标志码:A 文章编号:1006-8228(2018)07-48-04
Abstract: OCR (Optical Character Recognition) is the process of translating the shape, which is determined by detecting the pattern of the brightness of each pixel of the character, into computer text by character recognition method. In this paper, OCR procedure is implemented in Java language, including pixel binarization, image segmentation, recognition training and output. The test development is carried out in the Web verification code identification scene. The Web verification code is a string of randomly generated symbols, generated as a picture, and a number of interference lines added on it, so that it can effectively prevent malicious registration and irrigation. The test shows that the method is feasible and effective, with low rejection rate and error rate, fast recognition speed, and has practical significance.
Key words: OCR; verification code; character recognition; interfering line; rejection rate; error rate
0 引言
識别原理及实现方法:OCR采用光学的方式,将纸质或图片文档中的文字转换成为黑白点阵的图像文件,并通过识别软件将图像中的文字转换成文本格式,供文字处理软件进一步编辑加工的技术。
识别过程一般分以下几个步骤:
首先训练学习过程,分成图像生成,预处理,图像分割三个步骤,图像分割不是简单的将图片等份分割,常常需要程序员像素级微调,才能最终生成合适的样本。
其次才是识别过程,识别前3个步骤和训练学习是一致的,而且各个步骤处理的参数必须和训练完全一样,否则获取的单字符图片完全没有可比性,识别步骤是把单字符图片和样本数据一一比较,获得最为接近的作为结果。识别流程如图1所示。
以下是各个步骤详细内容及代码实例。
1 图像预处理
预处理过程就是用阈值分割法把图片上每个像素二值化,像素红绿蓝在一定范围内置成白色,反之黑色。这里常见的问题是背景和字符亮度接近,需要手工试探,才能找到合适的阈值。以下是java预处理函数,函数根据图片高和宽遍历每个像素点,通过ISWHITE函数来判断当前像素取值。
INT WIDTH=IMG.GETWIDTH();
INT HEIGHT=IMG.GETHEIGHT();
FOR (INT X=0; X FOR (INT Y=0; Y IF (ISWHITE(IMG.GETRGB(X, Y))==1) { IMG.SETRGB(X, Y, COLOR.WHITE.GETRGB()); } ELSE { IMG.SETRGB(X, Y, COLOR.BLACK.GETRGB()); } 2 分割 最常见的验证码字符,一般是四位数字,为了识别字符串,需要将图片分割成四个单字符图片,以下方法适用于位置固定的验证码。SPLITIMAGE函数按照固定宽高分别生成1.JPEG,2.JPEG,3.JPEG,4.JPEG四张图片。 PUBLIC STATIC LIST SPLITIMAGE(BUFFEREDIMAGE IMG) THROWS EXCEPTION { IMAGEIO.WRITE(IMG, "JPEG", NEW FILE (WORKPATH+"RESULT\\ALL.JPEG")); LIST ARRAYLIST
SUBIMGS.ADD(IMG.GETSUBIMAGE(4, 1, 15, 18));
SUBIMGS.ADD(IMG.GETSUBIMAGE(19, 1, 15, 18));
SUBIMGS.ADD(IMG.GETSUBIMAGE(34, 1, 15, 18));
SUBIMGS.ADD(IMG.GETSUBIMAGE(49, 1, 15, 18));
IMAGEIO.WRITE(IMG.GETSUBIMAGE(4, 1, 15, 18),
"JPEG",NEW FILE(WORKPATH+"RESULT\\1.JPEG"));
IMAGEIO.WRITE(IMG.GETSUBIMAGE(19,1, 15, 18),
"JPEG",NEW FILE(WORKPATH+"RESULT\\2.JPEG"));
IMAGEIO.WRITE(IMG.GETSUBIMAGE(34,1, 15, 18),
"JPEG",NEW FILE(WORKPATH+"RESULT\\3.JPEG"));
IMAGEIO.WRITE(IMG.GETSUBIMAGE(49,1, 15, 18),
"JPEG",NEW FILE(WORKPATH+"RESULT\\4.JPEG"));
RETURN SUBIMGS;
}
3 训练
训练是指按照步骤1,2,穷举单字符样式图片,并将文件名设置成实际字符值。-1,-2,-3则是字符多种变形时不同的样本序号。
4 识别
相对前面三个步骤,识别则相对简单,算法只是机械地将分割图片和样本对象对比,获取相似度最高的样本图片,该图片的结果就是样本的文件名(“-”前面部分)。代码为冒泡排序算法。
PUBLIC STATIC STRING GETSINGLECHAROCR
(BUFFEREDIMAGE IMG,
MAP
STRING RESULT="";
INT WIDTH=IMG.GETWIDTH();
INT HEIGHT=IMG.GETHEIGHT();
INT MIN=WIDTH * HEIGHT;
FOR (BUFFEREDIMAGE BI : MAP.KEYSET()) {
INT COUNT=0;
LABEL1: FOR (INT X=0; X FOR (INT Y=0; Y IF (ISWHITE(IMG.GETRGB(X,Y))!=ISWHITE (BI.GETRGB(X, Y))) { COUNT++; IF (COUNT>=MIN) BREAK LABEL1; } } } IF (COUNT < MIN) { MIN=COUNT; RESULT=MAP.GET(BI); } } RETURN RESULT; } 为了防止暴力破解,网站开发方通常会增加验证码复杂度,常用的方法有以下几种: 4.1 干扰线 增加干扰线会大大增加误识率。对不同的干扰线,也有不同的方法处理,a干扰线和字符亮度差别大。 如图3所示,X轴代表亮度,Y轴代表像素数量,此类情况干扰线亮度较集中,可以直接根据三原色重新调整阈值,从阈值1改至阈值2,这样背景色和干扰线设置在阈值之外,预处理之后的图片就已经不含干扰线了。 b对于干扰线和验证码亮度接近,无法用阈值二值化处理的,可以用算法剔除干扰。譬如对点Color[I][J],如果Color[I+1][J],Color[I-1][J],Color[I][J+1],Color[I][J-1]都是纯黑色或者纯白色的,就认为Color[I][J]是干扰,将Color[I][J]置为白色。 4.2 字符变形 字符变形也是常用的防识别手段,字符变形多种多样,有些扭曲的非常严重,这样的识别还是有些难度的,而常见的变形往往是几个固定方向的倾斜,这样情况处理起来非常简单,只要穷举各个角度各个字符的样本图片,依然能识别成功。 4.3 位置不固定的字符 有些验证码并不固定的图片的某个位置上,而是在一定区间范围内;x,y方向随机偏移,这种情况处理分两种。 直接在图片分割的时候,采用先縱后横的算法,直接获取单个字符图片,其算法如下: PUBLIC STATIC LIST SPLITIMAGE(BUFFEREDIMAGE IMG) THROWS EXCEPTION { LIST ARRAYLIST INT WIDTH=IMG.GETWIDTH(); INT HEIGHT=IMG.GETHEIGHT(); LIST
FOR (INT X=0; X INT COUNT=0; FOR (INT Y=0; Y IF (ISWHITE(IMG.GETRGB(X, Y))==1) { COUNT++; } } WEIGHTLIST.ADD(COUNT); } FOR (INT I=0; I INT LENGTH=0; WHILE (WEIGHTLIST.GET(I++)>1) { LENGTH++; } IF (LENGTH > 12) { SUBIMGS.ADD(REMOVEBLANK(IMG .GETSUBIMAGE(I-LENGTH-1, 0, LENGTH/2, HEIGHT))); SUBIMGS.ADD(REMOVEBLANK(IMG .GETSUBIMAGE(I-LENGTH/2-1, 0, LENGTH/2, HEIGHT))); } ELSE IF (LENGTH>3) { SUBIMGS.ADD(REMOVEBLANK(IMG .GETSUBIMAGE(I-LENGTH-1, 0, LENGTH, HEIGHT))); } } RETURN SUBIMGS; } 第二種方法,在识别过程中遍历整个区间和样本图片比较识别。 图4中所示案例情况:样本为4*3像素,实际图片范围为7*6像素,XY坐标区间[11,21][16,28],函数方法从原点向右下角遍历所有的4*3图片,再与样本作比较。函数在[13,24][15,27]处获得比较结果字符7。 5 结束语 文章介绍OCR字符识别四个步骤的函数方法,并描述了简单干扰下的应对措施。通过代码测试,证实该方法稳定、有效。OCR识别一直是模式识别领域极具代表性的课题,随着互联网的发展,产生出许多以光学字符识别作为入口的文字信息录入及查询类应用。由于能力和时间所限,上述方法依然比较粗浅,研究中发现几乎每个步骤都有大量优化算法的空间。在OCR领域,新的算法思路不断涌现,在一个高效的OCR系统中仅仅采用一种识别方式是无法满足现实要求的。单个识别策略的能力有限,因此采用多种策略实现优势互补,多角度利用字符的特征信息是OCR发展的方向。在这个方向上经常采用的集成策略有投票法、概率法、Dempster-Shafer法以及行为知识空间法等多种综合方法[4]。目前,在汉字图像识别中拒识率、误识率较高,是一个有待解决的问题。由于汉字是非字母化、非拼音化的文字,且汉字信息量很大,有不同的字形、字体,而且结构复杂,因此汉字识别的过程比一般英文字符识别更加复杂[5] 。 参考文献(References): [1] 霍强.光学字符识别技术:让电脑像人一样阅读[A].China Academic Journal Electronic Publishing House [C].科学与现代化,2016.14. [2] 杨淑莹.图像识别与项目实践VC++、MATLAB技术实现[M].电子工业出版社,2014. [3] 田媛美.基于深度学习的车牌检测[D].西安电子科技大学硕士学位论文,2017. [4] 荆涛,王仲.光学字符识别技术与展望[J].计算机工程,2003.29(2):2 [5] 李南.光学字符识别技术与图书馆信息资源的数字化[J].激光杂志,2012.33(5):3