文章目录

  • 基于轮廓嵌套的识别方法
  • OpenCV 中的 QRCodeDetector

最近在B站上看到了 PaperClip 关于二维码的视频,主要讲的是二维码中的纠错码。但是在读取二维码内容前需要先定位并矫正二维码位置,视频中有一个片段展示了二维码定位的流程:RGB转灰度,局部阈值二值化,形态学滤波,Harris角点检测,凸包,提取轮廓,计算顶点角点,透视变换。
说到检测二维码,我的第一反应是“跑一个Faster RCNN,返回bbox同时计算旋转角度”。但这想法立马就被自己否定了,二维码这么明显的结构特征,还需要用神经网络吗?hard code 都可以啊,效率还高得多。于是埋头自己构思了一个检测的方法。(这里我就不对二维码的构成细节进行累述了,直接进入正题。)

基于轮廓嵌套的识别方法

这是我自己设计的一套算法流程,因为只是空闲时间瞎搞搞的东西,想尽量用现成的 API 来做,所以可能有点绕弯子。代码放 Github 了,欢迎斧正。

https://github.com/New2World/LittleProjects/tree/master/QRCodeDetect

因为检测二维码最关键的就是检测三个定位框,而这些定位框最明显的特征有两个:嵌套关系方形。针对这两个特征做文章,先提取轮廓,然后检测三个三层嵌套的方形或平行四边形轮廓。

首先,对图像进行预处理:缩放,灰度,二值化,形态学开操作(先腐蚀后膨胀)。然后通过 OpenCV 的 findContour 函数获取所有轮廓,如下图。

可以看到有很多轮廓嵌套,而其中最特别的就是三个定位框。正如上面所说,它们是方形且嵌套的,那么我们通过返回的 hierarchy 可以计数每个轮廓的嵌套层数。由于我们不能确定每个定位框内部会不会因为噪声或一些其他因素影响而产生额外的轮廓,因此只要轮廓嵌套数大于 3 都可以。

嵌套关系算是考虑到了,然后要做的就是判断是否是近似的矩形。之前做过图像中找圆,基本原理是检查轮廓周长和面积的关系比例是否近似 π \pi π。依葫芦画瓢,通过检查周长的平方和面积的比例是否接近 16 来判断是否近似矩形。你可能会问为什么不检查边长相等?当然可以,但是 API 返回的轮廓并不规则。同一条边上可能不止两个端点,而是很多点构成了一条边,这样的话还得判断哪些点在一条边上,麻烦。由于我们嵌套条件是松弛过的,因此在判断矩形时就得把松弛了的条件拉回来,即嵌套的轮廓中必须有三层矩形。通过这两步筛选下来,剩下的轮廓基本就只有三个定位框了。如果剩下的轮廓个数不是三个那就判检测失败。

接下来需要矫正二维码方向。有很多方法可以做到,比如先通过三个定位框构建一个直角三角形,将直角顶点旋转到左上;或者计算三个定位框间的距离,距离相等或相近的边的公共框旋转到左上……但我记得 OpenCV 有个 minAreaRect 函数能找到外接矩形同时返回这个矩形的旋转角度。因为三个定位框基本位于同一平面,所以大致上可以认为它们的旋转角度一样且就是二维码的旋转角度。这里的旋转角度是指将二维码转正的角度,而不是旋转到正确方向的角度,这是接下来要做的。

因为已经把二维码转正了,那么整个二维码可以分为四个象限。假设以左上为原点,垂直的轴为 x 轴,水平为 y 轴,那四个定位框可能的位置可以表示为 [ 0 , 0 ] , [ 0 , 1 ] , [ 1 , 0 ] , [ 1 , 1 ] {[0,0],[0,1],[1,0],[1,1]} [0,0],[0,1],[1,0],[1,1]。为了方便表示,我们将坐标叠起来写成矩阵:

  • 旋转 0°: { [ 0 0 ] [ 0 1 ] [ 1 0 ] } ⟹ [ 1 , 1 ] \begin{Bmatrix} [0 & 0] \\ [0 & 1] \\ [1 & 0] \end{Bmatrix} \implies [1,1] ⎩⎨⎧​[0[0[1​0]1]0]​⎭⎬⎫​⟹[1,1]
  • 旋转 90°: { [ 0 0 ] [ 0 1 ] [ 1 1 ] } ⟹ [ 1 , 2 ] \begin{Bmatrix} [0 & 0] \\ [0 & 1] \\ [1 & 1] \end{Bmatrix} \implies [1,2] ⎩⎨⎧​[0[0[1​0]1]1]​⎭⎬⎫​⟹[1,2]
  • 旋转 180°: { [ 0 1 ] [ 1 0 ] [ 1 1 ] } ⟹ [ 2 , 2 ] \begin{Bmatrix} [0 & 1] \\ [1 & 0] \\ [1 & 1] \end{Bmatrix} \implies [2,2] ⎩⎨⎧​[0[1[1​1]0]1]​⎭⎬⎫​⟹[2,2]
  • 旋转 270°: { [ 0 0 ] [ 1 0 ] [ 1 1 ] } ⟹ [ 2 , 1 ] \begin{Bmatrix} [0 & 0] \\ [1 & 0] \\ [1 & 1] \end{Bmatrix} \implies [2,1] ⎩⎨⎧​[0[1[1​0]0]1]​⎭⎬⎫​⟹[2,1]

通过上面沿着 axis=0 求和的结果进行映射到旋转角度就能将二维码旋转到正确的方向。最后就只需要剪切图片只留下二维码区域即可。这里其实应该做仿射变换来调整二维码可能出现的一些形变,但我省略了……

