opencv 二维码_【从零学习OpenCV 】QR二维码检测

f925f3543cbd3b213e8257c1dc5cd110.png

本文首发于“小白学视觉”微信公众号,欢迎关注公众号

本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究!


经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍《OpenCV 4开发详解》。为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通,提前在公众号上连载部分内容,请持续关注小白。

二维码被广泛的应用在我们日常生活中,比如微信和支付宝支付、火车票、商品标识等。二维码的出现极大的方便了我们日常的生活,同时也能将信息较为隐蔽的传输。二维码种类多种多样,有QR Code、Data Matrix、Code One等,日常生活中常用的二维码是QR二维码,该二维码样式以及每部分的作用在图7-30给出。二维码定点方向有三个较大的“回”字形区域用于对二维码进行定位,该区域最大的特别之处在于任何一条经过中心的直线其在黑色和白色区域的长度比值都为1:1:3:1:1。二维码中间具有多个较小的“回”字形区域用于二维码的对齐,根据二维码版本和尺寸的不同,对齐区域的数目也不尽相同。

cc4dccb2fd0aa9fc3e5fc1e972964634.png
图7-29 QR二维码各部分的作用

QR二维码的识别过程大致分成两个过程,首先搜索二维码的位置探测图形,即QR二维码中三个顶点处的“回”字区域,QR二维码位置以四个顶点的坐标形式给出。之后对二维码进行解码,提取其中的信息。QR二维码识别是OpenCV 4新增加的功能,OpenCV 4提供了相关函数直接解码QR二维码读取其中的信息,但是在OpenCV 4之前的版本中对QR二维码的识别需要借助第三方工具,常用的是zbar解码库。

针对QR二维码识别的两个过程,OpenCV 4提供了多个函数用于实现每个过程,这些函数分别是定位QR二维码的detect()函数、根据定位结果解码二维码的decode()函数以及同时定位和解码的detectAndDecode()函数,接下来将详细介绍这三个函数的函数原型和使用方法。

定位QR二维码的位置不仅可以用于解码QR二维码,也可以用于视觉定位。在利用QR二维码定位的任务中有时不需要对QR二维码进行解码,而是直接使用四个顶点的坐标,因此只定位不解码QR二维码可以加快系统的运行速度。定位QR二维码函数detect()的函数原型在代码清单7-37中给出。

代码清单7-37 detect()函数原型
1.  bool cv::QRCodeDetector::detect(InputArray  img,
2.                                         OutputArray  points 
3.                                        )
  • img:待检测是否含有QR二维码的灰度图像或者彩色图像。
  • points:包含QR二维码的最小区域四边形的四个顶点坐标,即二维码的四个顶点坐标。

该函数能够识别图像中是否含有QR二维码,以bool类型的返回值表示是否含有二维码的结果。如果图像中含有二维码,返回值为true,否则返回值为false。函数第一个参数是待检测是否含有QR二维码的图像,图像可以是灰度图像或者彩色图像,图像的尺寸任意。函数第二个参数是包含QR二维码的最小区域四边形的四个顶点坐标,数据类型为vector。

decode()函数能够利用图像中二维码的定位结果对QR二维码进行解码,该函数的函数原型在代码清单7-38中给出。

代码清单7-38 decode()函数原型
1.  std::string cv::QRCodeDetector::decode(InputArray  img,
2.                                         InputArray  points,
3.                                         OutputArray  straight_qrcode = noArray() 
4.                                         )
  • img:含有QR二维码的图像。
  • points:包含QR二维码的最小区域四边形的四个顶点坐标。
  • straight_qrcode:经过校正和二值化的QR二维码。

该函数能够根据二维码定位的结果信息对二维码进行解码,以string类型的返回值输出解码结果。该函数前两个参数与detect()函数的两个参数含义相同,不过该函数的第二个参数是输入值,数据量不能为空。函数第三个参数是经过校正和二值化的QR二维码,变量类型为Mat,在校正的二维码中每一个有效数据点都以单个像素出现,例如在经过校正和二值化的QR二维码中“回”字形区域中心的黑色区域尺寸为3×3,黑色区域边缘的白色轮廓宽度为1。

有时我们需要识别二维码中的信息,detectAndDecode()函数可以直接一步完成二维码的定位和解码过程,该函数的函数原型在代码清单7-39中给出。

