最后说一下模块的不足和需要改进的地方
第一是没有对粘连字符的切割方法等等,以后作者会更新更多图像处理算法
第二是算法中没有采用位运算,算法结构没有进行深度优化导致出现了重复运算,这些由于本人时间以及能力不足,以后可能会优化。
矩阵运算也缺乏支持库,导致用易语言建立自己的字库完成验证码识别比较麻烦,为了方便一些朋友用易语言建立自己的字库,写出自己的图像识别软件,我制作了图像处理模块,能够实现一些简单图像处理功能。
1.灰度化
验证码图像处理的第一步是灰度化,由于验证码是24位图,每个像素的颜色就有256*256*256=16777216种,显然对具有这么多颜色的图像很难处理,一个像素的颜色是由它具备的R,G,B值决定的,前面已经说明了rgb的颜色值分别为0-255共256个值,对于RGB的颜色值相等的像素成为灰度像素,即一个像素的R=G=B时这个像素是**的,它们的值称为灰度值。所以首先把一个验证码灰度化处理,这样验证码的颜色就从原来的16777216种变为了256种。模块种第一个命令能把传入的彩色图像字节集处理完成后返回一个灰度化的字节集。如下图所示,模块中采用了Gamma校正的灰度化公式:通过RGB的值算出灰度值Gray,把全部像素的R[x]G[y]B[z]变为R[Gray]G[Gray]B[Gray],完成灰度化处理,总之一个等式搞定。
2.二值化
灰度化图像仍然具有256种灰度值,如果把全部的像素转化为纯黑色或者纯白色那么对于某个像素就只有两种情况了,我们可以设置一个阈值,如果像素的灰度值小于阈值就把这个像素变成黑色,反之变成白色。二值化的算法很多,模块中采用了OTSU算法,优点是不用人手动设置灰度化的阈值,虽然一般情况下能实现完美的二值化,但是对于上面背景色逐渐加深的验证码会有一些误差(比如第二张图右边由于原图右边灰度值过低也被判定成了字符变为黑色),我在命令中设置了阈值偏差这个参数,假如处理后的图像出现大面积的黑色遮住原字符(第二张图右边黑色并未遮住原字符,所以不用在意,我在去除干扰线算法中加入了去除由于二值化过程出现大面积黑色的算法),那么提前手动增加阈值偏差即可。
3.去除干扰线
对于这种图像较粗,干扰线较细的验证码,采用4邻域法去除效果较好,原理是每扫描到一个黑色像素就判断这个像素上下左右黑色点的数量,小于一个阈值就把它变为白色点。缺点是无法去除较粗的干扰线,去除干扰线后会留下噪点。
4.去除噪点
噪点指图像中的孤立的具有干扰作用的色块,模块中提供了两种方法能够分别去除小噪点和大的色斑,在噪点去除上能实现完美去噪。
第一种方法采用8邻域法,每扫描到一个黑色像素就判断与之相邻的8个像素点是黑色还是白色,如果全部是白色,那么这个黑色像素显然就是噪点了,当然我们也可以设置一个阈值,如上图所示的噪点是两个黑色像素连接在一起的,那么就认为如果某黑色像素周围黑色像素数量小于等于1该像素就是噪点,原理简单,效果很好。缺点是对于大块的色斑无法去除。
第二种方法采用泛水填充法,在画板中的**就使用了API:floodfill,用户用**选择一个区域任意一点,与之相连的区域都会变成**的颜色。原理其实就是遍历,说高端点叫“深度优先搜索(DFS)”泛水填充法就是基于这一原理遍历所有与某个黑点相连的黑色像素计算出他们的面积并进行排序,与floodfill不同的是我的算法是8邻域的,floodfill是4邻域,采用8邻域让两个斜着连接的色块也被认为是相连的色块,这样上图的连通区域就被分成了6块。(模块中的命令既可以设置一个面积阈值,小于这个面积的黑色色块都将被删除,也可以设置保留字符数)上图设置保留四个字符留下了面积最大的四个字符。
对任意二值化验证码去噪处理时,先进行8邻域法去除小噪点,再进行泛水填充法去除大噪点,两者相互配合能实现完美的去噪。
5.字符分割
字符分割的方法很多,对于不粘连的字符采用泛水填充法是最优的,因为一般的投影法对歪斜的字符无法找到一个确定的位置分割,而泛水填充法基于面积分割,只要字符不粘连,那么从左到右,从上到下扫描便能依次取出字符。
当然到了这一步,只要有字库识别这个验证码就变得很容易了
emmmmmmm
其实不是,还缺少了一个非常重要的处理过程
那就是字符的归一化处理
6.字符归一化
上面的字符虽然看起来是一样大小的,但是实际上是我把图片框弄成一样大小的了www
相信大家都理解分辨率概念,大家的电脑屏幕可以一样大,但是看电影的时候有480p 1080p 2k好多分辨率选项
相信大家肯定都爱看高清无码的www
上面的字符也一样,看着一样大小,实际分辨率可不相同,所以在日后构建神经网络实现字符识别前一定要把字符的分辨率统一。
对于这种黑白字符归一化,双线性插值法能实现从任意分辨率的图像转为任意分辨率,比如下面我把上边第一个字符转为了1920*1080的分辨率图像,看起来是不是高清无码了哟,周围锯齿都没了
当然提高分辨率的代价是构建神经网络的训练时间以及识别时间几何倍数增长,一般我们把原图转为24*24或者16*16的图像即可
7.图像细化
模块中还提供了图像细化算法,能把任意二值化图像的线条变为单像素宽度,效果还不错。