不知道哪天下午突然想起来要搞(fuck)学校教务网的验证码,像我这种不分轻重缓急的人于是立马就开始写了……(其实当时也没什么要紧的事)虽然青果做的这个垃圾教务不难绕过验证码,从学校的信息门户进教务就可以了,但还是要试一试识别验证码~

先贴上GitHub地址:fuck-csujw 下面的解释配合代码来看。说一下最终的整体思路:

1、去背景色

下载了很多张验证码图片观察一下,其实这个验证码是比较弱的。主要包括这样几部分:背景色(蓝灰等颜色)、背景中一条黄色的色带、噪点、四个字符(粘连程度很小而且大部分粘连的字符颜色不同)。那首先就去背景色吧。读取了图片以后先把颜色索引值保存在二维矩阵里便于处理。在处理的过程中找到那几种背景色,包括黄色在内,统统变成白色。

下面直接去掉他们

2、去噪点

这一步还是有点曲折。刚开始通过一个点四周的点是不是3个以上是白色来去噪点(因为噪点也有可能是一小团所以判断是大于3个白色),发现数字1还有I、J这些字符上面那一横也有可能被去掉,后来改用DFS的方式。DFS所有不是空白处的点,如果这一团的大小小于10,那就是一团噪点同样DFS来抹白他。这样就基本去掉了不跟字符粘连的噪点。在字符内部的噪点就不管了,因为他们比较少对识别的影响也不是很大。

这里我遇到的一个问题是我这里PHP默认的递归层数应该是由于我装的XDebug扩展的限制,只有区区几百层,需要修改php.ini。那就在[XDebug]中加入一行:

去噪点代码就不贴了,是在Denoise.php文件中。

3、确认字符的范围

现在图片就只剩下字符了(当然还有字符身上的噪点)。也就是从左到右,从上到下扫描一下字符的范围,来把他们抠出来进行识别。这里比较简单,但是需要注意字符的粘连。在从左向右扫描过后,判断出来的字符的个数,小于4个那肯定就有粘连了。

4、分割粘连字符

分割字符我只做到了两个字符的粘连,由于这个验证码比较弱,三个字符以上粘连在一起的可能性实在太小了我还没遇到,所以这种情况干脆不予考虑。

5、取出四个字符

扫描完范围,解决了粘连问题,这时候就可以根据范围取出四个字符了。因为学习算法中输入为固定个数的特征,在这里取出字符的时候,每个字符固定为25 x 25大小,空白地方为0,有颜色部分统一为1。

6、转化为向量

这时已经有4个字符了,就将他们按照行展开,每个字符变成一个25*25=625维的向量。处理很多个验证码并将获得的字符编程625个数存入data.txt文件,用于训练。然后还要人工先识别这些验证码,放入target.txt。

data.txt和target.txt这两个文件构成了我们的最初的训练集。

7、读取训练集(Python)

因为Python的numpy库用矩阵方便很多,下面的机器学习算法用Py完成。

8、逻辑回归、梯度下降

因为比较菜嘛,上学期学的全忘了……那就先用个简单的逻辑回归吧。梯度下降算法也是没有优化。(后来改进下梯度下降对准确率也没有大影响)h()为预测函数,sigmoid是逻辑回归中的s形函数,保证结果在0和1之间。

这里也记录下梯度下降改进吧。上面的是批处理的梯度下降,每次下降都使用全部数据。可以使用随机部分数据,则变成随机梯度下降。theta这里是固定下降,改进梯度下降则是在训练过程中theta由大变小。那么下降速度就是从快到慢,可以更快的下降到预期点。上面也没有使用代价函数而是固定的迭代次数,当然可以使用代价函数来判断是否达到预期位置。

在这个验证码中,要训练36个分类器分类出0-9 a-z。然后我把这36个分类器存为625*36的矩阵保存在h.txt中。

9、识别

又回到PHP,在处理过验证码图片得到向量之后,通过训练出的参数计算36个分类器的值,选出最大的那个就是可能性最大的那个字符。代码如下

 

就此得到识别结果。我这里到现在训练的正确率可以达到85%左右。

 

另,自动获取训练集

有了开始的正确率,就可以通过这个自动识别出来,然后提交教务进行验证。验证通过那么识别结果是对的,保存识别结果和图片。验证失败也保存图片用来人工识别。最终得到对的和错的验证码,全部转化成向量,和识别结果一起再送入训练机,用来改善识别成功率。这部分代码见autocheck.php

 

评论

电子邮件地址不会被公开。 必填项已用*标注

你可以使用以下 HTML 标签和属性:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">