新闻动态
2021年春节放假通知
图片验证码识别包月产品特价来了!
2020年春节放假通知
图片验证码识别-包月版产品说明
2019年国庆放假通知!
对公转账支付和发票开具说明
春季验证码专场活动详情!
3.15钜惠活动详情!
验证码识别接口免费测试步骤
中国6家公司上榜全球AI初创企业100强

机器学习之验证码识别

发布时间:2019-01-14 23:48:09

  经常爬虫的同学,验证码识别应该是经常会碰到的事情。现在网上也有很多验证码识别的工具,但不一定适应全部网站,而且识别率往往不会太高。这周兴起,突然想试试通过机器学习训练后识别验证码的正确率能去到多少,好吧,那就拿自家的生产系统练练手。

机器学习之验证码识别

000.png

  从截图可以看到,cBSS系统的验证码并不算复杂,没有倾斜,也不会重叠,就是图片上的字母位置比较靠近边缘或底部,以及背景会有一些颜色线条干扰。那么,就开始本次实验。

  从网上看了些教程,对于验证码识别,一般标准流程如下图所示(图片来自于http://www.jianshu.com/p/41127bf90ca9):

机器学习之验证码识别

  Step 1.图像采集

  既然要使用到机器学习,那么足够的训练集样本就必不可少了。最方便的办法就是写个小爬虫程序,把系统上的验证码爬一些下来。以下是我写的简单的爬虫程序(作为一个Python新手,代码可能写得很渣):

机器学习之验证码识别

  爬虫程序很简单,主要就是找到验证码的src,程序里的base_url即是验证码的src(后面的“random=”加上随机数就能生成验证码图片)。爬的不多,就只爬下1000张。

机器学习之验证码识别

  Step 2.图像处理

  图像处理,是为了方便后续图像识别时的特征提取及训练,如果不嫌麻烦,可以先对这1000个验证码进行切割后手工打标,但我比较懒,后续想借助光学字符识别技术( Optical Character Recognition (OCR))进行预处理,ocr在单文字识别上的效果正确率还是可以的,所以想先进行一系列处理以提高OCR识别。一开始,没仔细研究图片特点,我直接对照片进行了中值滤波、增强对比度、灰度化处理,以下是代码(后面因为效果不好,注释掉了)。

机器学习之验证码识别

  之后,由于每张验证码有4个字母,且间距基本为等距,所以我进行了等距切割,代码如下:

机器学习之验证码识别

  结果处理后的效果图如下,我一脸懵逼;人眼识别都有点困难,机器会更加懵逼吧。。。

机器学习之验证码识别

  于是我又重新审视了验证码的特征,其实原图验证码很端正,且边缘清晰,只是背景有一些干扰线(颜色大体都比较浅),以及验证码上下边框的横线(也列入干扰线)。上网看了一些图像处理方法,发现给图像降噪,也许效果会更好。思路是这样的,每张图片的颜色都是RGB三种颜色构成,对于每个像素点,RGB每种颜色的深浅范围都是[0,256],数字越小,颜色越深。由于图片上的干扰线颜色大体都比字母要浅,这也意味着它的RGB值要比字母小,通过分析RGB值应该可以滤掉大部分的噪声,代码如下:

机器学习之验证码识别

  处理+切割后的验证码图片:

机器学习之验证码识别

  是不是效果比之前的好了很多?其实在进行降噪后切割前,我尝试使用tesseract-OCR工具进行识别,效果也不算差,正确率应该有60%~70%。但咱并不满足于这个正确率,于是继续往下撸。

  Step 3.图片预分类

  至此,我已将1000个验证码通过降噪处理及切割后,生成4000个字母样本集。此时,OCR可以上场了。对于Python,有个pytessearct库可以使用到OCR功能,对分割后的图片进行预分类。第一次进行分类时,发现各种类别都有,有归类成数字的(比如有的字母Z被识别成2),有归类成小数点“.”的(很伤心,大部分很明显的字母O全被归类为点),有无法识别的,这就尴尬了,难道还是得手工去归类?于是又各种Google。后来看到有个方法或许能有作用,就是修改Tesseract-OCR文件里的digits文件,路径:C:\Program Files (x86)\Tesseract-OCR\tessdata\configs\digits,简单说就是将digits文件里的白名单限制为字母,然后在代码里加入digits参数,那么OCR则会优先将图片归类为字母,而不会出现数字和字符等情况。

10.jpg

11.png

  再次进行归类,这次预分类效果好了很多,遗留的问题就是将大写的i(“I”)归类为“L”,“g”和“q”混淆,‘t'和'f’混淆,还有各种奇葩混淆('n'和'r'什么鬼的),但总体上识别错误的占比不高,稍微花了点时间手工纠错,预分类基本就这样妥了。

12.png

13.png

  代码如下:

14.png

  Step 4.特征提取

  这一步是为后续的机器学习模型准备训练集,基本上,目前所有机器学习的模型都是基于向量操作,所以我们的特征提取实际上是将每张图片转化为向量,思路是将图像的每个像素点进行灰度化+二值化,在这个实验上,我是将像素值低于或等于128的设置为0,高于128的设置为1,之后将各个图像对应的字母放入向量最后一维,并存储到train_data.txt。

15.png

  结果:

16.png

  Step 5 机器学习-SVM

  在这个案例里,我采用的SVM(支持向量积)模型。其实对于机器学习,我也是近期才接触,理解的也不深,SVM其实是一种分类方法,在这个算法中,我们将每个图像(即向量)在N维空间中用点标出,N是该向量的所有特征总数,在此案例里,我们的图像有300个像素点,即N=300;举个例子,如果我们只有身高和头发长度两个特征,我们会在二维空间中标出这两个变量,每个点有两个坐标(这些坐标叫做支持向量)。

17.jpeg

  现在,我们会找到将两组不同数据分开的一条直线。两个分组中距离最近的两个点到这条线的距离同时最优化。下图中,中间的线是两组中距离最近的点(即A、B点)到达黑线的距离满足最优条件。这条直线就是分割线,测试数据落在直线的哪边,就把它归为哪一类。

18.jpeg

  在这个案例里,我们是通过scikit-learn来实现。SVM支持多个核函数,例如高斯核、线性核、poly以及sgmoid核函数,在这里,我们通过scikit-learn的GridSearchCV来对参数进行最优化选择,对于这个案例里,线性核效果较好,所以我使用线性核训练。

  另外,案例里使用了joblib模块进行持久化,主要是方便后续预测时不需要再次进行训练。最后,则使用了5折交叉验证来对结果进行检验。代码如下:

19.png

20.png

21.png

22.png

  使用5折交叉验证来对结果进行检验,最终准确率达到100%左右!

23.png

  在最后,为了实际验证机器学习效果,我再次爬了100张验证码放在文件夹E:\lect\pics1\里并进行预测,结果预测正确率确实就是在100%左右。

24.png

  Yeah,finished!

  总结:作为一个新手,大概也只能挑战这种难度的验证码了。今晚在登录微信公众平台的时候,看到这样的验证码,吓shi了,人眼识别都填错了几次,有空再研究看看是否也能做到机器识别。

25.png


上一篇:百度ocr实现验证码自动识别
下一篇:人性化的滑动验证码识别

周一至周五 9:00-18:00

尖叫网络

尖叫数据