验证码的识别可以说是一个非常困难的问题,更何况现在有一些验证码让人来辨认都有些不容易,当然正如我标题里说的,我这里讨论的是一种简单的验证码,具体来说就是经过旋转、缩放之后再加上一些随机线条作为干扰而得到的图片,如右图所示。其实这个问题最开始是 MSTC 第四届趣味程序设计竞赛中的一道题,这个学期上了一门《计算机视觉》课,最后要求交一个 Project ,老师给了一些题目,也可以自己想主题,于是我就定了这个主题。
由于最近各种 deadline ,我也没空把详细过程再用 blog 的方式写一遍了,如果感兴趣可以直接看我的 Report 文档以及完整的代码。
其实这个问题我在当时趣味程序设计竞赛的时候就尝试解决过,不过我当时用的办法是 PCA ,事实上,我尝试了 PCA 、LPP 以及 NPE ,从各种 paper 上还有理论推导中的道理来看,似乎都是后两者要更加先进一些,然而结果却是 PCA 最好,当时就令我有些诧异。其实我一直以来都有一些极端的“理想”,就是总希望有那么一些非常“自动化”或者“傻瓜化”的方法,把问题放进去就能得出结果,例如我在中学的时候凡是遇到几何题,几乎都是首先尝试建立坐标系用解析几何的方法来做,虽然构造各种精巧的辅助线来解决问题是许多人的最爱,然而我似乎不太喜欢这种“专门针对某一个问题要重新想一个方法”的方式,却更偏爱通用性更强的办法,就算有时候计算会变得很繁琐,但是最后通常总是能算出来的。在这里也一样,我似乎有一种愿望,或者甚至是一种错觉,我们可以有一种算法,只要把数据放进去,就能得出最完美的结果来,比如通常特征提取和构造的问题,我似乎不太喜欢使用太多 domain 相关的先验知识来人工构造 feature 的方式,而比较偏爱直接使用最原始的 feature ,然后使用降维来自动选择——我甚至在想,是不是首先通过升维(例如,使用 Kernel 的方法)来够找更多的特征以增加数据的区分度,然后再紧接着用降维的方法来提炼,是不是就可以完美地解决一切特征构造和抽取的问题了?
当然,现在我知道这只是一个美好的愿望,其实我一直也都知道这只是一个愿望了,只是仍然有点不自觉地往那个方向倾斜。其实这样的问题,也许如果我们可以得到无穷多的训练数据和无穷多的计算资源的话,应该是可以实现的啦,哈哈!
总的来说,我正在纠正自己的一些偏见,所以在学习了《计算机视觉》这门课之后我决定做一些尝试,特别是在知道了有一种叫做 SIFT 的特征可以保持旋转和缩放的不变性的时候,我就在想——这不就是正好是解决这个问题所需要的吗?所以我定了这个题目。然而不幸的是当我做出最后结果的时候发现实际结果并不好,还是经典的 PCA 最强。当然,到这个 deadline 前夕,肯定不能再换题目了,另一方面,虽然我一开始的设想被验证是错误的,但是这个 project 并不是没有意义的,我把它和 PCA 做了一些对比,并对结论做了一些分析,自己的理解也更深刻了一些,可以说还是收获挺多的。
另外就是这次我对噪音过滤的方法做了不少对比和尝试,最后的结论是中值滤镜最好,我印象中自己在做趣味程序设计竞赛的时候只做了非常简单的处理,于是好奇地找出以前的代码来看了一下,发现居然就是一个中值滤镜而已!不过当时不知道 OpenCV 也没有学过滤镜什么的,怎么找到这么个方法的来着?真是想不起来了。不过,有时候翻翻自己以前写的代码,确实会如同在论坛上考古一样别有一番趣味的,代码里也散发着岁月的味道,不是吗?