代码清单7-39 detectAndDecode()函数原型
1.  std::string cv::QRCodeDetector::detectAndDecode(InputArray  img,
2.                                                  OutputArray  points = noArray(),
3.                                                  OutputArray  straight_qrcode = noArray() 
4.                                                        )
  • img:含有QR二维码的图像。
  • points:包含QR二维码的最小区域四边形的四个顶点坐标。
  • straight_qrcode:经过校正和二值化的QR二维码。

该函数能够直接完成对QR二维码四个顶点的定位和识别图像中QR二维码的信息,并以vector类型返回四个顶点的坐标,以string类型的返回值输出QR二维码识别的结果。函数第一个参数是含有QR二维码的灰度图像或者彩色图像。第二个参数是包含QR二维码的最小区域四边形的四个顶点坐标,在此函数中该参数是输出值,如果不需要QR二维码顶点坐标可以在调用函数时缺省该参数或者使用默认参数noArray()表示不输出坐标。函数第三个参数是经过校正和二值化的QR二维码,变量类型为Mat,如果不需要输出该结果可以在调用函数时缺省该参数或者使用默认参数noArray()表示不输出图像。

为了了解QR二维码定位和解码相关函数的使用方法,在代码清单7-40中给出了利用上述三个函数识别QR二维码的示例程序。程序中将定位和解码分步识别结果和直接识别结果显示在含有QR二维码的图像中,并输出校正和二值化的QR二维码。程序输出结果在图7-30给出,为了能够直观的了解校正和二值化的QR二维码,图7-30中使用的是Image Watch中查看到的校正和二值化的QR二维码图像。

代码清单7-40 mydetectQRcode.cpp二维码识别
1.  #include <opencv2/opencv.hpp>
2.  #include <iostream>
3.  #include <vector>
4.  
5.  using namespace cv;
6.  using namespace std;
7.  
8.  int main()
9.  {
10.     Mat img = imread("qrcode2.png");
11.     if (img.empty())
12.     {
13.         cout << "请确认图像文件名称是否正确" << endl;
14.         return -1;
15.     }
16.     Mat gray, qrcode_bin;
17.     cvtColor(img, gray, COLOR_BGR2GRAY);
18.     QRCodeDetector qrcodedetector;
19.     vector<Point> points;
20.     string information;
21.     bool isQRcode;
22.     isQRcode = qrcodedetector.detect(gray, points);  //识别二维码
23.     if (isQRcode)
24.     {
25.         //解码二维码
26.         information = qrcodedetector.decode(gray, points, qrcode_bin);
27.         cout << points << endl;  //输出二维码四个顶点的坐标
28.     }
29.     else
30.     {
31.         cout << "无法识别二维码,请确认图像时候含有二维码" << endl;
32.         return -1;
33.     }
34.     //绘制二维码的边框
35.     for (int i = 0; i < points.size(); i++)
36.     {
37.         if (i == points.size() - 1)
38.         {
39.             line(img, points[i], points[0], Scalar(0, 0, 255), 2, 8);
40.             break;
41.         }
42.         line(img, points[i], points[i + 1], Scalar(0, 0, 255), 2, 8);
43.     }
44.     //将解码内容输出到图片上
45.     putText(img, information.c_str(), Point(20, 30), 0, 1.0, Scalar(0, 0, 255),2,8);
46. 
47.     //利用函数直接定位二维码并解码
48.     string information2;
49.     vector<Point> points2;
50.     information2 = qrcodedetector.detectAndDecode(gray, points2);
51.     cout << points2 << endl;
52.     putText(img, information2.c_str(), Point(20, 55), 0, 1.0, Scalar(0, 0, 0), 2, 8);
53. 
54.     //输出结果
55.     imshow("result", img);
56.     namedWindow("qrcode_bin", WINDOW_NORMAL);
57.     imshow("qrcode_bin", qrcode_bin);
58.     waitKey(0);
59.     return 0;
60. }

http://weixin.qq.com/r/VSiJkbLExO_7rfby931H (二维码自动识别)

经过几个月的努力,市面上第一本OpenCV 4入门书籍《OpenCV 4开发详解》将春节后由人民邮电出版社发行。如果小伙伴觉得内容有帮助,希望到时候多多支持!

关注小白的小伙伴可以提前看到书中的内容,我们创建了学习交流群,欢迎各位小伙伴添加小白微信加入交流群,添加小白时请备注“学习OpenCV 4”。

https://u.wechat.com/MJ-57nVtXgxUyL3dTwWd014 (二维码自动识别)

a8d89473af5b879e2f26fc307feecf52.png
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值