Python pyzbar: Detecting and decoding barcode

In this tutorial we will check how to detect and decode a barcode in an image. For this we will be using the pyzbar library.

Introduction

In this tutorial we will check how to detect and decode a barcode in an image. For this we will be using the pyzbar library. We will also be using OpenCV to read the original image.

To easily install the pyzbar library, you can use pip and the following command:

pip install pyzbar

This tutorial was tested with version 3.7.2 of Python.

The code

We will start by importing the cv2 module, so we can read our testing image as a numpy array. We will also import the decode function from the pyzbar module, which we will use to detect and decode the barcode.

import cv2
from pyzbar.pyzbar import decode

After that we are going to read the testing image from the file system. We will do this with a call to the imread function, passing as input a string with the path to the file.

You can use this free online tool to generate a bar code with the content you want. In my case, I’ve created a bar code with the data “TechTutorialsX“. You can check below on figure 1 the barcode used in my tests.

Testing barcode generated with an online tool.
Figure 1 – Testing barcode generated with an online tool.

As output, this function will return the image as a numpy ndarray.

image = cv2.imread('C:/Users/N/Desktop/barcode.png')

Then, to decode the barcode in the image, we simply need to call the decode function we have imported, passing as input the image.

This function returns an array of objects of class Decoded. Each element of the array represents a detected barcode. This means that we can use the library with images with multiple barcodes.

detectedBarcodes = decode(image)

In our case, our image only has one barcode, so it is expected that this array only contains a single element. Nonetheless, for a more robust code, we will iterate through the array with a for in loop, meaning it will work in case one, multiple or no barcodes are found.

for barcode in detectedBarcodes:
     # handling each barcode

One of the attributes we can obtain from our Barcode object is called rect. It contains the bounding box of the polygon to which the barcode corresponds.

For this simple example, we are using an image where the barcode doesn’t have any rotation and thus forms a rectangle. Taking this in consideration, we can use the rect attribute to draw a shape around the barcode.

Nonetheless, for more complex scenarios, the Barcode object also has the polygon attribute, which contains the points that form the polygon around the barcode. You can check here how the rect attribute behaves regarding the polygon, when the barcode is rotated.

Since here we are going to use the rect attribute, we will analyze it. Basically, it is a class that contains the x and y coordinates of the top left corner of the rectangle, and its width and height. We will obtain these as 4 distinct variables.

(x, y, w, h) = barcode.rect

Using these coordinates, we are going to draw the rectangle in the image with a call to the rectangle function from the cv2 module.

cv2.rectangle(image, (x, y), (x + w, y + h), (255, 0, 0), 5)

We will also print the decoded content from the barcode (data attribute) and the type of barcode (type attribute). In the testing image, I’ve used a Code 128 barcode.

print(barcode.data)
print(barcode.type)

The full loop can be seen below.

for barcode in detectedBarcodes:
	
	(x, y, w, h) = barcode.rect
	cv2.rectangle(image, (x, y), (x + w, y + h), (255, 0, 0), 5)
 
	print(barcode.data)
	print(barcode.type)

To finalize, we will display the image, already with the rectangle around the barcode, in a window.

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

The final code can be seen below.

import cv2
from pyzbar.pyzbar import decode


image = cv2.imread('C:/Users/N/Desktop/barcode.png')

detectedBarcodes = decode(image)

for barcode in detectedBarcodes:
	
	(x, y, w, h) = barcode.rect
	cv2.rectangle(image, (x, y), (x + w, y + h), (255, 0, 0), 5)
 
	print(barcode.data)
	print(barcode.type)


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

Testing the code

To test the previous code, simply run it in an environment of your choice. I’ve used IDLE, a Python IDE.

You should obtain a result similar to figure 2. As can be seen, the barcode was detected in the image and the correct data was decoded and printed to the python shell.

Output of the program.
Figure 2 – Output of the program.

References

[1] https://pypi.org/project/pyzbar/

Leave a Reply