QR Code Scanner using Raspberry Pi and OpenCV

Published  May 14, 2020   1
QR Code Scanner using Raspberry Pi and OpenCV

QR code (Quick Response code) is a type of matrix barcode that contains information about the item to which it is attached, like location data, identifier, or a tracker that identifies a website or app, etc. It is a machine-readable optical label that is in the form of a 2D image and has a different pattern. To learn more about QR codes and how to generate a QR code, follow our previous tutorial. Also if you want to learn how to interface USB Barcode Scanner with Raspberry Pi and read 2D barcodes with Raspberry pi, then follow this tutorial.

In this tutorial, we are going to build a Raspberry Pi based QR Code Scanner using OpenCV and ZBar library. ZBar is the best library for detecting and decoding the different types of barcodes and QR codes. OpenCV is used to grab a new frame from a video stream, and process it. Once OpenCV captures a frame, then we can pass it to a dedicated Python barcode decoding library such as a ZBar which decodes the bar code and converts it into respective information.

Requirements

  • Raspberry Pi 3 (any version)
  • Pi Camera Module

Before proceeding with this Raspberry Pi 3 QR code scanner, first, we need to install OpenCV, Barcode decoding library ZBar, imutils, and some other dependencies in this project. OpenCV is used here for digital image processing. The most common applications of Digital Image Processing are object detectionFace Recognition, and people counter.

Installing OpenCV in Raspberry Pi

Here OpenCV library will be used for the Raspberry Pi QR scanner. To install the OpenCV, first, update the Raspberry Pi.

sudo apt-get update

Then install the required dependencies for installing OpenCV on your Raspberry Pi.

sudo apt-get install libhdf5-dev -y 
sudo apt-get install libhdf5-serial-dev –y 
sudo apt-get install libatlas-base-dev –y 
sudo apt-get install libjasper-dev -y 
sudo apt-get install libqtgui4 –y
sudo apt-get install libqt4-test –y

After that, install the OpenCV in Raspberry Pi using the below command.

pip3 install opencv-contrib-python==4.1.0.25

We previously used OpenCV with Raspberry pi and created a lot of tutorials on it.

We have also created a series of OpenCV tutorials starting from the beginner level.

Installing other Required Packages

Installing ZBar 

Zbar is the best library for detecting and decoding the different types of barcodes and QR codes. Use the below command to install the library:

pip3 install pyzbar

Installing imutils 

imutils is used to make essential image processing functions such as translation, rotation, resizing, skeletonization, and displaying Matplotlib images easier with OpenCV. Use the below command to install the imutils:

pip3 install imutils

Installing argparse 

Use the below command to install the argparse library. argparse is responsible for parsing command-line arguments.

pip3 install argparse

Raspberry pi QR Code Reader ​Hardware Setup

Here we only require Raspberry Pi and Pi camera for this QR code scanner using Raspberry Pi Camera and you just need to attach the camera ribbon connector in the camera slot given in the Raspberry pi

OpenCV Human Counting Project

Pi camera can be used to build various interesting projects like Raspberry Pi Surveillance Camera, Visitor Monitoring System, Home Security System, etc.

Python code for Raspberry Pi QR Code Reader

The complete code for Raspberry Pi QR reader is given at the end of the page. Before we program the Raspberry Pi, let's understand the code.

So, as usual, start the code by importing all the required packages.

from imutils.video import VideoStream
from pyzbar import pyzbar
import argparse
import datetime
import imutils
import time
import cv2​

Then construct the argument parser and parse the arguments. The Command-line argument contains information about the path of the CSV file. The CSV (Comma Separated Values) file contains the timestamp and payload of every barcode from our video stream.

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())

After that, initialize the video stream and uncomment the commented line if you are using USB webcam.

#vs = VideoStream(src=0).start()
vs = VideoStream(usePiCamera=True).start()
time.sleep(2.0)

Now inside the loop, grab a frame from the video stream and resize it to 400 pixels. Once it grabs the frame, call the pyzbar.decode function to detect and decode the QR code.

frame = vs.read()
frame = imutils.resize(frame, width=400)
barcodes = pyzbar.decode(frame)

Now, loop over the detected barcodes to extract the location of the barcode and draw the bounding box around the barcode on the image.

for barcode in barcodes:
        (x, y, w, h) = barcode.rect
        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)

QR Code

Then decode the detected barcode into an "utf-8" string using the decode ("utf-8") function and then extract the type of barcode using the barcode.type function.

barcodeData = barcode.data.decode("utf-8")
barcodeType = barcode.type

After that, save the extracted barcode data and barcode type inside a variable named text, and 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)

Raspberry Pi Extracted Barcode Data

Now display the output with the barcode data and the barcode type.

cv2.imshow("Barcode Reader", frame)

Barcode Scanner

Now in the last step, check if the key ‘s’ is pressed, then break out the main loop and start the clean-up process.

key = cv2.waitKey(1) & 0xFF
# if the `s` key is pressed, break from the loop
if key == ord("s"):
        break
print("[INFO] cleaning up...")
csv.close()
cv2.destroyAllWindows()
vs.stop()

Testing the Raspberry Pi QR Code Scanner

Once your setup is ready, launch the QR code reader program. You will see a window showing a live view from your camera, now you can present barcodes in front of the PI camera. When pi decodes a barcode, it will draw a red box around it with barcode data and barcode type as shown in below image:

Barcode Output

This is how you can easily build a Raspberry Pi Camera QR Code Reader with just using the Raspberry Pi board and Pi camera or USB camera.

A working video and complete code for this project are given below.

Code
from imutils.video import VideoStream
from pyzbar import pyzbar
import argparse
import datetime
import imutils
import time
import cv2

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())
#vs = VideoStream(src=0).start()  #Uncomment this if you are using Webcam
vs = VideoStream(usePiCamera=True).start() # For Pi Camera
time.sleep(2.0)
csv = open(args["output"], "w")
found = set()

while True:
frame = vs.read()
frame = imutils.resize(frame, width=400)
barcodes = pyzbar.decode(frame)
for barcode in barcodes:
(x, y, w, h) = barcode.rect
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)
barcodeData = barcode.data.decode("utf-8")
barcodeType = barcode.type
text = "{} ({})".format(barcodeData, barcodeType)
        print (text)
cv2.putText(frame, text, (x, y - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)

# if the barcode text is currently not in our CSV file, write
# the timestamp + barcode to disk and update the set
if barcodeData not in found:
csv.write("{},{}\n".format(datetime.datetime.now(),
barcodeData))
csv.flush()
found.add(barcodeData)
cv2.imshow("Barcode Reader", frame)
key = cv2.waitKey(1) & 0xFF

# if the `s` key is pressed, break from the loop
if key == ord("s"):
break
print("[INFO] cleaning up...")
csv.close()
cv2.destroyAllWindows()
vs.stop()
Video

Have any question realated to this Article?

Ask Our Community Members

Comments

Hello,

 

Thank you for the installation steps.

I followed all the steps but i still run into an error when running the code.

 

Can you maybe help me solve the problem? I think is has something to do with the space, tabs in the code?