验证码介绍
现在的验证码主要分为4类:识图验证码、计算验证码、滑块验证码、语音验证码。本文只针对taobao的识图验证码进行识别。目标验证码如下:
可以看到这类验证码都是变形、粘连、大小不一、位置不固定的,不再像以前的可分割的验证码了,也就增加了机器识别的难度。这类粘连验证码就是本文主要的研究对象。
识别步骤
(1)图片预处理
灰度化、 二值化、去噪声(本文验证码无噪声,没有此步骤)等
(2)字符切割
CFS连通域分割、滴水法
(3)分类模型训练
支持向量机或神经网络。本文训练的是卷积神经网络
图片预处理
图片预处理之后的效果:
(1)灰度化
彩色图片的像素点是由R、G、B三个原色组成,其值在0-255之间,有三个通道。灰度图是指只含有亮度信息,不含彩色信息的图像,即只有一个通道。灰度化就是将彩色图像转为灰度图像的过程。本文采用的灰度化方法是加权平均法。
def rgb2gray(img): # 求灰度值
return np.dot(img[...,:3], [0.299, 0.587, 0.114])
(2)二值化
二值化是指将灰度图像转换成只有黑白两色的图像,通常做法是选择一个阈值,如果灰度图像上的像素大于该阈值则为白色,否则为黑色。
def binary(gray):# 二值化
height,width=gray.shape
bin = gray.copy()
for i in range(height):
for j in range(width):
if (gray[i,j]<=130):
bin[i,j]=0
else:
bin[i,j]=1
return bin
字符切割
由于粘连的字符不好识别,所以我们将粘连的字符切割为单个字符,再训练模型进行识别。
(1)竖直投影法
竖直投影法是最简单的字符分割方法,根据相邻的波谷或者极大极小值来确定字符边界,常用于字符没有粘连的情况,如车牌识别。但是由于目标验证码倾斜程度不小并且大多粘连,对于倾斜严重但实际并未粘连的两个字符,竖直投影的效果不太好,因此未采用这种方法。
(2)CFS连通域分割法
假定每个字符由单独的一个连通域组成,因此只需要将不同连通域加以标记,就可分割出字符。此方法要求字符不粘连,无论旋转或扭曲。找到一个黑色像素并开始判断,直到所有相连的黑色像素都被遍历标记过后即可判断出字符的分割位置。
其算法原理:
1.对二值化之后的图像,从左往右,从上往下扫描图片,遇到黑点,并且该点没有被访问,则将该点压栈,并标记为已经访问。
2.如果栈不空,则继续探测周围4个点(四邻域,也可选择八邻域),并执行步骤1;如果栈空,则代表已经探测完一个字符块,并将该字符块的最左最右、最上最下坐标保存(本文只保存左右)。
3.探测结束,最后通过每个字符的坐标进行切割。
代码(复制别人的: