二维码(QR码)是一种矩阵条形码,是一种机器可读的光学标签,其中包含有关其所附着物品的信息。实际上,二维码(QR码)码通常包含指向网站或应用程序的定位器,标识符或跟踪器的数据。

最近,OpenCV 4.0 发布了许多改进和新功能。其中之一是二维码扫描仪。我们在之前的文章中已经写过关于条码和二维码扫描器的文章,它使用了一个外部库——ZBar。因此,我们想检查 OpenCV 扫描仪的工作原理,以及它是否比 Zbar 扫描仪更好。在这篇文章中,我们将看到如何使用来自 OpenCV 的这个新的二维码扫描器。如果您想选择使用哪一种,我们还将它与基于 ZBar 的扫描仪进行比较。

链接:https://pan.baidu.com/s/1SjOnoxUic6wG8Fh0nB50kw
提取码:123a

1.使用qrcode库生成QR码

pip install opencv-python qrcode pillow pyzbar
#!/usr/bin/python3
# -*- encoding: utf-8 -*-
"""
@File    : generateQRCode.py
@Time    : 2021/10/12 14:13
"""
# 生成二维码
import qrcode# 二维码包含的示例数据
data = "https://blog.csdn.net/weixin_43229348"
# 生成的二维码图片名称
filename = "CSDNBlog.png"
# 生成二维码
img = qrcode.make(data)
# 保存成图片输出
img.save(filename)

2.基于OpenCV读取QR码

(1)Python

import cv2
import numpy as np
import sys
import timeif len(sys.argv) > 1:inputImage = cv2.imread(sys.argv[1])
else:inputImage = cv2.imread("CSDNBlog.png")# 显示条码和二维码位置
def display(im, bbox):# bbox:Nx4x2n = len(bbox)for j in range(n):cv2.line(im, tuple(bbox[j][0]), tuple(bbox[j][1]), (255, 0, 0), 1)cv2.line(im, tuple(bbox[j][1]), tuple(bbox[j][2]), (255, 0, 0), 1)cv2.line(im, tuple(bbox[j][2]), tuple(bbox[j][3]), (255, 0, 0), 1)cv2.line(im, tuple(bbox[j][3]), tuple(bbox[j][0]), (255, 0, 0), 1)# 显示cv2.imshow("Results", im)# 创建一个 qrCodeDetector 对象
qrDecoder = cv2.QRCodeDetector()# 检测和解码二维码
t = time.time()
data, bbox, rectifiedImage = qrDecoder.detectAndDecode(inputImage)
print("Time Taken for Detect and Decode : {:.3f} seconds".format(time.time() - t))
if len(data) > 0:print("Decoded Data : {}".format(data))display(inputImage, bbox)rectifiedImage = np.uint8(rectifiedImage);cv2.imshow("Rectified QRCode", rectifiedImage);
else:print("QR Code not detected")cv2.imshow("Results", inputImage)
cv2.imwrite("output.jpg", inputImage)
cv2.waitKey(0)
cv2.destroyAllWindows()

(2)C++

