This article was first published onSet wisdom column


Computer vision expert Adrian Rosebrock recently shared how to create a practical barcode and QR code scanner using OpenCV and Zbar.

A friend recently asked me if there is any module in OpenCV that can directly recognize barcodes and QR codes. Unfortunately, the answer is no. But OpenCV speeds up the process of reading barcodes and qr codes, including loading images from hard drives, grabbing new frames from video streams, and processing them. Once we have captured the image or video frame, we can pass it into a dedicated barcode decoding library in Python, such as Zbar. Zbar then decodes the bar code or QR code. OpenCV can then perform further image processing and display the results. It sounds complicated, but the whole process is pretty straightforward. The Zbar library also has many variations, of which PyZBar is my favorite.

In this article, I will teach you how to read barcodes and qr codes using OpenCV and Zbar. Also, I’ll show you how to deploy our bar code & QR code scanner to the Raspberry PI!!

Use OpenCV and ZBar to create a barcode and TWO-DIMENSIONAL code scanner

This paper is divided into four parts.

  • In the first part, I’ll show you how to install the Zbar library (Python binding).
  • The Zbar library, along with OpenCV, is used to scan barcodes and qr codes.
  • Once Zbar and OpenCV are configured correctly, I’ll show you how to use them to scan barcodes and qr codes on an image.
  • After identifying and practicing the barcode and QR code on an image, we move on to the next stage: reading the BARCODE and qr code in real time with OpenCV and Zbar.
  • Finally, I’ll show you how to deploy a ready-made real-time QR & bar code scanner to the Raspberry PI.

Install Zbar (with Python binding) for decoding barcodes & QR codes

Some time ago Staya Mallick posted a useful tutorial on how to scan barcodes with Zbar on the LearnOpenCV blog.

The Zbar installation section of this article basically follows the instructions of this blog post, but with a few improvements, mainly around installing the Python Zbar binding section, to ensure that we can:

Use Python3 (official Zbar Python binding only supports Python 2.7) to accurately detect and locate qr codes and barcodes in images

Install the required software in three simple steps.

Step 1: Install Zbar from APT or BREW libraries

Install Zbar on Ubuntu or Raspberry PI

$ sudo apt-get install libzbar0
Copy the code

Install Zbar on your MacOS system

It is also easy to install Zbar on a macOS system using BREW (assuming you already have Homebrew installed) :

$ brew install zbar
Copy the code

Step 2: Create a virtual environment and install OpenCV.

You have two options here: use an existing virtual environment that already has OpenCV installed (skip this step and go to step 3). Or create a new standalone virtual environment and install OpenCV.

Virtual environments are very useful for Python development, and I highly encourage them.

I chose to create a new standalone Python 3 virtual environment, then installed OpenCV and named the environment barcode:

$ mkvirtualenv barcode -p python3
Copy the code

Note: If you already have OpenCV installed, you can skip the OpenCV compilation process by simply putting your Cv2.so binding symlink (SYm-link) into the site-Pakages directory in your new Python virtual environment.

Step 3: Install Pyzbar NOW I have Python 3 installed

The virtual environment, named barcode, then activates the barcode environment and installs PyZBar:

$ workon barcode
$ pip install pyzbar
Copy the code

If you are not using a Python virtual environment, simply:

$ pip install pyzbar
Copy the code

If you want to install Pyzbar on a Python system, make sure you use sudo as well.

Decode bar and QR codes on a single image with OpenCV

Before we can read barcodes and qr codes in real time, we will first create a single image scanner to practice.

Open a new file called barcode_scanner_image.py and insert the following code:

Import the required toolkits
from pyzbar import pyzbar
import argparse
import cv2

Build a parameter parser and parse the parameters
ap = argparse.ArgumentParser()
ap.add_argument("-i"."--image", required=True,
 help="path to input image")
args = vars(ap.parse_args())
Copy the code

In lines 2-4, we import the required toolkits.

You need to install PyZBar and CV2 (OpenCV) as instructed in the previous section. Argparse, however, is included with the Python installation to parse command-line arguments.

We have a required command-line argument (–image) for this script, which is parsed on lines 7-10.

You’ll see at the end of this section how to run the script here when passed a command line parameter containing the path to the input image.

Now we get the input image and run Pyzbar:

Load the input image
image = cv2.imread(args["image"])

# Find the barcode in the image and decode it
barcodes = pyzbar.decode(image)
Copy the code

In line 13, we load the image through its path (contained in our handy args directory).

From here, we call pyzbar.decode to find and decode barcodes in the image (line 16).

We’re not done yet — now we need to parse the information contained in the barcode variable:

# Loop detected bar codes
for barcode in barcodes:
 Extract the position of the boundary box of the bar code
 # Draw the bounding box for the bar code in the image
 (x, y, w, h) = barcode.rect
 cv2.rectangle(image, (x, y), (x + w, y + h), (0, 0, 255), 2)

 # Barcode data is a byte object, so if we want to output images on
 # to draw it, you need to convert it to a string
 barcodeData = barcode.data.decode("utf-8")
 barcodeType = barcode.type

 Draw the barcode data and barcode type on the image
 text = "{} ({})".format(barcodeData, barcodeType) cv2.puttext (image, text, (x, y-10), cv2.font_hershey_simplex, 0.5, (0, 0, 255), 2)Print barcode data and barcode type to terminal
 print("[INFO] Found {} barcode: {}".format(barcodeType, barcodeData))

Display the output image
cv2.imshow("Image", image)
cv2.waitKey(0)
Copy the code

Starting at line 19, we loop through the barcodes detected. In this loop, we continue:

The boundary box (x,y) coordinates are extracted from the barcode-.rect object (line 22), which allows us to locate and determine the current barcode position in the input image.

Draw a bounding box on the image around the detected barcode (line 23).

Decode barcode to utF-8 and extract the barcode type (lines 27 and 28). The decode (” UTF-8 “) function converts an object from a byte array to a string, which is crucial. You can experiment with the results by deleting or adding comments.

Format and draw barcodeData and barcodeType on the image (lines 31-33).

Finally, output the same data and input information to the terminal for debugging (line 36).

Let’s test our OpenCV barcode scanner. From here, open your terminal and execute the following command:

$ python barcode_scanner_image.py --image barcode_example.png
[INFO] Found QRCODE barcode: {"author": "Adrian"."site": "PyImageSearch"}
[INFO] Found QRCODE barcode: https://www.pyimagesearch.com/
[INFO] Found QRCODE barcode: PyImageSearch
[INFO] Found CODE128 barcode: AdrianRosebrock
Copy the code

You can see in the terminal that all 4 barcodes are correctly discovered and decoded!

As shown, barcodes and qr codes in the image are identified, highlighted in red boxes, and the information they contain is displayed.

Read bar codes and qr codes in real time with OpenCV

In the previous section, we learned how to create a Python+OpenCV barcode scanner for a single image.

Our bar code and QR code scanners work fine – but the question is, can we detect and decode bar code + QR code in real time?

Let’s try. Open a new file called barcode_scanner_video.py and insert the following code:

Import the required toolkits
from imutils.video import VideoStream
from pyzbar import pyzbar
import argparse
import datetime
import imutils
import time
import cv2

Create a parameter parser to parse the parameters
ap = argparse.ArgumentParser()
ap.add_argument("-o"."--output".type=str, default="barcodes.csv".help="path to output CSV file containing barcodes")
args = vars(ap.parse_args())
Copy the code

In lines 2-8, we import the required toolkits. Recall from the above explanation that you should recognize PyZbar, Argparse and Cv2. We will use VideoStream to process the captured video frames in an efficient and single-threaded manner. If imutils is not installed on your system, simply use the following command:

$ pip install imutils
Copy the code

We then parse an optional command-line argument –output, which contains the path to the output CSV file. This file will contain the timestamp and payload of the barcode detected and extracted from the video stream. If this parameter is not specified, the CSV file will be replaced with our current working directory named “barcodes.csv” (lines 11-14).

Here we initialize the video stream and open the CSV file:

Initialize the video stream to warm up the camera
print("[INFO] starting video stream...")
# vs = VideoStream(src=0).start()V = VideoStream (usePiCamera = True). The start () time. Sleep (2.0)Open the output CSV file used to write and initialize all barcodes discovered so far
csv = open(args["output"]."w")
found = set(a)Copy the code

In lines 18-19, we initialize and start the video stream. You can either: use your own USB Webcam (uncommented line 18 and comment line 19) or PiCamera (uncommented line 19 and comment line 18) if you are using raspberry PI (like me).

I chose to use my raspberry PI PiCamera, as discussed in the next section.

We then wait a few seconds for the camera to warm up (line 20).

All barcodes and qr codes found will be written to the hard disk as CSV files (make sure not to write twice). This is just one example of recording barcodes, but you can do it to your liking, such as detecting barcodes and reading them as:

  • Save it in an SQL database
  • Send it to the server
  • Upload it to the cloud
  • Send an email or text message

The practice is arbitrary; we’ll just use a CSV file as an example.

We open the CSV file at line 24 to write to hard disk. If you modify the code to add to the file, you can simply change the second parameter from “w” to “A” (but you can only search duplicate files in a different way later).

We also initialize a set for the found bar code. The set will contain a unique bar code to prevent duplication.

We start getting and processing video frames:

# Loop frames from the video stream
while True:
 # Grab frames from a single threaded video stream,
 Resize to a maximum width of 400 pixels
 frame = vs.read()
 frame = imutils.resize(frame, width=400)

 # Find the bar codes in the video and parse all the bar codes
 barcodes = pyzbar.decode(frame)
Copy the code

At line 28, we begin the loop, continuing to grab and resize the frame from the video stream (lines 31 and 32).

Here, we call Pyzbar.decode to detect and decode all barcodes and qr codes in the Frame.

We then loop through the detection of barcodes:

 # Loop detected bar codes
 for barcode in barcodes:
  Extract the boundary box position of the bar code
  # Draw a bounding box around the bar code on the image
  (x, y, w, h) = barcode.rect
  cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)

  # Bar code data is a byte object, so if we want to draw it
  You need to convert it to a string first
  barcodeData = barcode.data.decode("utf-8")
  barcodeType = barcode.type

  Draw the barcode data and type on the image
  text = "{} ({})".format(barcodeData, barcodeType) cv2.putText(frame, text, (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)# If the barcode text is not currently in the CSV file, write
  To disk and update the set
  if barcodeData not in found:
   csv.write("{},{}\n".format(datetime.datetime.now(),
    barcodeData))
   csv.flush()
   found.add(barcodeData)
Copy the code

If you look at the loop section earlier, you’ll see that this loop is very similar to the previous one.

In fact, lines 38-52 are the same script that identified the individual images above. For a detailed explanation of this code, see the single image barcode Detection and Scanning section.

Lines 56-60 are relatively new. In these lines, we check to see if we found a unique (previously unfound) bar code (line 56).

If this is the case, we write the timestamp and data as CSV files (lines 57-59). You can also add barcodeData to a found set as an easy way to handle duplicate files.

In the remaining lines of the live barcode scan script, we show the video frame, check to see if the exit key is pressed, and clear:

 Display the output frame
 cv2.imshow("Barcode Scanner", frame)
 key = cv2.waitKey(1) & 0xFF

 # Stop the loop if you press the "Q" key
 if key == ord("q") :break

# Close output CSV file for cleanup
print("[INFO] cleaning up...")
csv.close()
cv2.destroyAllWindows()
vs.stop()
Copy the code

In line 63, we show the output frame.

Then on lines 64-68, we check to see if “q” is pressed to execute the main loop.

Finally, we perform cleanup on lines 72-74.

Deploy bar code and QR scanner on raspberry PI

I decided to build my own real-time barcode scanner using raspberry PI, a touch screen and a power bank.

The picture below shows my assembly. If you want to make one yourself, here are the components you need:

  • Raspberry PI 3 (you can also use the latest 3 B+)
  • Raspberry PI camera module
  • Pi Foundation 7-inch touchscreen
  • RAVPower 22000mAh Charger

It’s very easy to put together.

Here, open the terminal on your Raspberry PI and launch the app with the following command (this step requires a keyboard/mouse, but not later) :

$ python barcode_scanner_video.py
[INFO] starting video stream...
Copy the code

Once everything is ready, you can show the barcode to the camera by opening the barcode. CSV file (or if you prefer, you can run tail -f barcodes.csv on another terminal to see the data when the CSV file is opened).

I first showed the camera a QR code on a black background, which Zbar easily detected:

Then I found another QR code in my kitchen using the device:

Success! And can multi-angle scan recognition two-dimensional code.

Now, let’s try a QR code that contains jSON-BLOb data:

Finally, I tried the traditional 1-dimensional bar code:

A 1-dimensional bar code is a bit more difficult for our system because the camera doesn’t support autofocus. But the bar code was successfully detected and decoded.

It’s much better if you use a USB webcam with autofocus.

conclusion

In this article, we discussed how to build a bar code and QR code scanner using OpenCV and the Python library Zbar.

After installing Zbar and OpenCV, we created two Python scripts:

  • The first is used to scan bar and qr codes on a single image.
  • The second is used to read barcodes and qr codes in real time. In both cases, we used OpenCV to speed things up.

Eventually, we deployed the program to raspberry PI and successfully recognized barcodes and QR codes in real time.

You can try to do a bar code & TWO-DIMENSIONAL code scanner, project source code download

References:www.pyimagesearch.com


0806 ai – From Scratch to Master – on sale for a limited time!

Click here for details

What about online programming?

(The first 25 students can also get ¥200 coupon)