前面讲到已经把所有的字符经过去干扰、分割和归一化得到标准大小的单个字符,接下来要做的就是识别验证码了。现在要做的基本上也就和OCR没什么区别了,因为得到的字符已经是尽可能标准的了。下面的识别分为两个步骤,第一步先是特征值的提取,第二步是SVM训练。
一、特征值提取
首先要说的是我当时在做这个的时候,还没有了解“主成分分析”,所以在提取特征值的时候用的是比较简单的方法,就是简单的提取像素值来解决的。具体来说,由于前面归一化的字符每个都是16*16大小的,可以将字符图片等分为16个子区域,每个区域是4*4的,然后统计每个区域内部黑色像素(字符像素)的个数,这样可以得到16个数值,然后按照从左到右,从上到下来的顺序进行排列,可以得到一个16维的数据,这样依赖就将256维的原数据降到了16维。
现在要做的就是如果想验证哪个网站的验证码,就写个爬虫爬该网站的验证码,爬个几百张然后对每一张验证码上的字符进行标记,然后按照前面的步骤一步一步预处理然后提取特征值,将每个字符的特征值和其标记的字符写入到数据文件中,在这里我取了某网站的验证码一共250张,每张有4个字符,字符集只有大写字母26个和0-9十个数字,这样得到了1000条数据,由于字符存在粘连状况,因此在字符分割那一部分并不是100%成功,最后有十几张验证码图片分割失败,所以最终得到的数据集个数只有900多个。部分数据如下:
- D,0,4,7,12,9,9,4,12,7,8,4,12,0,8,8,2
- N,0,1,5,6,9,15,7,2,0,5,14,7,6,9,7,3
- Y,3,1,0,0,5,12,9,8,3,12,4,1,5,0,0,0
- 2,0,0,0,1,7,2,7,12,8,9,8,8,0,3,0,0
- Z,0,0,1,8,13,1,10,12,12,11,1,12,5,1,0,2
- I,0,0,0,0,0,1,4,6,7,11,7,3,0,0,0,0
- Z,0,0,1,6,12,1,11,12,12,12,2,12,6,1,0,0
- 5,0,0,1,0,6,12,4,9,8,7,9,8,2,0,0,0
- G,0,9,8,3,8,7,5,11,12,1,10,11,3,6,9,1
- 7,0,0,0,0,8,1,6,11,9,10,6,0,2,1,0,0
- M,0,4,7,10,8,16,11,9,0,4,12,7,9,14,13,8
- D,0,1,4,5,11,10,9,12,12,1,3,10,5,11,11,1
- 3,0,0,1,1,6,2,2,10,10,9,12,8,0,2,0,0
- F,0,0,4,6,7,13,12,4,8,8,8,0,5,3,2,0
- N,0,0,5,6,9,15,6,2,0,5,11,7,7,10,5,3
- X,1,0,0,7,7,11,12,4,3,13,10,8,9,2,0,1
- 2,0,0,0,2,8,4,6,13,9,11,9,7,2,3,0,0
- P,1,0,4,5,11,12,11,4,12,6,8,0,4,10,1,0
- J,0,0,2,2,0,0,3,13,4,10,11,6,3,2,0,0
- V,4,4,3,0,2,6,9,16,0,7,12,4,6,6,0,0
- 7,1,0,0,0,8,5,10,9,12,8,0,0,1,0,0,0
- W,9,12,12,9,4,8,11,1,9,10,11,9,4,9,9,2
数据集每行代表一条数据,第一个字母或数字是该字符的标记结果,后面紧跟着16个数字是其特征值。
二、机器学习识别
现在终于到了验证码识别的最后一步了,有了前面的数据集,就可以进行训练了。我在这里使用的分类器是SVM,由于整个项目都是用OpenCV做的,而OpenCV正好提供SVM的库,因此就直接拿来用了。OpenCV的SVM是基于libSVM的,有关SVM(支持向量机)的知识我也了解的不是太多,这里不再赘述,有兴趣的可以去找找资料看看。在OpenCV的源代码工程里,可以找到怎么使用OpenCV SVM的demo,这里就直接拿来用了,代码如下: