随着OpenCV4.0.0的正式Release,OpenCV已经走过了18个年头,OpenCV4中加入一些有意思的新算法,其中就包括二维码识别。OpenCV的二维码识别究竟如何呢?和其它开源二维码识别库相比有哪些优劣呢?博主将带你简析代码,分析性能。一、二维码识别概述
二维码的识别分为两个阶段,第一阶段是检测与对齐,第二阶段是解码。解码没什么好说的,目前主要问题在检测阶段,一般是检测算法决定了二维码识别算法的性能。
博主将OpenCV4中的二维码检测模块独立出来,方便我们维护、修改和学习。(OpenCV2以上的支持就可以了,如果是OpenCV4也没关系,使用了其它namespace,完全不会和OpenCV原本的检测代码冲突),下面这个仓库中的代码可能是博主改进过的,如果想下到和OpenCV4一模一样的代码,在分支/标签那里选 tag opencv4 下载就可以了。
P-Chao / QRCode-CV4
qrcode detection enhanced with opencv4.0 qrcode
二、查找定位点
1.定位点的几何特征
三个定位点黑白间隔的宽度是1:1:3:1:1,所以先水平扫描全图,保存候选点,在垂直扫描全图,保存可能点
2.聚类特征点
对于查找到所有的可能点使用kmeans聚类,聚类到三类,就会有三个定位点的大致位置了
3.连通域标注
通过聚类特征点,就可以找到其边缘点,然后floodfill(水漫金山),黑色的回就被填充起来的,找到回自就是未来后面查找对齐点。
三、查找对齐点
最开始会找到下图中的三个红色的特征点,这个比较容易理解,因为左上角的点到其它两个点的距离是差不多的。
然后在左下角和右上角的回字上,找离左上角红点最远的点,那么可以得到两个蓝颜色的特征点
根据红蓝点连线的交叉点,就可以得到第四各顶点,这样对齐需要的点我们就都找到了
在这里,因为右下角的顶点可能定位不准,OpenCV做了其它工作,就是如果这个点篇左上,那么通过联通域标注+凸包顶点检测的方式,将这个点外扩。但是如果这个点本身偏右下,那么OpenCV就无法处理了,改进后的方法见我的下一篇博客。
四、仿射变换
OpenCV中选取了5各点对,除了四个顶点,还有中心点(通过对角线的交点计算得到),这五个点来算Homograph,然后Warp回去,就得到了一个正对着我们的二维码了。
五、解码
对正对我们二维码,还是根据回字上的特征,找到水平和垂直的时钟延(二维码编码格式中,在回字之间会有黑白间隔的时钟延,不懂的话查下二维码编码格式),根据时钟延数量来判断二维码是哪种格式。然后根据格式进行比特采样,得到01比特后就直接送进解码库取解码了。
OpenCV直接调用的开源解码库quirc,解码这部分完全没必要自己写。
六、对比与分析
对于视角不是特别大的情况,ZXing更鲁棒一些,尤其是图像质量不高时ZXing效果更好。如果拍摄图像质量高、二维码清晰、边缘明显,那么OpenCV的二维码检测可以在更大视角上work。opencv的二维码检测虽然不完美,但是在一些场景可以work,速度很快,代码也不到1000行,也无法应对多个二维码同时出现的情况,但是毫无一位以OpenCV为基石,接近商用将更加容易,其检测二维码的思路值得学习和借鉴。
关于代码速度,我认为OpenCV的败笔在于使用了费时的AdaptiveThreshold,该函数占据了检测时间的70%,所以我们使用大津法二值化或者其它二值化方法,就可以提升速度(不过这要求我们在解码时额外做些工作,才不至于降低性能,参见我下篇博客)
(发现目前最牛逼的二维码解码算法在微信,halcon、opencv、zxing、zbar搞不定的,weixin wechat都能搞定*^_^*)
最后,纪念OpenCV4.0.0发布。
2022.10.05补充:
发现opencv-4.6.0开源了微信的QRCode识别,以后又可以少造一个轮子,文档:
https://docs.opencv.org/4.6.0/dd/d63/group__wechat__qrcode.html
博主您好,关于源码中查找定位点的方法我有些地方不太懂,能请教一下吗?
我也发现微信最牛逼。哈哈
还有支付宝扫一扫咋不比较下,支付宝比微信识别率要高挺多的哈。