📢 公告:OpenCV 系列文章重構完成(75%)。專案實作篇仍在製作中,完成時間未定,敬請期待!→ 查看文章索引

熱門系列
Like Share Discussion Bookmark Smile

J.J. Huang   2026-04-12   Python OpenCV 08.專案實作篇   瀏覽次數:次   DMCA.com Protection Status

Python | OpenCV QR Code 與 BarCode 辨識

📚 前言

與 OpenCV 整合推論 中,我們學會了如何把深度學習模型整合進 OpenCV 的視訊流程。

這一篇介紹一個非常實用的應用:QR Code 與 BarCode 辨識
從商品掃碼、入場驗票到倉儲管理,條碼掃描是日常中最常見的電腦視覺應用之一,而且實作起來相對簡單。

🎨 範例圖片

這裡我們使用 BarcodeOcean 提供的條碼產生器:BarcodeOcean
使用「生成QR Code」產生後,下載將檔名改為 qrcode.png,放在 assets/,即可用於以下各範例。
使用「生成條碼」產生後,下載將檔名改為 Barcode.png,放在 assets/,即可用於以下各範例。

🛠️ 套件安裝

OpenCV 內建 QRCodeDetector 可解碼 QR Code,Barcode 辨識則建議搭配 pyzbar 套件:

1
2
pip install pyzbar
pip install qrcode[pil] # 若需要產生 QR Code

💡 Windows 使用者若安裝 pyzbar 後出現 zbar DLL not found 錯誤,需另外下載 zbar DLL:
可安裝 pip install pyzbar-win32-fix 或從 zbar 官網 下載 DLL 後放入 %SystemRoot%\System32

💻 使用 OpenCV 解碼 QR Code

OpenCV 內建 cv2.QRCodeDetector,不需要額外套件即可解碼 QR Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# decode_qrcode_opencv.py
import cv2

img = cv2.imread("assets/qrcode.png")
detector = cv2.QRCodeDetector()

# detectAndDecode:同時偵測位置與解碼
# 回傳三個值:解碼字串、邊框座標、灰度圖;灰度圖不需要用到,以 _ 表示丟棄
data, bbox, _ = detector.detectAndDecode(img)

if data:
print(f"QR Code 內容:{data}")

# bbox 為四個角點座標,繪製邊框
if bbox is not None:
bbox = bbox.astype(int) # bbox 預設為 float,繪圖函式需要整數座標
for i in range(len(bbox[0])):
pt1 = tuple(bbox[0][i])
pt2 = tuple(bbox[0][(i + 1) % len(bbox[0])])
cv2.line(img, pt1, pt2, (0, 255, 0), 2)

cv2.putText(img, data, (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2)
else:
print("未偵測到 QR Code")

cv2.imshow("QR Code", img)
cv2.waitKey(0)
cv2.destroyAllWindows()


圖:使用 OpenCV 內建 QRCodeDetector 解碼圖片中的 QR Code,繪製邊框並顯示解碼內容

💻 使用 pyzbar 解碼 QR Code 與 BarCode

pyzbar 支援多種條碼格式(QR Code、Code128、EAN-13、EAN-8、UPC-A 等),是更通用的選擇:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# decode_barcode_pyzbar.py
import cv2
from pyzbar import pyzbar

img = cv2.imread("assets/Barcode.png")

# decode 會回傳圖片中所有偵測到的條碼
barcodes = pyzbar.decode(img)

for barcode in barcodes:
# barcode.data 是 bytes(二進位),需要 decode 成一般字串才能印出或比對
data = barcode.data.decode("utf-8")
bc_type = barcode.type # 條碼格式,例如:QRCODE、CODE128、EAN13

# barcode.rect:(x, y, w, h)
x, y, w, h = barcode.rect
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)

