原创
2017年07月08日 18:56:26 最近工作中开始使用opencv来做一些跟图像相关的机器学习项目,开始对图像处理产生浓厚的兴趣。搜索资料的时候偶然看到有一些使用opencv读取摄像头的小demo,在输入烦人的阿里云数加身份宝验证码的时候,突发奇想,为何不用摄像头自动识别验证码,实现快速输入。当然,出于学习目的可以用摄像头来输入,如果是公司里,追求短平快和稳定,直接对手机截屏进行识别才是正路。 说干就干,公司台式机没有摄像头,先买一个。19块的看上去有点low,太便宜的一个是担心容易坏,另外是担心拍出来字符不清晰。29的看上去还可以, 硬件到手,来列一下接下来我们需要完成的任务:
opencv读取摄像头我们的需求比较简单,从 开发的时候可以先从摄像头截取几张图来调试代码。这样图片是固定的,方便debug和调整参数。然后根据相机方向旋转图像。opencv没有直接旋转90度,180度这种函数,但是简单的组合transpose和flip可以实现。 ROI识别找到了几篇相关的文章,比如这篇。但是没有完整的代码,所以自己简单尝试一下吧。
因为我们的场景比较简单,通过opencv的简单函数基本可以把ROI提取到,其他类型的图片识别问题就得需要复杂点的方法。比如调试的时候,我不小心截图把窗口边框也截图进去了,这样找boundingBox识别到的是窗口那个框框,就有问题了。把用到的这几个函数对应的文档仔细读读,还挺简单的。 BoundingBox提取出来之后,用一些小trick过滤出我们想要的数字即可。注意数字1比较窄,要特殊照顾一下。
数字OCR刚开始以为这种打印字体识别起来应该很简单,比如我之前这篇博客介绍的《Digit Recognizer – 从KNN,LR,SVM,RF到深度学习》,结果被现实狠狠打脸了。 算了,放大招mnist数据集
可能网络不太好,可以自己到mldata.org下载,打开fetch_mldata的源码看看就知道了,下载用的是matlab格式的数据。 然后加载的时候发现报错了
查了一下,是scipy版本过低,https://github.com/ContinuumIO/anaconda-issues/issues/650。自己升级一下吧。 然后用svm训练一把,发现训练很难收敛,结果也很差。最后终于找出来是忘记输入归一化。简直吐血,说多了都是泪。 但是bug改正后,发现效果居然比原来的更差了。 又开始怀疑人生了。。。 分析了一下,训练数据是手写体的,有各种歪歪曲曲的数据,跟我们的机器字体分布不同。而且图片没有crop到中心且最大化,灰度保留[0,255]的范围,没有离散化。load_digits的数据反而把灰度离散化成1到16。 怎么办,svm这种算法解释性并不好,训练出来的模型也难以人工调整。但我们的ground truth是比较明确的。 最后想出一个办法,直接屏幕截图把0-9十个数字搞到,然后比较跟哪个数字比较接近,懒得去查到底是什么字体,反正直接截图挺快的。这种土方法可以算是knn在n_neighbors=1的特例。所以我们用sklearn提供的KNeighborsClassifier来实现就好了。
识别的时候,会把图像缩放到固定大小,但是数字1提取处理的图像比较窄,拉伸到标准长宽之后就变得很像7了。所以数字1稍微特殊处理一下,特别窄的直接输出1。 结果发现效果贼好。 simple http server很简单,例子 http:///articles/1480.html 自己重写一下do_GET就可以了
但是,随着https的普及,问题来了。阿里云的页面是https的,如果插件嵌入我们的http内容,会报错
不过还好,python代码只需要加一行
问题是怎么生成https的证书文件。找了一些方法,比如 这个虽然勉强可以运行,但是有难看的不安全标签。 最后还是在这里找到解决方案 https:///questions/43929436/subject-alternative-name-missing-err-ssl-version-or-cipher-mismatch 现在好看多了 openssl在git Bash有,如果你有git,可以不用单独再安装。 浏览器脚本chrome安装一个Tampermonkey插件,然后就可以简单添加各种小脚本到我们需要的页面去执行。 登陆页面的url是https://account.aliyun.com/mfa/authMfa.htm* 我们要做的操作其实只有两步
因为是跨域,不能直接用ajax。但逻辑比较简单,可以不用jsonp,http接口直接返回上面两行代码就行。 最终效果
小结可以发现,用摄像头直接获取图片由于环境和输入条件的不同,会出现画面倾斜变形,关照不足等情况,为了提高算法鲁棒性,是需要继续优化的。但是我们这个场景比较简单,而且手机屏幕是自发光的,问题不太严重。这个识别问题继续扩展一下就是车牌识别了,继续学习可以参考EasyPR 另外就是算法实际中应用会发现各种坑,有时候简单粗暴的方法确实有效。 |
|