A robust, production-grade QR code detection and decoding system designed to handle real-world failures where OpenCV alone is insufficient.
This project combines:
- OpenCV → detection, geometry, cropping, visualization
- ZXing/ZBar (via pyzbar) → reliable decoding fallback
- ArUco markers (optional) → constrained search & noise reduction
This architecture is similar to what is used in payment apps, scanners, and industrial CV systems.
├── python_detect_qr.py # Main QR detection & decoding pipeline
├── image_processor.py # 10 image preprocessing techniques (optional)
├── README.md
├── requirements.txt
├── Pictures/ # Input images
├── Output/ # Visualized results for image processor
└── Outputs/ # Visualized results for QR Reader
- Python ≥ 3.10
- Linux / macOS / Windows
(Linux recommended for ZBar stability)
Linux (Ubuntu/Debian):
sudo apt install libzbar0EndeavourOS / Arch Linux / Manjaro:
sudo pacman -S zbarmacOS (Homebrew):
brew install zbarWindows:
- Install ZBar binaries
- Or use WSL (recommended)
python -m venv .venv
source .venv/bin/activate # Linux / macOS
# .venv\Scripts\activate # Windowspip install -r requirements.txtpython python_detect_qr.pypython python_detect_qr.py --input_dir Pictures --out_dir Outputpython python_detect_qr.py --marker_ids 43 44 101 102- OpenCV detectAndDecodeMulti
- Multi-scale retry
- ROI-based enhanced decode (CLAHE + scaling)
- ZXing/ZBar fallback (final authority)
If a QR fails after ZBar, it is either:
- invalid
- decorative
- missing quiet zone
- non-standard
No further CV tricks will help.
For each input image:
<name>_result.jpgis generated inOutput/
Visualization includes:
- 🟢 Green polygon → decoded QR
- 🔴 Polygon only → detected but undecodable
- Text rendered on expanded, centered canvas (never clipped)
Update the picture name at the bottom of 'image_processor.py' Run:
python image_processor.pyGenerates:
- 10 preprocessing variants
- Side-by-side comparisons
- Collage output
Useful for analysis, debugging, and documentation — not required for decoding.
Total QR found : 7
Successfully read : 7
Average time/img : ~0.3s
Decode rate is limited by QR validity, not the pipeline.
- Detection ≠ decoding
- Geometry first, decoding second
- Fallbacks are explicit, not magic
- OpenCV has limits — ZXing/ZBar exists for a reason
This is the correct end-state of a serious QR pipeline.
Article: 10 Image Processing Techniques for Computer Vision
Note
pyzbarrequires system-level ZBar (libzbar0/zbar) It will NOT work with pip alone.