1、该模块是一个日本的author开源的一个二维码检测的项目,可以用来检测:
同时可以返回检测二维码和条形码的相关信息:
2、pyzbar支持两种数据类型输入:
PIL.Image
数据类型ndarray
数据类型1、Mac OS X:
brew install zbar
2、Linux:
sudo apt-get install libzbar0
3、直接使用pip安装
pip install pyzbar
1、pyzbar的decode接受测PIL.Image的实例
图片:
>>> from pyzbar.pyzbar import decode
>>> from PIL import Image
>>> decode(Image.open('pyzbar/tests/code128.png'))
[
Decoded(
data=b'Foramenifera', type='CODE128',
rect=Rect(left=37, top=550, width=324, height=76),
polygon=[
Point(x=37, y=551), Point(x=37, y=625), Point(x=361, y=626),
Point(x=361, y=550)
]
)
Decoded(
data=b'Rana temporaria', type='CODE128',
rect=Rect(left=4, top=0, width=390, height=76),
polygon=[
Point(x=4, y=1), Point(x=4, y=75), Point(x=394, y=76),
Point(x=394, y=0)
]
)
]
从上面的内容可以看到,返回检测到两个条形二维码
,每个条形二维码包含内容:
存储的内容
CODE128
左上角坐标
和矩形框的宽与高
外接多边形框
的四个点坐标
2、检测二维码
测试图片(图片来源pyzbar的github项目
):
from PIL import Image, ImageDraw
from pyzbar.pyzbar import decode
image = Image.open('./qrcode_rotated.png').convert('RGB')
draw = ImageDraw.Draw(image)
for barcode in decode(image):
rect = barcode.rect
draw.rectangle(
(
(rect.left, rect.top),
(rect.left + rect.width, rect.top + rect.height)
),
outline='#0080ff'
)
draw.polygon(barcode.polygon, outline='#e945ff')
image.save('bounding_box_and_polygon.png')
image.show()
检测结果:
q
键,退出显示和程序运行__Author__ = "Shliang"
__Email__ = "[email protected]"
# coding:utf8
import cv2
import pyzbar.pyzbar as pyzbar
import numpy as np
def decodeDisplay(image):
barcodes = pyzbar.decode(image)
rects_list = []
polygon_points_list = []
QR_info = []
# 这里循环,因为画面中可能有多个二维码
for barcode in barcodes:
# 提取条形码的边界框的位置
# 画出图像中条形码的边界框
(x, y, w, h) = barcode.rect
rects_list.append((x, y, w, h))
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)
polygon_points = barcode.polygon
# print(f"polygon_points: {polygon_points}") # polygon_points: [Point(x=217, y=174), Point(x=257, y=353), Point(x=433, y=316), Point(x=394, y=140)]
# print(f"polygon_points: {polygon_points[0]}") # polygon_points: Point(x=217, y=174)
point_x, point_y = polygon_points[0]
# print(f"point_x, point_y: {point_x, point_y}") # point_x, point_y: (217, 174)
extract_polygon_points = np.zeros((4, 2), dtype=np.int)
for idx, points in enumerate(polygon_points):
point_x, point_y = points # 默认得到的point_x, point_y是float64类型
extract_polygon_points[idx] = [point_x, point_y]
print(extract_polygon_points.shape) # (4, 2)
# 不reshape成 (4,1 2)也是可以的
extract_polygon_points = extract_polygon_points.reshape((-1, 1, 2))
polygon_points_list.append(extract_polygon_points)
# 要加上中括号,否则只会绘制四个点
# cv2.polylines(image, extract_polygon_points, isClosed=True, color=(255, 0, 255), thickness=2)
# 绘制多边形
cv2.polylines(image, [extract_polygon_points], isClosed=True, color=(255, 0, 255), thickness=2,
lineType=cv2.LINE_AA)
# 条形码数据为字节对象,所以如果我们想在输出图像上画出来,就需要先将它转换成字符串
barcodeData = barcode.data.decode("utf-8")
barcodeType = barcode.type
# 绘出图像上条形码的数据和条形码类型
text = "{} ({})".format(barcodeData, barcodeType)
QR_info.append(text)
cv2.putText(image, text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX,
.5, (0, 0, 125), 2)
# 向终端打印条形码数据和条形码类型
print("[INFO] Found {} barcode: {}".format(barcodeType, barcodeData))
return image, rects_list, polygon_points_list, QR_info
def detect():
cap = cv2.VideoCapture(0)
while True:
# 读取当前帧
ret, frame = cap.read()
# 转换为灰度图是为了检测到二维码,如果是BGR图很大概率是检测不到二维码
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
im, rects_list, polygon_points_list, QR_info = decodeDisplay(gray)
# 把检测到二维码的信息再绘制到BGR彩色图像上
for data in zip(rects_list, polygon_points_list, QR_info):
print(f"data: {data}")
x, y, w, h = data[0]
polygon_points = data[1]
text = data[2]
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)
cv2.polylines(frame, [polygon_points], isClosed=True, color=(255, 0, 255), thickness=2,
lineType=cv2.LINE_AA)
cv2.putText(frame, text, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX,
.5, (0, 0, 125), 2)
# 因为一个是单通道的灰度图,一个是BGR三通道的彩色图,因此不能够拼接在一起显示,这里就用两个窗口显示
cv2.imshow("camera", im)
cv2.imshow("frame", frame)
# 按q键退出画面显示
k = cv2.waitKey(1)
if k == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
detect()
显示结果如下: