记得二轮选课时,因为手滑退了门政治课,结果连抢几天,也没抢到理想的政治课,然后从那时开始,我就产生了写个刷课机的想法。

不过复旦的选课系统每次提交请求都要填写验证码,虽然复旦的验证码背景没有干扰,字符位置均衡,但因为有严重的扭曲,看起来比较恶心,即使是人眼识别率也不高,加之当时有别的东西要折腾,没有时间和心情去研究验证码识别,就没有再搞下去。

 

前段时间比较空,Baldr Sky Zero也没有想象中的那样把我吸引住,我就去研究了下验证码识别。

看了不少资料,主流的验证码识别基本都是基于机器学习,其中SVM神经网络是被最为广泛使用的方法

识别的简单不重大致就是给一堆识别好的样本,提出其字符特征,交给程序去训练,最终可以得到一个训练好的模型,再用这个模型去识别就行了。

然后学一些SVM相关的东西,抛开繁琐的严格数学证明,SVM的大概思想还是比较好理解的,而且还有libsvm这种库直接拿来用。。。最后我决定选SVM作为验证码识别的最后一步的机器学习算法。。。

验证码识别的步骤基本都是模板式的

因为背景没干扰,转灰度后随便选个阀值做二值化就行了

然后我手工试了十多张数据,结果发现字符分割直接找固定位置分割所得的效果就很好

当然因为扭曲的关系这么切可能会把旁边字符的一部分切进来

这只需从边界做BFS,判断8联通块里黑的像素数量是否小于一个阀值就行了(比如4)

事实上我试了下切开字符直接调tesserart-ocr的进行ocr的验证码识别率都有20%左右

然后就可以对字符做归一化

将里面的字符抠出来扔到16*12的图片里就行了

至此,验证码识别的大部分东西都解决了

下一步就是从归一化的图片中提取特征向量了

因为我看的几篇论文里最终使用的特征向量都是30,40维的,这让我误认为直接把每个像素的0,1做特征,最后会得到16*12+1维向量,这样做维数会太多,SVM可能跑不出来

我去zjk寝室让他帮我一起手动识别几百个字符做训练和测试用,结果正好在zjk的寝室遇到lym大神,得知他在选课时就折腾过这个,也用的SVM,

他告我这些字符扭曲是按sin函数来的(。。。我居然没注意到),直接猜几个参数就可以还原回去

我问他字符特征向量是怎么提取的,他告我他就是12*10的图片每个点0,1值,最后一个121维的向量。。。原来100多维也可以跑出来。。。

然后他还友情提供了我1300多个识别好的验证码共计5000多个字符

我取了其中500个验证码,共计2000个字符做样本,加上我原来自己识别的100个验证码,最后那2400个字符做为训练样本,直接给libsvm里easy.py自动训练优化参数,并同时提供了200个验证码,800个字符给libsvm做测试,发现后来生成的模型对那个测试数据的识别率已经是100%了。。。

用这个模型完成了最后的程序,识别一次验证码的耗时大概0.06s左右,还算可以,在http://xk.fudan.edu.cn/xk/提交了1000次,只有15次返回的是验证码错误,98.5%的识别率,已经远超人眼识别率了。。。(主要它能识别8,p这种变形的很诡异的字符)

 

最后产品的源代码

https://github.com/Aixile/FDUCaptchaKiller

图片处理使用了OpenCV,自己编译了libsvm,直接调用了svm.h中的函数

Windows x64版本 http://itai75.org/FDCK(x64).zip

之前我用的样本随手选的,随机性不够,1月初改了下就识别率1000/1000,编译后的版本一直没放上来

https://blog.girls.moe/FDUCaptchaKiller.zip

 

至于刷课机什么的,我就不提供了……

 

2 Responses to 复旦选课系统的验证码识别

  1. dnc1994说道:

    大牛你的这篇博客以及simy86那篇下面的的zip为啥都不能下载了T_T

    • Aixile说道:

      不好意思,之前blog搬服务器的时候只把wordpress移过去,其他没管
      现在修复了

发表评论

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