Friday, 15 June 2018

Detecting and tracking QR codes in Python

QR or Quick Response codes have become ubiquitous. I figured that some of might be looking to use them in your applications so I decided to write this tutorial which will cover QR code detection, some plotting and tracking and a neat way to build a GUI using Tkinter.

What you will need for this tutorial (I am assuming that you are on a Linux based installation) :

1. Python installation : Python 2.7.x onwards.
 
    sudo apt-get install python

2. Open_CV , pyzbar , Tkinter:
 

     sudo apt-get install libzbar0
     sudo pip install opencv-python
     sudo pip install pyzbar
     sudo apt-get install python-tkinter


Now you are all set to write some code on python which will detect QR codes and Display their values and draw their paths on screen.


I will explain it section wise below :

# First importing the packages in your python Code.

import pyzbar.pyzbar as pyzbar
import numpy as np
import cv2
import Tkinter as tk
import math


#Global Variables
 track_points=[ ]      #All stored points of positions of QR_Codes.

#Creating a Quit Button Using Tkinter
   root=tk.Tk()
frame=tk.Frame(root)
frame.pack()
button=tk.Button(frame,text="Destroy",command=destroy)
button.pack(side=tk.LEFT)
 

#Initializing Your WebCam for video Capture Using OpenCv


cap = cv2.VideoCapture('0')
 

 #A loop that will keep running and processing each frame captured
while(True):
    #Updates the Tkinter GUI
    root.update()


    ret, frame = cap.read()

    # Our operations on the frame come here    

    im = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    #All Detected QR_codes are stored as decoded Objects   

    decodedObjects= decode(im)
    

     
    #If there are Detected Codes, Computations are performed
    if (len(decodedObjects)>0):           
        compute(im,decodedObjects)
        
    

    cv2.imshow("Results", im)   
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# When everything done, release the capture
button.destroy()
cap.release()
cv2.destroyAllWindows()




I will Now describe the compute and track_object user Functions used Above. Keep in mind that the Decoded Objects has two attributes of use :

1. .polygon : All corner point of the detected QR_code
2. .data :       Data encoded by the QR_Code

def decode(im) :
  # Find barcodes and QR codes
  decodedObjects = pyzbar.decode(im)

  # Print results
  #for obj in decodedObjects:
    #print('Type : ', obj.type)
    #print('Data : ', obj.data,'\n')
    
  return decodedObjects


This Function will compute the centre of each QR Code, using mean of points in the polygon attribute. It will then put the data of the QR code at its centre
 
def compute(im, decodedObjects):
  # Loop over all decoded objects
  for decodedObject in decodedObjects:
        points = decodedObject.polygon
         

         centre=find_centre(points)   
        #print ("Object:", points,'\n')       
        #print ("Centre:", centre, '\n')
    cv2.circle(im,centre,10,(0,0,255),-1)
    cv2.putText(im,decodedObject.data,centre,cv2.FONT_HERSHEY_SIMPLEX, 1, 255)

        if centre in track_points:
                    #Do Something
        else:
             track_points.append(centre)

    for point in track_points:
            cv2.circle(im,point,3,(0,0,255),-1)


This Function Computes the centre of the QR_Code and returns it
 
def find_centre(points):
     x_mean=0
     y_mean=0       
     for point in points:
            x,y=point
            x_mean+=x
            y_mean+=y
     #calculate mean of points
     return (x_mean/len(points) , y_mean/len(points))





Finally the destroy function, which will close all windows and release the camera


def destroy():
        button.destroy()
        cap.release()
        cv2.destroyAllWindows()   
    button1.destroy()









Hope You have Fun Extending this code and build exciting things with it.

       

No comments:

Post a Comment