label = f"{bc_type}: {data}"
cv2.putText(img, label, (x, y - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
print(f"類型:{bc_type},內容:{data}")

cv2.imshow("Barcode", img)
cv2.waitKey(0)
cv2.destroyAllWindows()


圖:使用 pyzbar 解碼圖片中的 QR Code 或 BarCode,繪製矩形框並輸出條碼類型與內容

💻 即時攝影機掃描

結合攝影機做即時掃描,是最常見的應用場景:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# scan_camera.py
import cv2
from pyzbar import pyzbar

cap = cv2.VideoCapture(0) # 0 表示第一支攝影機;若有多支可改為 1、2…
if not cap.isOpened():
print("無法開啟攝影機,請確認設備是否連接")
exit()
print("對準條碼,按 q 離開")

scanned = set() # 避免重複顯示同一條碼

while True:
ret, frame = cap.read()
if not ret:
break

barcodes = pyzbar.decode(frame)

for barcode in barcodes:
data = barcode.data.decode("utf-8")
bc_type = barcode.type

x, y, w, h = barcode.rect
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.putText(frame, f"{bc_type}: {data}", (x, y - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)

if data not in scanned:
scanned.add(data)
print(f"掃描到 [{bc_type}]:{data}")

cv2.imshow("Scanner", frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break

cap.release()
cv2.destroyAllWindows()

📝 註:由於本身沒有攝影鏡頭,所以無法示範效果。

💻 批次處理圖片資料夾

需要批次掃描大量圖片時(如倉儲盤點照片):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# batch_scan.py
import cv2
import os
from pyzbar import pyzbar

img_dir = "assets/"
results = []

for fname in os.listdir(img_dir):
if not fname.lower().endswith((".jpg", ".jpeg", ".png")):
continue

img = cv2.imread(os.path.join(img_dir, fname))
barcodes = pyzbar.decode(img)

for barcode in barcodes:
data = barcode.data.decode("utf-8")
bc_type = barcode.type
results.append({"file": fname, "type": bc_type, "data": data})
print(f"{fname} [{bc_type}] {data}")

print(f"\n共掃描 {len(results)} 筆條碼")


圖:批次掃描目錄中的所有圖片,輸出每張圖片中偵測到的條碼類型、內容與統計筆數

💻 產生 QR Code

使用 qrcode 套件產生自訂的 QR Code 圖片:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# generate_qrcode.py
import qrcode
import os

output_dir = "output"

# 如果 output 資料夾不存在,就自動建立
if not os.path.exists(output_dir):
os.makedirs(output_dir)
print(f"已自動建立資料夾:{output_dir}")

# 基本 QR Code
data1 = "https://morosedog.gitlab.io/"

img1 = qrcode.make(data1)

# 存到 output 資料夾
save_path1 = os.path.join(output_dir, "qrcode_basic.png")
img1.save(save_path1)
print(f"基本 QR Code 已儲存 → {save_path1}")

# 自訂樣式 QR Code
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_H, # 高容錯
box_size=10,
border=4,
)

qr.add_data("Hello, OpenCV!")
qr.make(fit=True)

img2 = qr.make_image(fill_color="black", back_color="white")

# 存到 output 資料夾
save_path2 = os.path.join(output_dir, "qrcode_custom.png")
img2.save(save_path2)
print(f"自訂 QR Code 已儲存 → {save_path2}")

print("✅ 所有 QR Code 產生完成!")


圖:使用 qrcode 套件產生基本與自訂樣式的 QR Code 圖片,設定容錯等級、格子大小與邊框


圖:QR Code 錯誤修正等級(Error Correction Level)比較表,包含各等級的可容錯比例與建議使用情境

💻 用 OpenCV 驗證產生的 QR Code

產生後立刻用 OpenCV 驗證是否可正常讀取:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# verify_qrcode.py
import qrcode
import cv2
import numpy as np
import os

# 產生 QR Code
data = "驗證測試字串" # ← 你要驗證的內容

# 使用 qrcode 產生 QR Code(PIL Image)
qr_pil = qrcode.make(data)

# PIL → OpenCV 格式轉換
rgb_array = np.array(qr_pil.convert("RGB")) # PIL Image → numpy array (RGB)
img = cv2.cvtColor(rgb_array, cv2.COLOR_RGB2BGR) # RGB → BGR (OpenCV 格式)

# 驗證 QR Code
detector = cv2.QRCodeDetector()
decoded_data, bbox, _ = detector.detectAndDecode(img)

print(f"原始內容:{data}")
print(f"解碼結果:{decoded_data}")

if decoded_data == data:
print("✅ 驗證成功!產生與解碼一致")
else:
print("❌ 驗證失敗")

# 儲存圖片到 output 資料夾
output_dir = "output"
if not os.path.exists(output_dir):
os.makedirs(output_dir)

save_path = os.path.join(output_dir, "qrcode_verify.png")
cv2.imwrite(save_path, img)
print(f"圖片已儲存至:{save_path}")

# 顯示圖片
cv2.imshow("Generated QR Code", img)
cv2.waitKey(0)
cv2.destroyAllWindows()


圖:產生 QR Code 後立即用 OpenCV QRCodeDetector 解碼驗證,確認生成與讀取結果一致

⚠️ 注意事項

  • 圖片品質影響辨識率:模糊、光線不足、角度過斜都會降低辨識率。實際應用時建議先做影像前處理(灰階、銳化)再解碼。
  • pyzbar 比 OpenCV 內建的 QRCodeDetector 更通用:OpenCV 只能解 QR Code,pyzbar 支援十幾種條碼格式,建議以 pyzbar 為主。
  • pyzbar 在 macOS 上需要額外安裝 zbarbrew install zbar
  • 容錯等級越高,QR Code 越複雜ERROR_CORRECT_H 雖然耐用,但產生的圖案較密集,距離過遠時反而難以掃描。
  • scanned set 防止重複觸發:即時掃描時同一個條碼可能連續數幀都被偵測到,用 set 記錄已掃描的內容可避免重複處理。

📊 應用場景

  • 門票驗證:掃描入場 QR Code,即時查詢資料庫確認有效性。
  • 商品盤點:批次掃描倉庫照片,自動統計 EAN-13 條碼數量。
  • 名片辨識:掃描名片上的 QR Code,擷取聯絡資訊。
  • 產線追蹤:每個產品貼上 QR Code,在生產各階段掃描記錄流程。

🎯 結語

QR Code 與 BarCode 辨識是電腦視覺中相對容易上手、卻非常實用的一塊。
搭配 pyzbar 與 OpenCV,幾十行程式就能完成即時掃描系統。

下一篇將進入 OpenCV 專案:即時濾鏡相機,實作一個可即時切換、疊加多種視覺效果的濾鏡相機。

📖 如在學習過程中遇到疑問,或是想了解更多相關主題,建議回顧一下 Python | OpenCV 系列導讀,掌握完整的章節目錄,方便快速找到你需要的內容。

註:以上參考了
OpenCV QRCodeDetector 官方文件
pyzbar GitHub
qrcode PyPI