python3 + opencv +pyzbar實時檢測二維碼 / 定位二維碼,并繪制出二維碼的框和提取二維碼內容
- 1 pyzbar二維碼檢測模塊
- 1.1. pyzbar模塊介紹
- 1.2 pyzbar模塊的安裝
- 1.3 pyzbar模塊測驗用例
- 2 python3 + opencv +pyzbar實時檢測二維碼,并繪制二維碼的矩形框
1 pyzbar二維碼檢測模塊
- pyzbar的github主頁:https://github.com/NaturalHistoryMuseum/pyzbar
- pyzbar的pypi主頁:https://pypi.org/project/pyzbar/
1.1. pyzbar模塊介紹
1、該模塊是一個日本的author開源的一個二維碼檢測的專案,可以用來檢測:
- 二維碼
- 條形碼
同時可以回傳檢測二維碼和條形碼的相關資訊:
- 二維碼中包含的資訊
- 檢測二維碼的矩形框
- 檢測二維碼的最小外接多邊形框
2、pyzbar支持兩種資料型別輸入:
- PIL讀取的
PIL.Image資料型別 - opencv讀取的
ndarray資料型別
1.2 pyzbar模塊的安裝
1、Mac OS X:
brew install zbar
2、Linux:
sudo apt-get install libzbar0
3、直接使用pip安裝
pip install pyzbar
1.3 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()
檢測結果:

2 python3 + opencv +pyzbar實時檢測二維碼,并繪制二維碼的矩形框
- 連接攝像頭,運行程式即可實時檢測二維碼
- 按
q鍵,退出顯示和程式運行
__Author__ = "Shliang"
__Email__ = "shliang0603@gmail.com"
# 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()
顯示結果如下:

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/279592.html
標籤:python
