在现代技术中,二维码和条形码的应用非常广泛,它们为日常生活带来了极大的便利。其中一种简单且流行的日常应用就是使用二维码和条形码扫描器。通过Python,可以轻松地实现一个二维码扫描器,使用OpenCV和ZBar库。
当在超市结账时,收银员会用设备扫描购物篮中的每件商品,然后价格会自动记录在系统中以生成账单。那个设备就是一个二维码/条形码扫描器,这正是今天要构建的!
二维码,全称为快速响应码(Quick Response Code),是一种矩阵型编码,广泛用于追踪物品。二维码以像素形式存储数据,这些像素对应二进制代码,可以被解释以显示实际数据。
二维码在多个领域都有应用,例如:
二维码的一个主要优势是数据可以以加密形式共享,而无需显式揭示编码数据。这增加了一层保护,防止敏感信息被滥用。
与二维码类似,条形码也是机器可读的加密代码,但与二维码不同,数据以不同间距和厚度的条形加密。二维码被认为是二维条形码,因为它可以水平和垂直存储数据,而条形码通常只沿水平方向存储数据。因此,二维码比条形码更强大。
在项目中,将使用OpenCV来读取图像,获取视频流输入并显示输出。需要的主要库是pyzbar和zbar库,这些是开源的Python库,帮助解码条形码和二维码。还需要NumPy库。必须进行必要的安装。
import numpy as np
from pyzbar.pyzbar import decode
import cv2
首先,将使用cv2库读取保存在“qr1.png”中的二维码图像。然后,将使用pyzbar的decode方法尝试解码代码并分析结果。
# 从图像中读取二维码
img = cv2.imread("qr1.png")
code = decode(img)
print(code)
输出显示了很多信息。让了解输出的每个部分。
这就是为什么将使用多边形的坐标来绘制边界框,以便即使二维码旋转,也能获得代码的确切边界。
现在,一张图片可能包含多个二维码。因此,让将代码放入一个for循环中,以便它可以检测图片中的所有条形码。由于主要感兴趣的是编码信息,让只显示编码文本。
for barcode in decode(img):
print(barcode.data) # 以字节形式
text = barcode.data.decode('utf-8')
print(text)
print(barcode.rect)
输出的第一行显示b'Hello! '。b表示它是一个字节字面量。后来使用'utf-8'方案解码以获得纯str文本。
太好了!现在已经成功地从二维码中解码了编码文本。
现在让尝试使用相机输入实时进行这个操作。大多数实际应用,如超市的二维码扫描器、用户认证或追踪对象,都需要实时解码代码。让开始吧!
# 从相机输入中扫描二维码
vid = cv2.VideoCapture(0)
vid.set(3,640)
vid.set(4,740)
在视频开启时,将像之前一样在帧中解码二维码。此外,还将使用多边形点绘制围绕二维码的边界框,并在相机帧输入本身上显示相应的解码文本。
while True:
success, img = vid.read()
for barcode in decode(img):
text = barcode.data.decode('utf-8')
print(text)
polygon_Points = np.array([barcode.polygon], np.int32)
polygon_Points=polygon_Points.reshape(-1,1,2)
rect_Points= barcode.rect
cv2.polylines(img,[polygon_Points],True,(255,255, 0), 5)
cv2.putText(img, text, (rect_Points[0],rect_Points[1]), cv2.FONT_HERSHEY_DUPLEX, 0.8, (255,255, 0), 2)
cv2.imshow("Video", img)
cv2.waitKey(1)
在上面的代码中,cv2.polylines(img,[polygonPoints],True,(255,255, 0), 5)这行显示了二维码周围的边界框。'img'指定输入帧。注意,这里使用多边形点,以便即使二维码旋转,也能获得确切的边界框。(255,255,0)指定边界框的颜色,5表示厚度。
代码行cv2.putText(img, text, (rect_Points[0],rect_Points[1]), cv2.FONT_HERSHEY_DUPLEX, 0.8, (255,255, 0), 2)用于显示解码文本。如果仔细观察,会看到在这里使用了矩形而不是多边形的坐标来显示文本。这样做的原因是确保文本无论二维码是否旋转都能直立显示,以便更容易阅读。
这个输出将向展示当二维码直立时和当它以角度放在相机前时的比较结果。
让在一些现实世界的对象上测试它,看看它是否有效!
确实有效!可以随意测试周围能找到的尽可能多的二维码!
另一个有趣的特性是,这个库不仅可以解码二维码,还可以解码条形码,而不需要对代码做任何更改!
让看看条形码相机输入的结果。
瞧!现在使用一些简单的OpenCV函数和pyzbar库构建了条形码和二维码扫描器!
让来看一个现实生活场景。每个公司的员工都会得到带有相应二维码的ID卡。一些在特殊项目上工作的员工被允许进入特定的实验室,而其他人则被限制进入。每个员工都必须在入口处扫描他们的ID卡以获得实验室的访问权限。
已经拥有了二维码扫描器。现在让把到目前为止学到的所有知识付诸实践。将构建一个简单的用户认证系统,检查二维码是否属于授权人员,并决定是否授予他们访问权限。
import numpy as np
from pyzbar.pyzbar import decode
import cv2
# 从相机输入中扫描二维码
vid = cv2.VideoCapture(0)
vid.set(3,640)
vid.set(4,740)
库已经导入,视频捕获已经设置。现在必须读取包含授权员工解码二维码文本的文本文件,并将它们存储在一个列表中。
这是文本文件“Authorized.txt”。
with open('Authorized.txt', 'r') as file:
auth_list = file.read().strip()
print(auth_list)
作为参考,让运行之前的代码在输入图像上显示每个二维码的解码文本。稍后需要这个,以验证模型是否工作正常。让看看得到的输出。
现在所要做的,就是检查每个二维码,如果解码的文本在授权人员列表中,那么就使用绿色(0,255,0)为边界框,并显示文本“Access Granted”,否则使用红色(0,0, 255)边界框,并显示消息“Unauthorised Access”。
while True:
success, img = vid.read()
for barcode in decode(img):
text = barcode.data.decode('utf-8')
text=str(text)
if text not in auth_list:
color=(0,0,255)
displaytext = "Unauthorised Access"
else:
color=(0,255,0)
displaytext = "Access Granted"
polygon_Points = np.array([barcode.polygon], np.int32)
polygon_Points=polygon_Points.reshape(-1,1,2)
rect_Points= barcode.rect
cv2.polylines(img,[polygon_Points],True,color, 3)
cv2.putText(img, displaytext, (rect_Points[0],rect_Points[1]), cv2.FONT_HERSHEY_PLAIN, 0.9, color, 2)
cv2.imshow("Video", img)
cv2.waitKey(1)
太棒了!模型完美地扫描了二维码,并只授予授权员工访问权限!已经成功地使用OpenCV构建了一个用户认证系统,该系统仅在员工扫描他们ID卡上的二维码时授予访问权限!
二维码的用途是无止境的。所以,继续尝试不同的代码及其应用吧!