The QR code or Quick Response code is a two-dimensional or matrix barcode invented in the early nineties by a Japanese car manufacturer. QR codes started to become popular in warehousing, marketing, and other areas in the early 2010s and the technology to read them is now built into the cameras of pretty much every smartphone.
Most recently, you’ll probably have noticed QR codes on the fronts of lateral flow tests for Covid 19. By scanning the QR code, scientists can quickly extract the unique code number embedded in the QR code in a reliable manner and import it directly into a database or other application.
QR codes are popular because they are fast to read, have a higher storage capacity than typical UPC barcodes, and include built in error checking. In this project, I’ll show you how you can develop a Python QR code reader to read the QR code shown on images of Covid 19 tests to extract the unique reference code for the kit issued using the OpenCV computer visualisation library.
First, open a Jupyter notebook and install the OpenCV computer visualisation package using !pip install opencv-python
. Confusingly, although the computer visualisation package is known (and imported) using the cv2
name, the library itself is called opencv-python
, not cv2
.
!pip install opencv-python
Collecting opencv-python
Downloading opencv_python-4.5.5.64-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (60.5 MB)
[K |████████████████████████████████| 60.5 MB 8.7 MB/s eta 0:00:011
[?25hRequirement already satisfied: numpy>=1.14.5; python_version >= "3.7" in /conda/envs/data-science-stack-2.5.1/lib/python3.7/site-packages (from opencv-python) (1.19.4)
Installing collected packages: opencv-python
Successfully installed opencv-python-4.5.5.64
Next, import the packages required. Technically, we only really need cv2
to read the QR code, but we’re going to write a bit of extra code that will read an entire directory of images of Covid 19 lateral flow test images and extract their QR code values and store the data in a Pandas dataframe, so we need a few others.
import glob
import cv2
import pandas as pd
import pathlib
To avoid repetition later, we’ll create a simple helper function called read_qr_code()
to read the value embedded in the QR code that may (or may not) be present on each image. We’ll pass the filename
to the function holding the path to the file, then we’ll use the cv2.imread()
function to read the image.
We’ll then instantiate the cv2.QRCodeDetector()
class and use the detectAndDecode()
function to extract the data from the QR code, if one can be read. The detectAndDecode()
function actually returns several values, but we only want the text stored in the QR code, so we’re only returning the value
part. If we don’t find a code, we’ll return nothing via a crude Python try except block.
def read_qr_code(filename):
"""Read an image and read the QR code.
Args:
filename (string): Path to file
Returns:
qr (string): Value from QR code
"""
try:
img = cv2.imread(filename)
detect = cv2.QRCodeDetector()
value, points, straight_qrcode = detect.detectAndDecode(img)
return value
except:
return
To test the function we’ll load up an image of a lateral flow test result showing a QR code by passing the file path to the read_qr_code()
function we just created, then we’ll print out the value. This successfully extracts the correct digits from the QR code image using the QR code reader.
value = read_qr_code('data/00003090-PHOTO-2022-03-19-08-31-34.jpg')
value
'LXQ12345774'
If you’ve got hundreds or thousands of images, you can scale up this approach to scan an entire directory and extract the QR code values and store the data. To do this we’ll first create a Pandas dataframe called df
that has two columns - filename
and qr
, then we’ll load all the .jpg
files from the /data
directory and store the list in files
.
Then we can use a for
loop to loop over files
and run the read_qr_code()
function on each file, storing the filename and QR code value back to our dataframe. In just a few minutes, OpenCV can open, read, and detect the QR codes in thousands of images and store the outputs for you.
df = pd.DataFrame(columns=['filename', 'qr'])
files = glob.glob('data/*.jpg')
for file in files:
qr = read_qr_code(file)
row = {'filename': file, 'qr': qr}
df = df.append(row, ignore_index=True)
df.head()
filename | qr | |
---|---|---|
0 | data/00003090-PHOTO-2022-03-19-08-31-34.jpg | LXQ12345774 |
Want to learn how to read QR codes in Python? Check out my other tutorial for details…
Matt Clarke, Monday, March 21, 2022