DaisyKit: AI for Everyone
8 / 10
Lesson 8 of 10

Lesson 08: Barcode & QR Code Scanning

4 min readViet-Anh NguyenViet-Anh Nguyen

BarcodeScannerFlow is DaisyKit's barcode and QR code reader. Unlike the other flows, it uses no neural network — it is powered by ZXing-CPP, a fast classical computer vision algorithm. This means it works offline, requires no model download, and runs instantly even on low-power hardware.

Barcode scanner detecting a QR code and a product barcode in real time

Supported Formats

ZXing-CPP reads all major 1D and 2D barcode formats:

TypeFormats
2DQR Code, Data Matrix, PDF417, Aztec Code
1DEAN-13, EAN-8, UPC-A, UPC-E, Code 128, Code 39

Configuration

import json

config = {
    "try_harder": True,    # try multiple scanning angles — slower but more robust
    "try_rotate": True,    # scan rotated barcodes (helps with tilted codes)
}

BarcodeScannerFlow takes no model paths — there is nothing to download.

Real-Time Webcam Demo

import cv2
import json
from daisykit import BarcodeScannerFlow
from daisykit.utils import to_py_type

config = {"try_harder": True, "try_rotate": True}
flow = BarcodeScannerFlow(json.dumps(config))

cap = cv2.VideoCapture(0)

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

    rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

    # draw=True draws the detected region and decoded text on rgb
    result = flow.Process(rgb, draw=True)

    display = cv2.cvtColor(rgb, cv2.COLOR_RGB2BGR)
    cv2.imshow("Barcode Scanner", display)

    # Print decoded values
    results_py = to_py_type(result)
    for r in results_py:
        print(f"  [{r['format']}] {r['text']}")

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

cap.release()
cv2.destroyAllWindows()

Reading Barcode Data

from daisykit.utils import to_py_type

result = flow.Process(rgb, draw=False)  # draw=False for raw data only
codes = to_py_type(result)

for code in codes:
    print(f"Format: {code['format']}")   # e.g. "QR_CODE", "EAN_13"
    print(f"Text:   {code['text']}")     # decoded string content
    print(f"Points: {code['points']}")   # corner points of the code region

Scanning a Static Image

import cv2
from daisykit import BarcodeScannerFlow
from daisykit.utils import to_py_type
import json

# Generate a test QR code image first:
# pip install qrcode pillow
import qrcode
qr = qrcode.make("https://vietanh.dev")
qr.save("test_qr.png")

config = {"try_harder": True, "try_rotate": True}
flow = BarcodeScannerFlow(json.dumps(config))

img = cv2.imread("test_qr.png")
rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

result = flow.Process(rgb, draw=True)
codes = to_py_type(result)

for code in codes:
    print(f"  Decoded: {code['text']}")
# Expected: "https://vietanh.dev"

cv2.imwrite("qr_result.jpg", cv2.cvtColor(rgb, cv2.COLOR_RGB2BGR))

Building a URL Launcher

A practical example: scan a QR code and open the URL in a browser automatically.

import cv2
import json
import webbrowser
from daisykit import BarcodeScannerFlow
from daisykit.utils import to_py_type

config = {"try_harder": True, "try_rotate": True}
flow = BarcodeScannerFlow(json.dumps(config))

cap = cv2.VideoCapture(0)
seen = set()  # avoid opening the same URL twice

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

    rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    result = flow.Process(rgb, draw=True)
    codes = to_py_type(result)

    for code in codes:
        text = code["text"]
        if text not in seen:
            seen.add(text)
            print(f"Scanned: {text}")
            if text.startswith("http"):
                webbrowser.open(text)

    display = cv2.cvtColor(rgb, cv2.COLOR_RGB2BGR)
    cv2.imshow("QR URL Launcher", display)

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

cap.release()
cv2.destroyAllWindows()

Performance Tips

  • try_harder=False, try_rotate=False — fastest mode, only scans axis-aligned codes
  • try_harder=True, try_rotate=True — robust but ~2× slower
  • For production systems with high scan volume, use try_harder=False and rotate the image yourself before scanning

Applications

  • Inventory management — scan product barcodes to update stock
  • Smart attendance — students scan a QR code to register presence
  • Contactless menus — restaurants use QR codes to serve digital menus
  • Asset tracking — scan labels on equipment for maintenance logs
  • IoT projects — Raspberry Pi reads QR codes to trigger actions

Conclusion

BarcodeScannerFlow handles all common 1D and 2D code formats with no model download, no GPU, and no training data. It's the simplest flow in DaisyKit to deploy. In the next lesson we take DaisyKit to mobile — Android and iOS.