// #include <opencv2/opencv.hpp>
#include <opencv2/objdetect.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>using namespace cv;
using namespace std;void display(Mat &im, Mat &bbox)
{int n = bbox.rows;for(int i = 0 ; i < n ; i++){// 下面有点小问题,自己画线line(im, Point2i(bbox.at<float>(i,0),bbox.at<float>(i,1)), Point2i(bbox.at<float>(i+1) % n,0), bbox.at<float>((i+1) % n,1)), Scalar(255,0,0), 3);}imshow("Result", im);
}int main(int argc, char* argv[])
{// Read imageMat inputImage;if(argc>1)inputImage = imread(argv[1]);elseinputImage = imread("qrcode-learnopencv.jpg");QRCodeDetector qrDecoder;Mat bbox, rectifiedImage;std::string data = qrDecoder.detectAndDecode(inputImage, bbox, rectifiedImage);if(data.length()>0){cout << "Decoded Data : " << data << endl;display(inputImage, bbox);rectifiedImage.convertTo(rectifiedImage, CV_8UC3);imshow("Rectified QRCode", rectifiedImage);waitKey(0);}elsecout << "QR Code not detected" << endl;
}

3.Zbar与OpenCV读取QR码比较

import cv2
import numpy as np
import sys
import time
import pyzbar.pyzbar as pyzbarcap = cv2.VideoCapture("qr-code_animated.gif")
hasFrame, frame = cap.read()
vid_writer = cv2.VideoWriter('output.avi', cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'), 10,(frame.shape[1], frame.shape[0]))# 显示条码和二维码位置
def display(im, decodedObjects):# 遍历所有已解码的对象for decodedObject in decodedObjects:points = decodedObject.polygon# 如果点不形成四边形,请找到凸包if len(points) > 4:hull = cv2.convexHull(np.array([point for point in points], dtype=np.float32))hull = list(map(tuple, np.squeeze(hull)))else:hull = points;# 凸包中的点数n = len(hull)# 绘制凸包for j in range(0, n):cv2.line(im, hull[j], hull[(j + 1) % n], (255, 0, 0), 3)# 显示结果# cv2.imshow("Results", im);# 创建一个 qrCodeDetector 对象
qrDecoder = cv2.QRCodeDetector()# 检测和解码二维码
t = time.time()
while (1):hasFrame, inputImage = cap.read()if not hasFrame:breakdecodedObjects = pyzbar.decode(inputImage)if len(decodedObjects):zbarData = decodedObjects[0].dataelse:zbarData = ''opencvData, bbox, rectifiedImage = qrDecoder.detectAndDecode(inputImage)if zbarData:cv2.putText(inputImage, "ZBAR : {}".format(zbarData.decode()), (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1,(0, 255, 0), 2, cv2.LINE_AA)else:cv2.putText(inputImage, "ZBAR : QR Code NOT Detected", (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2,cv2.LINE_AA)if opencvData:cv2.putText(inputImage, "OpenCV:{}".format(opencvData), (10, 150), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2,cv2.LINE_AA)else:cv2.putText(inputImage, "OpenCV:QR Code NOT Detected", (10, 150), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2,cv2.LINE_AA)display(inputImage, decodedObjects)cv2.imshow("Result", inputImage)vid_writer.write(inputImage)k = cv2.waitKey(20)if k == 27:break
cv2.destroyAllWindows()
vid_writer.release()

4.将视频转为GIF代码

#!/usr/bin/python3
# -*- encoding: utf-8 -*-
"""
@File    : toGIF.py
"""
import cv2
import imageiodef read_video(video_path):video_cap = cv2.VideoCapture(video_path)frame_count = 0all_frames = []while True:ret, frame = video_cap.read()if ret is False:breakframe = cv2.resize(frame, (320, 280))frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)all_frames.append(frame)cv2.imshow('frame', frame)cv2.waitKey(1)frame_count += 1if frame_count > 100:breakprint(frame_count)video_cap.release()cv2.destroyAllWindows()print('===>', len(all_frames))return all_framesdef frame_to_gif(frame_list):gif = imageio.mimsave('./qrCode.gif', frame_list, 'GIF')if __name__ == "__main__":frame_list = read_video('output.avi')frame_to_gif(frame_list)

5.对比结果分析

现在,让我们基于以下理由比较这两种实现。令人惊讶的是,基于 ZBar 的扫描仪在各个方面都优于 OpenCV 的二维码。

5.1速度

ZBar 库的速度几乎是 OpenCV 二维码检测器的两倍。

5.2稳健性

与 OpenCV 相比,ZBar 库在以下因素上产生了更可靠的结果,如上述视频所示:

  • ZBar 在各种旋转下都更好或具有可比性
  • 从视频中的不同缩放级别可以看出,ZBar 在不同图像尺寸下效果更好
  • ZBar 更擅长处理透视失真(当图像与相机不垂直时。

5.3特征

ZBar 库也提供对条码的支持,而 OpenCV 中还没有。

总的来说,我们可以说 QR Code 是最近在 OpenCV 中推出的,它可能会在未来的版本中变得更好。到那时之前,如果您想在您的应用程序中使用条形码或二维码,请坚持使用 ZBar。

BONUS

最近在github上发现使用 Python+PyZBar+OpenCV 读取和跟踪二维码

  • Python代码
from pyzbar.pyzbar import decode
import cv2
import numpy as npcap = cv2.VideoCapture(0)def get_qr_data(input_frame):try:return decode(input_frame)except:return []def draw_polygon(f_in, qro):if len(qro) == 0:return f_inelse:for obj in qro:text = obj.data.decode('utf-8')pts = np.array([obj.polygon], np.int32)# print("Before Reshape::", pts.shape)pts = pts.reshape((4, 1, 2))# print("After Reshape::",pts.shape)cv2.polylines(f_in, [pts], True, (255, 100, 5), 2)cv2.putText(f_in, text, (50, 50), cv2.FONT_HERSHEY_PLAIN,1.5,(255,100,5),2)return f_inwhile True:_, frame = cap.read()qr_obj = get_qr_data(frame)frame = draw_polygon(frame, qr_obj)cv2.imshow("DD", frame)# cv2.imshow("DD2", frame2)if cv2.waitKey(1) & 0xFF == ord('q'):breakcap.release()
cv2.destroyAllWindows()
  • C++代码
//Reference:https://www.learnopencv.com/opencv-qr-code-scanner-c-and-python/#include <iostream>
#include <vector>
#include <zbar.h>#include <opencv2/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>using namespace std;
using namespace cv;
using namespace zbar;typedef struct
{string type;string data;vector <Point> location;
}decodedObject;// Find and decode barcodes and QR codes
void decodewithlocation(Mat &im, vector<decodedObject>&decodedObjects)
{// Create zbar scannerImageScanner scanner;//Clear decoded Object to keep only one QR code in memory at a time.decodedObjects.clear();// Configure scannerscanner.set_config(ZBAR_NONE, ZBAR_CFG_ENABLE, 1);
//    scanner.set_config(ZBAR_QRCODE, ZBAR_CFG_ENABLE, 1);// Convert image to grayscaleMat imGray;cvtColor(im, imGray,COLOR_BGR2GRAY);// Wrap image data in a zbar imageImage image(im.cols, im.rows, "Y800", (uchar *)imGray.data, im.cols * im.rows);// Scan the image for barcodes and QRCodesint n = scanner.scan(image);// Print resultsfor(Image::SymbolIterator symbol = image.symbol_begin(); symbol != image.symbol_end(); ++symbol){decodedObject obj;obj.type = symbol->get_type_name();obj.data = symbol->get_data();// Print type and datacout << "Type : " << obj.type << endl;cout << "Data : " << obj.data << endl << endl;// Obtain locationfor(int i = 0; i< symbol->get_location_size(); i++){obj.location.push_back(Point(symbol->get_location_x(i),symbol->get_location_y(i)));}decodedObjects.push_back(obj);}
}int main(int argc, char *argv[])
{vector<decodedObject> decodedObjects;VideoCapture *cam = new VideoCapture(0);while(cam->isOpened()){Mat image;cam->read(image);
//        cvtColor(image, image,COLOR_BGR2GRAY);decodewithlocation(image, decodedObjects);cout<<decodedObjects.size()<<endl;for (int i=0; i<decodedObjects.size(); i++){//QR Object location in image stored in points variablevector<Point> points = decodedObjects[i].location;//Convex Hull is created if points are more than 4vector<Point> hull;if(points.size() > 4){convexHull(points, hull);}else{hull=points;}int n = hull.size();for(int j = 0; j < n; j++){line(image, hull[j], hull[ (j+1) % n], Scalar(0,255,90), 3);}}imshow("image", image);if(waitKeyEx(1)==99){break;}}// Variable for decoded objects// Find and decode barcodes and QR codesreturn 0;
}

参考代码

https://learnopencv.com/opencv-qr-code-scanner-c-and-python/

OpenCV基础(22)使用OpenCV生成及读取二维码以及与Zbar比较相关推荐

  1. 一行代码,生成和读取二维码!

    文 | 闲欢 来源:Python 技术「ID: pythonall」 二维码是用某种特定的几何图形按一定规律在平面(二维方向上)分布的.黑白相间的.记录数据符号信息的图形. 二维码被称为快速响应码,可 ...

  2. 利用ZXing生成和读取二维码

    在日常生活中二维码的使用非常频繁,给我们带来了极大的方便,避免了许多不必要的输入,也减少了在输入过程中的错误. 刚学完利用ZXing生成二维码的简单例子,在此给出最基本的源码,关于ZXing的jar文 ...

  3. jquery-qrcode 生成和读取二维码

    首先要导入jar包(生成二维码的jar和读取二维码的jar) 生成二维码: package com.imooc.qrcode;import java.awt.Color; import java.aw ...

  4. python生成和读取二维码

    目录 生产二维码 普通二维码 艺术二维码 二维码读取 CV2 pyzbar zxing 生产二维码

  5. ios使用AVFoundation读取二维码的方法

    二维码(Quick Response Code,简称QR Code)是由水平和垂直两个方向上的线条设计而成的一种二维条形码(barcode).可以编码网址.电话号码.文本等内容,能够存储大量的数据信息 ...

  6. 生成二维码,读取二维码,这很Python(23)

    小朋友们好,大朋友们好! 我是猫妹,一名爱上Python编程的小学生. 欢迎和猫妹一起,趣味学Python. 今日主题 如何用Python生成二维码. 如何用Python读取二维码. 什么是二维码 二 ...

  7. 【基础入门详解】程序员的二维码也要玩出不同色彩,用Python生成动态彩色二维码

    一.前言 常见的二维码为QR CodeCode,QR全称是Quick Response,是一个近几年来移动设备上超流行的一种编码方式.它的结构如下: 主要有以下特点: 符号规格从版本1(21×21)到 ...

  8. ZXing生成二维码、读取二维码

    使用谷歌的开源包ZXing maven引入如下两个包即可 <dependency> <groupId>com.google.zxing</groupId> < ...

  9. Python 二维码的读取与生成:使用链接生成二维码、读取二维码里的链接

    Python 二维码的读取与生成演示 ① 使用链接生成二维码 ② 读取二维码里的链接 [ 文章推荐 ] Python 绘制中国地图:使用 pyecharts 最新版本绘制中国地图实例详解,个性化地图定 ...

最新文章

  1. SIGIR 2019 | 为什么你的毛衣显胖又显黑?这个算法给你答案
  2. boost::hana::common用法的测试程序
  3. 使用Angular CLI创建一个Hello World级别的Angular应用
  4. Scom 2012 中的资源组(Resource Pool)
  5. Failed to maintain projects LRU cache for dir *********
  6. mysql存储过程已发_MySQL存储过程问题_MySQL - end
  7. H264 SPS中得到宽高的代码(java/c),测试通过
  8. 求任意多边形面积(凹多边形和凸多边形)
  9. Autocad 字体
  10. redis雪崩、穿透、击穿的原因和解决方案
  11. recyclerView多条目加载,点击动画事件
  12. WPS设置奇偶页页眉不同
  13. java还原合并单元格_Java 合并/取消合并 Excel 单元格
  14. 淘宝x-sign算法demo示例
  15. 【Plant Cell Physiol】R2R3-MYB调节因子FhPAP1在香雪兰花青素生物合成中的作用
  16. Linux和Windows系统基础操作命令
  17. WEB开发文档2 总结
  18. PhoneGap移动开发框架
  19. 实战 SQL:微信、微博等社交网络中的友好、粉丝关系分析
  20. 基于MUI的驾考宝典APP及后台管理系统

热门文章

  1. 【信号增强】基于广义结构化收缩算法(GSSA)实现振动信号弱特征增强附matlab代码和复现论文
  2. 使用pako.js 解压缩ws消息
  3. 用Python爬取股票数据,绘制K线和均线并用机器学习预测股价(来自我出的书)(转载)
  4. 脚本开发教程分享:如何用按键精灵判断窗口是否无响应或卡屏呢
  5. flutter 唤起微信 唤起其他应用
  6. YOLOV2参数详解
  7. 相机照片丢失怎么恢复?1招找回“离奇失踪”的照片
  8. ESP mDNS 学习
  9. iOS 图片压缩方法
  10. 宣传册翻译,企业宣传册如何翻译?