1.生成二维码,二维码解析 2.调用摄像头 3.识别二维码。
opencv是英特尔的计算机视觉处理模块,而pyzbar则是用于解析二维码的模块。
环境包括python环境和模块。我的环境如下:
模块安装很简单,我们直接用pip安装,先安装opencv模块:
pip install opencv-python-4.4.0.44
pip install pyzbar
pip install numpy
pip install qrcode
pip install MyQR
pip install zxing
pip install pillow
# 导包
# 方法1 MyQR二维码加背景图片(公司logo)
from MyQR import myqr
# 方法2 qrcode 二维码
import qrcode
# 主要用到以下几个参数
# words:文本,可以是一个链接,或者你想说的话(不支持中文,很不友好)
# picture:你用到的图片,作为背景,不然只是一个光秃秃的二维码
# colorsize:True,表示生成彩图
# save_name:表示生成的二维码的名字
# 解析1
import zxing
# 解析2
import numpy as np
from PIL import Image
from pyzbar import pyzbar
class UserQR():
def __init__(self):
self.bgimg = "view.png"
self.url="http://127.0.0.1:5000/users/opendoor"
def qr(self,opencode,userid):
myqr.run(words=self.url+"?opencode="+str(opencode)+"&userid="+str(userid),
picture=self.bgimg,
colorized=True,
save_name="UserQRimg/"+str(userid)+".png")
def myqr(self,opencode,userid):
# 调用QRCode,可以接收以下参数
"""
version: 二维码的格子大小,可以是1到40。值越大,格子越大,一般不超过10,选择3比较合适
error_correction: 二维码错误容许率,默认为qrcode.constants.ERROR_CORRECT_M,容许小于 15% 的错误率
此外还有qrcode.constants.ERROR_CORRECT_L: 容许小于 7% 的错误率
qrcode.constants.ROR_CORRECT_H: 容许小于 30% 的错误率
box_size: 二维码每个小格子包含的像素数量
border: 二维码到图片边框的小格子数,默认值为 4
"""
qr = qrcode.QRCode() # 事实上里面的参数我们可以都不指定,默认会选择一个比较合适的参数
# 调用add_data,指定url或者数据。
qr.add_data(self.url+"?opencode="+str(opencode)+"&userid="+str(userid))
# 生成二维码图像,颜色为蓝色,背景色为粉色
img = qr.make_image(fill_color='blue', back_color='pink')
# 显示图像,这个会打开一个临时文件
img.show()
# 此外,我们还可以保存到硬盘上
img.save("img/"+str(userid)+".png")
# 事实上,这个img实际上是通过PIL模块得到的,可以理解为里面Image对象
# 如果你熟悉PIL模块的话,那么你应该知道可以将里面Image对象保存成图片对应的字节流
from io import BytesIO
buf = BytesIO()
img.save(buf) # 将字节保存到buf里面
with open("img/"+str(userid)+".png", "wb") as f:
f.write(buf.getvalue()) # 和直接保存为1.png是一样的
# 解析1
def decode_QR(self):
reader = zxing.BarCodeReader()
barcode = reader.decode('UserQRimg/1.png')
# 解析二维码图片
return barcode.parsed # 是可以解析出来的
# 解析2
def decode_QR1(self):
# 读取文件,转成数组
im = np.array(Image.open("UserQRimg/1.png"))
print(pyzbar.decode(im))
# 返回的信息还是很多的
"""
[
Decoded(data=b'http://www.bilibili.com',
type='QRCODE',
rect=Rect(left=35, top=35, width=263, height=264),
polygon=[Point(x=35, y=35), Point(x=35, y=297), Point(x=297, y=299), Point(x=298, y=35)])
]
"""
# 返回拿到的内容
return pyzbar.decode(im)[0].data.decode("utf-8")
my = UserQR()
# my.qr("123456",1)
有了pyzbar模块后,我们识别二维码的工作就非常简单了,首先需要准备一张二维码。有了二维码后就可以开始解析了,具体步骤如下:
1.读取二维码图片2.解析二维码中的数据3.在解析出的数据中提取data信息
实现代码如下:
import cv2
from pyzbar import pyzbar
# 1、读取二维码图片
qrcode = cv2.imread('qrcode.jpg')
# 2、解析二维码中的数据
data = pyzbar.decode(qrcode)
print(data)
# 3、在数据中解析出二维码的data信息
text = data[0].data.decode('utf-8')
print(text)
这样我们就能拿到二维码中包含的信息了。为了方便后续使用,可以将上面的代码写成一个函数:
def scan_qrcode(img_path):
qrcode = cv2.imread(img_path)
data = pyzbar.decode(qrcode)
return data[0].data.decode('utf-8')
接下来我们再看看如何调用摄像头。
在opencv中提供了一个VideoCapture类用于读取视频,同样可以用来调用摄像头。调用摄像头的步骤如下:
1.调用摄像头2.循环3.在循环内读取一帧画面4.显示当前读取的画面5.等待键盘输入6.判断是否按退出键q7.按了退出键则退出,没按则继续循环
使用 cv2.VideoCapture
类
使用 VideoCapture 对象的 read 方法按帧读取视频,ret, frame 是 read 方法的两个返回值 ,其中 ret 是布尔值,如果能正确读取帧,则返回 True;如果文件读取到结尾,它的返回值就为 False。frame 就是每一帧的图像,是一个三维矩阵。
具体代码如下:
import cv2
# 调用摄像头(0,笔记本默认摄像头)
cap = cv2.VideoCapture(0)
while True:
# 读取一帧画面,fram:三维矩阵
ret, frame = cap.read()
# 显示当前帧
cv2.imshow('scan qrcode', frame)
# 等待键盘输入
key = cv2.waitKey(10)
# 当按下q键时关闭摄像头
if key == ord('q'):
break
# 销毁所有窗口
cv2.destroyAllWindows()
你们可以自己尝试运行一下上面的代码,效果就像是打开了自己的前置摄像头。
现在调用了摄像头,我们可以把两部分的代码结合起来。
我们扫码工具的主体部分是调用摄像头的操作,我们需要对读取到的每一帧画面进行解析,当解析出结果后输出并退出。具体代码如下:
import cv2
from pyzbar import pyzbar
def scan_qrcode(qrcode):
data = pyzbar.decode(qrcode)
return data[0].data.decode('utf-8')
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
cv2.imshow('scan qrcode', frame)
# 解析二维码
text = None
try:
text = scan_qrcode(frame)
except Exception as e:
pass
if text:
print(text)
break
key = cv2.waitKey(10)
if key == ord('q'):
break
cv2.destroyAllWindows()
上面我们把scan_qrcode函数修改了一下,从原来的传入图片路径到直接传入图片对象。因为通过VideoCapture对象获取的图片帧和通过cv2.imread获取的图片是同一数据类型。
上面关键步骤在解析二维码的操作。首先定义一个text,因为解析过程中如果没有二维码会出现异常,所以用try-except语句处理。如何通过if判断text的内容,只有当我们真正解析到了数据,程序才会输出结果,并退出程序。
关闭视频文件
vc.release()
到这里,我们就实现了扫码工具。