This article was published as a part of the Data Science Blogathon.
Computer Vision has opened up a plethora of possibilities, and one of the simplest and most popular day-to-day applications is the use of QR Codes and Bar Code scanners. With Python, you can easily implement a QR code scanner using OpenCV and ZBar.
( Source: https://i.pinimg.com/736x/bb/55/b1/bb55b1a42f4e2cf6e80a0e275ad8b0c8.jpg )
So, what happens when you’re at the supermarket checkout? The cashier scans each item in your basket with a device and then prices are automatically recorded in the system to generate your bill. That device is nothing but a QR / Bar code scanner and that is exactly what we are going to build today!
Before we dive into the code let us have a quick idea about QR Codes and their uses.
QR Code stands for Quick Response Code. It is a matrix type code that is popularly used to keep track of items. QR codes store data in the form of pixels which correspond to binary codes that can be interpreted to reveal the actual data.
This is the basic structure of a QR code.
(Source: https://en.wikipedia.org/wiki/File:QR_Code_Structure_Example_3.svg)
QR Codes find their application in various fields such as:
One of the main advantages of QR codes is that the data can be shared in encrypted form without having to reveal the encoded data explicitly. This acts as an added layer of protection to prevent the misuse of sensitive information.
Bar codes much like QR Codes are also machine-readable encrypted codes but unlike QR codes, the data is encrypted in the form of bars of different spacing and thickness. A QR code is considered to be a 2D bar code as it can store data both horizontally and vertically as opposed to Bar code which usually stores data in the horizontal direction. Thus QR Codes are more powerful than Bar Codes.
Now that we know what QR codes are, let’s get started with our python code.
Importing the Libraries
For our project, we are going to use OpenCV to read images, take video stream input and also display our output. The main libraries that we shall need are the pyzbar and zbar libraries to decode our encrypted QR codes. These are open-source python libraries that help in decoding bar codes and QR codes. We shall also need our NumPy library. We must make the necessary installations.
import numpy as np
from pyzbar.pyzbar import decode
import cv2
First, we shall read the image of a QR Code which is saved in ”qr1.png” with the help of the cv2 library. Then with the help of the decode method from pyzbar let us try to decode our code and analyze the results.
This is the QR code which we shall use as “qr1.png”
( Source: VectorStock.com/26810014 )
#Reading QR Code from an Image
img = cv2.imread("qr1.png")
code = decode(img)
print(code)
Output:
Now, there’s a lot of information being displayed. Let us understand each part of our output.
data -> This field gives us the text or the information encoded in the QR Code
type -> This field tells us the type of code QRCODE or BARCODE
rect -> This gives the left, top, width and the height of the rectangle enclosing the QR image. Even if the QR code is tilted, the rectangle stays upright giving us a bounding rectangle enclosing the entire QR Code
polygon -> This gives us the exact corner points of the polygon around the QR image. If the image of the QR code is tilted, so is the polygon bounding it.
This is why we shall use the coordinates of the polygon to draw our bounding box so that even if the QR code is rotated we get the exact boundary of the code.
Now, a picture might have multiple QR codes. So let us put our code in a for loop so that it can detect all the barcodes in our image. Since we are mainly interested in the encoded information, let us display just the encoded text.
for barcode in decode(img):
print(barcode.data) #in bytes
text = barcode.data.decode('utf-8')
print(text)
print(barcode.rect)
Output
The first line of output shows b’Hello! ‘. The b signifies that it is a bytes literal. It is later decoded using the ‘utf-8’ scheme to obtain just the str text.
Great! Now you have successfully decoded the encoded text from a QR Code.
Now let’s try to do this in real-time using camera feed input. Most real-life applications such as QR code scanners at a supermarket, user authentication or tracking an object would require us to decode a code in real-time. So let’s get started!
The following piece of code shall enable us to turn on the webcam and create a secondary window for the output.
#Scanning QR Code from Camera Feed
vid = cv2.VideoCapture(0)
vid.set(3,640)
vid.set(4,740)
Now, while the video is on, we are going to decode the QR codes in the frame as we did earlier. In addition to that, we shall also use the polygon points to draw the bounding boxes around our QR codes and display their corresponding decoded text on the camera frame input itself.
while True:
success, img = vid.read()
for barcode in decode(img):
text = barcode.data.decode('utf-8')
print(text)
polygon_Points = np.array([barcode.polygon], np.int32)
polygon_Points=polygon_Points.reshape(-1,1,2)
rect_Points= barcode.rect
cv2.polylines(img,[polygon_Points],True,(255,255, 0), 5)
cv2.putText(img, text, (rect_Points[0],rect_Points[1]), cv2.FONT_HERSHEY_DUPLEX, 0.8, (255,255, 0), 2)
cv2.imshow("Video", img)
cv2.waitKey(1)
Output
In the above piece of code the line
cv2.polylines(img,[polygon_Points],True,(255,255, 0), 5)
displays the bounding box around our QR Code. ‘img’ specifies the input frame. Note that here we are using the polygon points so that even if the QR Code is rotated we get the exact bounding box. (255,255,0) specifies the colour of the bounding box and 5 denotes the thickness.
The code line
cv2.putText(img, text, (rect_Points[0],rect_Points[1]), cv2.FONT_HERSHEY_DUPLEX, 0.8, (255,255, 0), 2)
is used to display the decoded text. If you observe carefully, you shall see that here we have used the coordinates of the rectangle instead of the polygon to display the text. The reason for doing this is to ensure that the text is displayed upright irrespective of whether the QR code is rotated or not so that it is easier to read.
This output shall show us the comparative results when the QR Code is upright and when it is held in front of the camera at an angle.
Let’s test it out on some real-world objects and see if it works!
It does! Feel free to test out with as many QR codes as you can find around you!
Another interesting feature is that this library can not only decode QR codes but also decode Bar Codes, without making any changes to our code!
Let’s see the results with a bar code camera feed input.
Voila! You have now built your Bar Code and QR Code Scanner using some simple OpenCV functions and the pyzbar library!
Now for the Fun Part! Buckle Up!
Lets us take a real-life use case scenario.
Each employee of a company gets an ID Card with their corresponding QR codes. Some of the employees working on a special project have been given access to a specific lab whereas it is a restricted zone for others. Each employee must scan their ID cards at the entrance to gain access to the labs.
We already have our QR Code Scanner. Now let us put all that we have learnt so far to use. We are going to build a simple User Authentication System, that checks if a QR Code belongs to authorised personnel and decides whether to grant them access or not.
So let’s get started with the code!
import numpy as np
from pyzbar.pyzbar import decode
import cv2
#Scanning QR Code from Camera Feed
vid = cv2.VideoCapture(0)
vid.set(3,640)
vid.set(4,740)
The libraries have been imported and the video capture is set. Now we must read the text file containing the decoded QR code texts for authorised employees and store them in a list.
This is our text file “Authorised.txt”
with open(‘Authorised.txt’, ‘r’) as file:
auth_list = file.read().strip()
print(auth_list)
Output
For reference, let us run the previous code on our input image to display the decoded text for each QR Code. We shall need this later, to verify whether our model is working correctly or not. Let us have a look at the output that we get.
Output
Now all that we need to do is check for each QR Code if the decoded text is present in the list of Authorised people. If there is a match, then we shall use a Green colour (0,255,0) for our bounding box and display the text “Access Granted” else we shall use a Red colour (0,0, 255) bounding box and display the message “Unauthorised Access”.
while True:
success, img = vid.read()
for barcode in decode(img):
text = barcode.data.decode('utf-8')
text=str(text)
if text not in auth_list:
color=(0,0,255)
displaytext = "Unauthorised Access"
else:
color=(0,255,0)
displaytext = "Access Granted"
polygon_Points = np.array([barcode.polygon], np.int32)
polygon_Points=polygon_Points.reshape(-1,1,2)
rect_Points= barcode.rect
cv2.polylines(img,[polygon_Points],True,color, 3)
cv2.putText(img, displaytext, (rect_Points[0],rect_Points[1]), cv2.FONT_HERSHEY_PLAIN, 0.9, color, 2)
cv2.imshow("Video", img)
cv2.waitKey(1)
Output
Kudos! You did it!
Our model perfectly scans the QR codes and grants access only to the authorised employees! You have successfully built a User Authentication System using the QR Code Scanner using opencv which grants access only to authorised employees once they scan the QR codes on their ID cards!
There are endless fields in which QR Codes can be really useful. So go ahead and have fun experimenting with different codes and their applications!
About Me:
Hey there, I’m Tithi Sreemany. Hope you liked reading this article and found it useful!
You can reach out to me on LinkedIn.
Do check out my other articles here: link.
Thanks for reading!
The media shown in this article is not owned by Analytics Vidhya and are used at the Author’s discretion.
i am facing an issue with multiple detects for single QR code . How can i stop it after detected one time ?