OpenCV 中的 QRCodeDetector

OpenCV 也提供了一个检测二维码的类 QRCodeDetector。它的算法应该是基于[1]这篇论文的,主要是通过定位框每个黑白部分的长度比进行检测。

在 OpenCV 源码的检测部分有两个函数 searchHorizontalLines 和 extractVerticalLines,先使用水平扫描找出黑白段长度比为 1:1:3:1:1 的部分作为候选,然后用垂直扫描筛选水平扫描得到的结果并返回两个方向上都满足长度比例的部分。接下来就用 KMeans 对所有候选进行聚类,使得最后合并到三个点,即三个定位框的中心点。如果聚类得到的有效的点不足三个,则判检测失败。在之后二维码转正的过程中,OpenCV 用的是检测出的三个定位点的夹角,夹角最大的是左上顶点,然后以此来对图像进行仿射变换。
想要具体了解实现细节还是得看看源码,不过 OpenCV 的识别并不是很完美,目前效果最好的应该是微信的二维码扫描引擎 QBar


[1]: Belussi, Luiz , and N. Hirata . Fast QR Code Detection in Arbitrarily Acquired Images. Sibgrapi Conference on Graphics IEEE, 2012.

【写着玩】二维码检测及定位相关推荐

  1. AprilTag二维码检测和定位

    AprilTag简介 AprilTag类似于二维码QR codes(Quick Response Code:全称为快速响应矩阵图码) AprilTag可用于多种用途,包括相机标定.目标大小估计单目距离 ...

  2. 【深度学习】【caffe】【python】【docker】微信 二维码检测,手写数字识别

    文章目录 介绍 docker环境 MNIST 数据(废弃) 微信二维码 微信二维码 python代码试试 用于造yolov5的目标检测数据 了解caffe,使用caffe,做个小例子熟悉caffe. ...

  3. Jetson Nano 从入门到实战(转载)(案例:Opencv配置、人脸检测、二维码检测)

    目录 1. Jetson Nano简介 2. Jetson Nano环境配置 2.1 开箱配件介绍 2.2 烧录系统 2.3 开机和基本设置 2.4 开发环境配置 2.4.1 更新源和软件 2.4.2 ...

  4. Jetson Nano 从入门到实战(案例:Opencv配置、人脸检测、二维码检测)

    目录 1. Jetson Nano简介 2. Jetson Nano环境配置 2.1 开箱配件介绍 2.2 烧录系统 2.3 开机和基本设置 2.4 开发环境配置 2.4.1 更新源和软件 2.4.2 ...

  5. OpenCV4.0 快速QR二维码检测测试示例

    点击我爱计算机视觉标星,更快获取CVML新技术 近几年由于微信大力推广移动支付,二维码已经成为手机App的标配,在众多种类的二维码中,QR码是最为流行的. 刚刚发布的OpenCV4.0-Alpha新增 ...

  6. OpenCV C++案例实战三《二维码检测》

    OpenCV C++案例实战三<二维码检测> 前言 一.二维码检测 二.二维码识别 1.通过findContours找到轮廓层级关系 三.二维码绘制 四.源码 总结 前言 本文将使用Ope ...

  7. 目标检测:二维码检测方案

    Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/cou ...

  8. OpenCV4学习笔记(58)——二维码检测与识别

    本次要整理的笔记内容是在OpenCV中对二维码进行检测与识别.二维码对我们来说可以说是非常熟悉的,乃至于每次出门都会和"扫码"挂钩,可以说二维码已经渗入到我们生活的方方面面.那么二 ...

  9. Opencv之微信二维码检测与解析

    简介 微信二维码检测器是由微信计算机视觉团队(WeChatCV)提供的一个高性能.轻量级的二维码检测与解码库.它已广泛应用于腾讯的各种应用,包括微信.微信.QQ.QQ浏览器等.微信二维码检测仪有四个主 ...

最新文章

  1. Java项目-基于SSM实现律师事务所管理平台
  2. 使用BeanUtils.copyProperties进行对象之间的属性赋值
  3. Vim - 编辑多个文件
  4. Linux vi/vim
  5. ajax 导致 css 延迟_AJAX远离404
  6. SpringBoot 数据处理
  7. 数据库连接配置 app.config web.config
  8. shell自定义数组元素分隔符
  9. android中自定义动态壁纸
  10. [一本通]题解 1031
  11. python查看保留字_Python 关键字(保留字)一览表,含查询方法
  12. 练习题《中心对称矩阵》
  13. My Seventy-first Page - 目标和 - By Nicolas
  14. 计算机中的right函数,excel的right函数的使用教程
  15. 桃花院长:怎么找对象?相亲过来人告诉你...
  16. android手机照片恢复,安卓手机照片怎么恢复?简单恢复方法分享
  17. .Net开发 开发工具使用vs C盘占用空间不断增大
  18. [BZOJ3811]玛里苟斯
  19. 粤港澳大湾区新地标,128米高“湾区之光”摩天轮重构深圳天际线
  20. miRNA的特征、功能及识别方法等详解

热门文章

  1. 当使用广告拦截器时,有些页面无法查看,应该怎样解决?
  2. 解读:基于订单流、技术分析与神经网络的期货短期走势预测模型
  3. RFID 负载调制和反向散射调制
  4. 淘宝商品详情API|获取宝贝SKU、主图、评价等API接口
  5. 在单面打印机上使用WPS实现手工双面打印
  6. python实现自动批量下载邮箱附件--GUI
  7. ⚓写写5G网速及页面提速中的延迟加载Lazyloading
  8. canvas路径,描边与填充
  9. FPGA|VGA的8色彩条的实现
  10. SpringMVC之405错误码