Detect and read QR codes with OpenCV in Python

Posted: | Tags: Python, OpenCV, Image Processing

This article describes how to detect and read QR codes with OpenCV in Python.

  • cv2.QRCodeDetector
  • Detect and read QR codes from an image
  • Detect and read QR codes from camera video

See the following article on how to create a QR code.

See the following article on how to detect and read barcodes instead of QR codes.

You can also use ZBar (pyzbar). Although not thoroughly verified, ZBar seems to have better detection accuracy.

The version of OpenCV used in the sample code is 4.6.0.

import cv2

print(cv2.__version__)
# 4.6.0

cv2.QRCodeDetector

The cv2.QRCodeDetector class is used to detect and read QR codes.

In version 4.3, detectAndDecodeMulti() was added to detect and decode multiple QR codes at once.

Although detect() to only detect and decode() to decode based on the detected coordinates are also provided, they are not mentioned here.

Detect and read QR codes from an image

The following image is used as an example.

The text stored in each QR Code is, from left to right, QR Code One, QR Code Two, and QR Code Three. The rightmost QR Code is masked with a white square in the center to make it difficult to read.

img = cv2.imread('data/src/qrcode.png')

QR code sample

Create an instance of cv2.QRCodeDetector and execute detectAndDecodeMulti(). Note that the result may differ depending on the version and environment.

qcd = cv2.QRCodeDetector()

retval, decoded_info, points, straight_qrcode = qcd.detectAndDecodeMulti(img)

retval is True if a QR code is detected and False if none is detected.

print(retval)
# True

decoded_info is a tuple whose elements are strings stored in QR codes. If it can be detected but not decoded, it is an empty string ''.

print(decoded_info)
# ('QR Code Two', '', 'QR Code One')

points is a numpy.ndarray representing the coordinates of the four corners of the detected QR Code.

print(type(points))
# <class 'numpy.ndarray'>

print(points)
# [[[290.9108    106.20954  ]
#   [472.8162      0.8958926]
#   [578.5836    184.1002   ]
#   [396.0495    287.81277  ]]
# 
#  [[620.         40.       ]
#   [829.         40.       ]
#   [829.        249.       ]
#   [620.        249.       ]]
# 
#  [[ 40.         40.       ]
#   [249.         40.       ]
#   [249.        249.       ]
#   [ 40.        249.       ]]]

print(points.shape)
# (3, 4, 2)

straight_qrcode is a tuple whose elements are numpy.ndarray. The numpy.ndarray is a binary value of 0 and 255 representing the black and white of each cell of the QR code.

print(points.shape)
# (3, 4, 2)

print(type(straight_qrcode))
# <class 'tuple'>

print(type(straight_qrcode[0]))
# <class 'numpy.ndarray'>

print(straight_qrcode[0].shape)
# (21, 21)

Draw frames for the detected QR code and superimpose the decoded text.

img = cv2.polylines(img, points.astype(int), True, (0, 255, 0), 3)

for s, p in zip(decoded_info, points):
    img = cv2.putText(img, s, p[0].astype(int),
                      cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2, cv2.LINE_AA)

cv2.imwrite('data/dst/qrcode_opencv.jpg', img)

Detect and decode QR code with OpenCV

Detect and read QR codes from camera video

The following is a sample code that detects and reads barcodes from real-time camera video.

See the following article for more information on the handling of videos in OpenCV.

Press q on the keyboard to exit.

import cv2

camera_id = 0
delay = 1
window_name = 'OpenCV QR Code'

qcd = cv2.QRCodeDetector()
cap = cv2.VideoCapture(camera_id)

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

    if ret:
        ret_qr, decoded_info, points, _ = qcd.detectAndDecodeMulti(frame)
        if ret_qr:
            for s, p in zip(decoded_info, points):
                if s:
                    print(s)
                    color = (0, 255, 0)
                else:
                    color = (0, 0, 255)
                frame = cv2.polylines(frame, [p.astype(int)], True, color, 8)
        cv2.imshow(window_name, frame)

    if cv2.waitKey(delay) & 0xFF == ord('q'):
        break

cv2.destroyWindow(window_name)

If a QR code can be detected but not decoded, a red frame is displayed; if it can be decoded, a green frame is displayed. If you want to display the decoded string, please refer to the still image example above.

In an actual application, the while loop would be terminated by break when the decoded_info string is obtained, and the application would move on to operation using the string.

Related Categories

Related Articles