效果
最后总的效果还是不错的,从测试集上面看,单个字符的识别准确率平均能达到90%左右,最好的时候达到过93%。我想这也差不多达到了优化的极限了,毕竟在图片样子不标准,位置更不标准。而且仅仅在截取子图这一步上就会与实际情况有些出入,况且一些细微的差别就算是人脑也容易出错,比如1和7、i和j等等。加上我使用整个数据集的量不算大,满打满算也就500张图,所以能进行33个字符的识别已经挺不错的了。官网上60000张图的数据集的学习也差不多达到了93%而已。
总结
代码就是这样了,不算多,也就小几百行。但是很多细节的把握以及参数的调整却让我头大了很久。
开始的时候也只是照着mnist的样子直接二值化后(仅仅调用了blur1函数)交给学习机来学习,效果可想而知。。。正确率只有可怜的10%+,让我一度怀疑这个算法的可行性。然而冷静下来想了想是不是因为线条过细导致信息量不够大。于是就像办法加粗线条,最后选择了用高斯模糊来进行边缘处理再二值化。果然,这么一搞就把正确率调到了50%左右。但是这个识别率也实在是太低了,想了半天又没啥办法,试着调节学习算法中的参数效果也并不理想。最后盯着8的两个圈圈看的时候突然想起来是不是可以通过数圈圈的个数来区分一些数字!于是写了一个种子填充,果然将正确率提高到了70%。有了这个经验,我想都没想就再加进去了count_fill和count_border函数计算两个特征值,最后将正确率提高到了90%。
除了算法设计部分,由于是第一次使用PIL,对图片的处理让我蛋疼了好久,比如二值的图像和灰度的图像之间性质的差别问题,图像矩阵中int到bool的转化问题,内存中的图像对象的显示错误问题等等,都特别让人伤脑筋。(不过多谢度娘)
还有,这次也是我第一次用python写这种小项目。深刻觉得python这种脚本语言还真是方便,比如ipython的即时反馈,数组列表字典元组的使用,文件和文件夹的IO,函数的调用和使用(竟然可以在函数的内部定义另一个函数,一个函数就能做到C中一个类才能做到的事情)等等。不过调试起来还是有点麻烦的,万一程序有点小错,他报的错经常会跳到好多地方去,让人摸不着头脑。
虽然这种代码的意义不大(毕竟只适用于这个特定的验证码),但是做为自己写的第一个能用的机器学习程序,还是挺有里程碑意义的。自己mark下。
附github上的完整项目:Zhengfang_CaptchaRecognition