In the past two weeks, I trained a custom YOLOv3 model for QR code detection and tested it with Darknet. In this article, I will use OpenCV’s DNN (Deep Neural Network) module to load the YOLO model for making detection from static images and real-time camera video stream. Besides, I will use Dynamsoft Barcode Reader to decode QR codes from the regions detected by YOLO.

YOLO QR Code Detection with OpenCV Python
Install OpenCV (CPU only) via pip:
pip install opencv-python
You can get qrcode.names, qrcode-yolov3-tiny.cfg and qrcode-yolov3-tiny.weights files from the package YOLOv3-tiny-QR.
To quickly get familiar with the OpenCV DNN APIs, we can refer to object_detection.py, which is a sample included in the OpenCV GitHub repository.
Now, let’s implement the QR detection code logic step by step.
First, we need to read an image to a Mat object using the imread() function. In case the image size is too large to display, I defined the maximum width and height values:
frame = cv.imread("416x416.jpg") threshold = 0.6 maxWidth = 1280; maxHeight = 720 imgHeight, imgWidth = frame.shape[:2] hScale = 1; wScale = 1 thickness = 1 if imgHeight > maxHeight: hScale = imgHeight / maxHeight thickness = 6 if imgWidth > maxWidth: wScale = imgWidth / maxWidth thickness = 6
The next step is to initialize the network by loading the *.names, *.cfg and *.weights files:
classes = open('qrcode.names').read().strip().split('\n') net = cv.dnn.readNetFromDarknet('qrcode-yolov3-tiny.cfg', 'qrcode-yolov3-tiny.weights') net.setPreferableBackend(cv.dnn.DNN_BACKEND_OPENCV)
The network requires a blob object as the input, therefore we can convert the Mat object to a blob object as follows:
blob = cv.dnn.blobFromImage(frame, 1/255, (416, 416), swapRB=True, crop=False)
Determine the output layer, and then input the blob object to the network and perform a forward pass:
ln = net.getLayerNames() ln = [ln[i[0] - 1] for i in net.getUnconnectedOutLayers()]
net.setInput(blob) outs = net.forward(ln)
As we get the network outputs, we can extract class names, confidence scores, and bounding boxes. In the meantime, we can draw them with OpenCV APIs:
def postprocess(frame, outs): frameHeight, frameWidth = frame.shape[:2] classIds = [] confidences = [] boxes = [] for out in outs: for detection in out: scores = detection[5:] classId = np.argmax(scores) confidence = scores[classId] if confidence > threshold: x, y, width, height = detection[:4] * np.array([frameWidth, frameHeight, frameWidth, frameHeight]) left = int(x - width / 2) top = int(y - height / 2) classIds.append(classId) confidences.append(float(confidence)) boxes.append([left, top, int(width), int(height)]) indices = cv.dnn.NMSBoxes(boxes, confidences, threshold, threshold - 0.1) for i in indices: i = i[0] box = boxes[i] left = box[0] top = box[1] width = box[2] height = box[3] # Draw bounding box for objects cv.rectangle(frame, (left, top), (left + width, top + height), (0, 0, 255), thickness) # Draw class name and confidence label = '%s:%.2f' % (classes[classIds[i]], confidences[i]) cv.putText(frame, label, (left, top), cv.FONT_HERSHEY_SIMPLEX, 0.5, (255,255,255))
Finally, we could adjust the image size to display appropriately on screen:
if hScale > wScale: frame = cv.resize(frame, (int(imgWidth / hScale), maxHeight)) elif hScale < wScale: frame = cv.resize(frame, (maxWidth, int(imgHeight / wScale))) cv.imshow('QR Detection', frame) cv.waitKey()

Decoding QR Code with Dynamsoft Barcode Reader
Once the QR code detection is done, we can get the corresponding bounding boxes, with which we are able to take a further step to decode the QR code.
Install Dynamsoft Barcode Reader:
pip install dbr
According to the coordinates of bounding boxes, we can decode the QR code by setting region parameters. Region decoding is much faster than the full image decoding:
from dbr import * # Initialize Dynamsoft Barcode Reader reader = BarcodeReader() # Apply for a trial license: https://www.dynamsoft.com/customer/license/trialLicense license_key = "LICENSE KEY" reader.init_license(license_key) def decodeframe(frame, left, top, right, bottom): settings = reader.reset_runtime_settings() settings = reader.get_runtime_settings() settings.region_bottom = bottom settings.region_left = left settings.region_right = right settings.region_top = top settings.barcode_format_ids = EnumBarcodeFormat.BF_QR_CODE settings.expected_barcodes_count = 1 reader.update_runtime_settings(settings) try: text_results = reader.decode_buffer(frame) if text_results != None: return text_results[0] except BarcodeReaderError as bre: print(bre) return None
On my screenshot, you can see the decoding result is obfuscated because I didn’t use a valid license key. If you want to experience the full functionalities of Dynamsoft Barcode Reader, you’d better apply for a free trial license.

References
- https://opencv-tutorial.readthedocs.io/en/latest/yolo/yolo.html
- https://docs.opencv.org/master/d6/d0f/group__dnn.html
- https://docs.opencv.org/3.4/db/d30/classcv_1_1dnn_1_1Net.html
Source Code
https://github.com/yushulx/opencv-yolo-qr-detection
The post How to Detect and Decode QR Code with YOLO, OpenCV, and Dynamsoft Barcode Reader appeared first on Dynamsoft Developers.