This website is made possible by displaying online advertisements to our visitors.
Please consider supporting us by disabling your ad blocker. Thank you for your support.
This website is made possible by displaying online advertisements to our visitors.
Please consider supporting us by disabling your ad blocker.

Barcode and QR Code Scanner with OpenCV and Python

Feb. 26 2023 Yacine Rouizi
OpenCV Image Processing Computer Vision
Barcode and QR Code Scanner with OpenCV and Python

In this tutorial, we are going to build a simple barcode and QR code scanner using OpenCV and the ZBar library.

The ZBar library will be responsible for detecting and localizing the QR codes and barcodes. OpenCV will be used for some preprocessing steps such as loading the image, looping through the detected barcodes, and displaying the results. 

Barcodes and QR Codes Scanner on Images

The first thing we need to do is to install the ZBar library.

The command below is for installing ZBar on Ubuntu, if you have another operating system, please check this page to see how to install it.

sudo apt-get install libzbar0

Next, we need to install the pyzbar Python wrapper because ZBar does not support Python3:

pip install pyzbar

Now we can start writing some code. Let's import the required packages and see how to detect barcodes on an image:

import cv2
import numpy as np
from pyzbar import pyzbar

image = cv2.imread("image.png")
image = cv2.resize(image, (640, 850))

red = (0, 0, 255)
blue = (255, 0, 0)
qrcode_color = (255, 255, 0)
barcode_color = (0, 255, 0)

# decode and detect the QR codes and barcodes
barcodes = pyzbar.decode(image)

We start by loading the cv2, numpy, and pyzbar packages. We then load our image from disk and resize it.

Next, we declare some variables of colors that will be useful later for display purposes.

Finally, we used the decode function from pyzbar to decode and detect the QR codes and barcodes on the image.

This function returns a list containing all detected QR codes and barcodes.

Each element in the list is either a QR code or a barcode along with some useful information, such as the text and location of the barcode on the image.

Here is an example of what the barcodes list can contain:

[Decoded(data=b'https://dontrepeatyourself.org/', type='QRCODE', rect=Rect(left=200, top=222, width=102, height=102), 
        polygon=[Point(x=200, y=273), Point(x=250, y=324), Point(x=302, y=273), Point(x=250, y=222)]), 
 Decoded(data=b'DontRepeatYourself', type='QRCODE', rect=Rect(left=26, top=244, width=127, height=128), 
         polygon=[Point(x=26, y=335), Point(x=119, y=372), Point(x=153, y=279), Point(x=62, y=244)])]

In this example, there are two QR codes stored in the list. So we can loop over the barcodes to extract each barcode and process it.

Let's see how to do it:

# initialize the total number of QR codes and barcodes
qr_code = 0
code = 0

for barcode in barcodes:
    # extract the points of th polygon of the barcode and create a Numpy array
    pts = np.array([barcode.polygon], np.int32)
    pts = pts.reshape((-1,1,2))

    # check to see if this is a QR code or a barcode
    if barcode.type == "QRCODE":
        qr_code += 1
        cv2.polylines(image, [pts], True, qrcode_color, 3)
    elif barcode.type == "CODE128":
        code += 1
        cv2.polylines(image, [pts], True, barcode_color, 3)

    # decode the barcode data and draw it on the image
    text = "{}".format(barcode.data.decode("utf-8"))
    cv2.putText(image, text, (barcode.rect[0] + 10, barcode.rect[1] - 10), 
                cv2.FONT_HERSHEY_SIMPLEX, 0.5, red, 2)

We start by initializing two variables to keep track of the number of QR codes and barcodes.

Then we start looping over the barcodes, create a Numpy array, and reshape it in order to use it to draw the bounding box around the barcode.

Next, we check whether the detected code is a QR code or a barcode. If it's a QR code we increment the qr_code variable and draw the bounding box around the QR code using the cv2.polylines function, and if it is a barcode we increment the code variable and draw the bounding box around the barcode.

You can also see that we are using a different color to draw the bounding box for the QR code and the barcode.

Finally, we draw the barcode data on the image using the cv2.putText function.

After finishing processing the barcodes, we can display the number of QR codes and barcodes detected on the image:

# Display the number of QR codes and barcodes detected
if len(barcodes) == 0:
    text = "No barcode found on this image"
    cv2.putText(image, text, (20, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.75, blue, 2)
else:
    text = "{} QR code(s) found on this image".format(qr_code)
    cv2.putText(image, text, (20, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.75, blue, 2)
    text = "{} barcode(s) found on this image".format(code)
    cv2.putText(image, text, (20, 43), cv2.FONT_HERSHEY_SIMPLEX, 0.75, blue, 2)

cv2.imshow("Image", image)
cv2.waitKey(0)

if the barcodes list is empty, this means that the function didn't detect any barcode. We display the text "No barcode found on this image".

Otherwise, we display the number of QR codes and barcodes.

Below you can see the output of the barcode detection script:

barcode detection on images

You can see that we were able to detect all QR codes and barcodes on the image!

Barcodes and QR Codes Scanner on Videos

There is nothing special to do in order to detect QR codes and barcodes on a video. We just need to read the video and put all the previous code inside the while loop.

Let's start by initializing the video capture object, looping over the frames and resizing them, and decoding the QR codes and barcodes:

video_cap = cv2.VideoCapture("video.mp4")

red = (0, 0, 255)
blue = (255, 0, 0)
qrcode_color = (255, 255, 0)
barcode_color = (0, 255, 0)

while True:
    # read and resize the frames
    success, frame = video_cap.read()
    frame = cv2.resize(frame, (480, 640))
    barcodes = pyzbar.decode(frame)

Next, we can put the exact same code as before to loop over the barcodes and process each of them:

    # initialize the total number of QR codes and barcodes
    qr_code = 0
    code = 0

    for barcode in barcodes:
        pts = np.array([barcode.polygon], np.int32)
        pts = pts.reshape((-1,1,2))
        if barcode.type == "QRCODE":
            qr_code += 1
            cv2.polylines(frame, [pts], True, qrcode_color, 3)
        elif barcode.type == "CODE128":
            code += 1
            cv2.polylines(frame, [pts], True, barcode_color, 3)
    
        text = "{}".format(barcode.data.decode("utf-8"))
        cv2.putText(frame, text, (barcode.rect[0] + 10, barcode.rect[1] - 10), cv2.FONT_HERSHEY_SIMPLEX,
            0.5, red, 2)
    
    if len(barcodes) == 0:
        text = "No barcode detected"
        cv2.putText(frame, text, (20, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.75, blue, 2)
    else:
        text = "{} QR code(s) detected".format(qr_code)
        cv2.putText(frame, text, (20, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.75, blue, 2)
        text = "{} barcode(s) detected".format(code)
        cv2.putText(frame, text, (20, 43), cv2.FONT_HERSHEY_SIMPLEX, 0.75, blue, 2)

    cv2.imshow("frame", frame)
    # wait for 1 milliseconde and if the q 
    # key is pressed we break the loop
    if cv2.waitKey(1) == ord('q'):
        break

Finally, we need to release the video capture object and destroy all the windows:

video_cap.release()
cv2.destroyAllWindows()

Check out the result in the video below, make sure to download the sample image and video from this link:

You can see that barcodes and small QR codes are a little harder to detect but overall the result is good.

Summary

So now you have a Python script that detects QR codes and barcodes which you can use on your own project. Try to add some functionality like for example, saving the results in a file or decoding the barcode data and searching for the corresponding product in a database or a file.

The code for this tutorial is available from this link.

Leave a comment

(Your email address will not be published)