1 QR Code
QR Code(Quick Response Code)是一种二维条码,由日本Denso-Wave公司于1994年发明。QR Code的主要特点是存储信息量大、编码范围广、容错能力强、识读速度快,并且支持全方位识读。这种条码最初是为了在汽车制造行业快速追踪零部件而设计的,但现在已经广泛应用于各种领域,如移动支付、产品防伪、广告宣传、物流追踪等。
QR Code的构成:
- 定位图案:位于二维码的左上角、右上角和左下角,用于确定二维码的角度和位置。
- 校正图案:在二维码中有多个校正图案,用于在二维码发生形变时帮助解码器校正。
- 格式信息:包含有关错误检测和校正的信息,以及使用的掩码版本。
- 版本信息:表明QR Code的版本号,版本号越高,可以存储的信息越多,但QR Code的尺寸也越大。
- 数据和纠错码:存储实际的信息和用于错误检测和校正的冗余数据。
QR Code的使用:
- 移动支付:通过手机扫描QR Code进行快速支付。
- 社交媒体:扫描QR Code可以直接跳转到某个社交媒体页面或添加好友。
- 产品防伪:在产品包装上打印QR Code,消费者可以扫描验证产品的真伪。
- 广告宣传:在广告中打印QR Code,观众可以通过扫描直接访问相关网站或获取更多信息。
- 物流追踪:在物流包裹上打印QR Code,可以方便地进行物流追踪和查询。
QR Code的生成和扫描通常需要使用专门的软件或应用,这些软件和应用可以在各种平台上找到,如手机、电脑等。
2 准备工作
OpenCV基础(22)使用OpenCV生成及读取二维码以及与Zbar比较
pip install qrcode
pip install pillow
pip install pyzbar
pip install zbar
3 生成 QR 码
generateQRCode.py
#!/usr/bin/python3
# -*- encoding: utf-8 -*-
"""
@File : generateQRCode.py
@Time : 2021/10/12 14:13
@Author : David
@Software: PyCharm
"""
# 生成二维码
import qrcode
# 二维码包含的示例数据
data = "https://blog.csdn.net/bryant_meng"
# 生成的二维码图片名称
filename = "CSDNBlog.png"
# 生成二维码
img = qrcode.make(data)
# 保存成图片输出
img.save(filename)
生成本博客主页的二维码
4 QR 码加 logo
# 导入图像处理库PIL的image方法
from PIL import Image
# qrcode是第三方库,需要pip install qrcode安装
import qrcode
# 初步生成二维码图像
qr = qrcode.QRCode(version=None, error_correction=qrcode.constants.ERROR_CORRECT_H, box_size=8, border=4)
# 添加二维码信息,可以是文字、数字、url
qr.add_data("https://blog.csdn.net/bryant_meng")
# 生成二维码实例
qr.make(fit=True)
# 把实例转换成图片
img = qr.make_image()
# 把颜色模式转换为RGBA
img = img.convert("RGBA")
# 打开logo文件,二维码中心logo图片
icon = Image.open("2.jpg")
# 先得出二维码的宽和高
img_w, img_h = img.size
factor = 3
# 通过二维码宽高计算出logo图片宽和高的最大限度
size_w = int(img_w / factor)
size_h = int(img_h / factor)
# 获取logo的宽和高
icon_w, icon_h = icon.size
# 比较logo宽高和最大限度宽高,如果超过最大限度就将logo尺寸调整到最大限度
if icon_w > size_w:
icon_w = size_w
if icon_h > size_h:
icon_h = size_h
# 重新调整logo的尺寸 Image.NEAREST :低质量 Image.BILINEAR:双线性
# Image.BICUBIC :三次样条插值 Image.ANTIALIAS:高质量
icon = icon.resize((icon_w, icon_h), Image.ANTIALIAS)
# 根据logo和图片的长宽确定logo的位置
w = int((img_w - icon_w) / 2)
h = int((img_h - icon_h) / 2)
# 将logo颜色模式转换为RGBA
icon = icon.convert("RGBA")
# 将logo图片粘贴到二维码的指定位置
img.paste(icon, (w, h))
# 保存二维码到指定位置,设置二维码格式
img.save('CSDNWithLOGO.png')
输入
输出
5 读取 QR 码
qrCodeOpencv.py
import cv2
import numpy as np
import sys
import time
if len(sys.argv) > 1:
inputImage = cv2.imread(sys.argv[1])
else:
inputImage = cv2.imread("CSDNBlog.png")
# inputImage = cv2.imread("qrcode-learnopencv.jpg")
# Display barcode and QR code location
def display(im, bbox):
cv2.line(im, tuple(bbox[0]), tuple(bbox[1]), (255, 0, 0), 5)
cv2.line(im, tuple(bbox[1]), tuple(bbox[2]), (255, 0, 0), 5)
cv2.line(im, tuple(bbox[2]), tuple(bbox[3]), (255, 0, 0), 5)
cv2.line(im, tuple(bbox[3]), tuple(bbox[0]), (255, 0, 0), 5)
# Write results
cv2.imwrite("Results.jpg", im)
# Display results
cv2.imshow("Results", im)
# Create a qrCodeDetector Object
qrDecoder = cv2.QRCodeDetector()
# Detect and decode the qrcode
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, np.array(bbox[0], dtype=np.int32))
rectifiedImage = np.uint8(rectifiedImage)
cv2.imwrite("Rectified_QRCode.jpg", 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()
生成 Results.jpg
Recitified_QRCode.jpg
6 与 Zbar 比较
import cv2
import numpy as np
import sys
import time
import pyzbar.pyzbar as pyzbar
cap = 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]))
# Display barcode and QR code location
def display(im, decodedObjects):
# Loop over all decoded objects
for decodedObject in decodedObjects:
points = decodedObject.polygon
# If the points do not form a quad, find convex hull
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;
# Number of points in the convex hull
n = len(hull)
# Draw the convext hull
for j in range(0, n):
cv2.line(im, hull[j], hull[(j + 1) % n], (255, 0, 0), 3)
# Display results
# cv2.imshow("Results", im);
# Create a qrCodeDetector Object
qrDecoder = cv2.QRCodeDetector()
# Detect and decode the qrcode
t = time.time()
while (1):
hasFrame, inputImage = cap.read()
if not hasFrame:
break
decodedObjects = pyzbar.decode(inputImage)
if len(decodedObjects):
zbarData = decodedObjects[0].data
else:
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()
输入
输出为视频,我们转化成 gif
可以看出 qrcode 库没有 pyzbar 库检测结果稳定