noobinmath
noobinmath

Reputation: 185

Python OpenCV QrCode reader

I want to make QR Code reader with using opencv and Python. My hardware is Raspberry Pi 4B and pi camera.

In the code, When I show the QR Code to camera opencv decode the QR. After that I want to send this code with using requests.post to Node.js server. Everything is okay in there but there is a problem. The problem is that As long as the same QR Code stays in front of the camera, it constantly sends post requests with that code.

In the system, people will read the QR Code from their mobile phone and enter the building according to the code. Nodejs sends unlimited requests to the server, as a person sends the QR Code as long as it is held on the screen.

Actually the system should work like this,

The user keeps the QR Code in the camera.

With requests.post, the code is sent to the server.

The server returns a negative or positive response.

The answer appears on the screen.

No action is taken until the next user arrives.

Please give me your opinion on this matter.

How can I stop sending requests until a different user arrives?

How can I control this with a function?

test.py

basic_auth_url= "http://192.168.1.6:3000/test"


def qr_test(code):
    myObj={"code":code}
    response = requests.post(
            url=basic_auth_url,
            data=myObj
            )
            
    print(response.content)




cap = cv2.VideoCapture(0)

detector = cv2.QRCodeDetector()

while True:
    _, img = cap.read()
    data, bbox, _ = detector.detectAndDecode(img)
    
    if(bbox is not None):
        for i in range(len(bbox)):
            cv2.line(img, tuple(bbox[i][0]), tuple(bbox[(i+1) % len(bbox)][0]), color=(255,
                     0, 255), thickness=2)
        cv2.putText(img, data, (int(bbox[0][0][0]), int(bbox[0][0][1]) - 10), cv2.FONT_HERSHEY_SIMPLEX,
                    0.5, (0, 255, 0), 2)
        if data:
        
            code=data
            code1=str(code)
            code=code.split("|")

            code_1=code[1]
            code_1=code_1[0:10]
            qr_test(code_1)
    cv2.imshow("code detector", img)
    if(cv2.waitKey(1) == ord("q")):
        break
cap.release()
cv2.destroyAllWindows()

Upvotes: 1

Views: 923

Answers (2)

Jordan Kalebu
Jordan Kalebu

Reputation: 72

Declare a global variable previous_qrcode as None and then you will be updating it to be the value of the current barcode and if the user tries to call the qr_test() function with a qr-code value similar to the previous_qrcode the function will do nothing.

Hope this will help

#!/usr/bin/python
# -*- coding: utf-8 -*-

# You can do this

basic_auth_url = 'http://192.168.1.6:3000/test'

previous_qrcode = None
def qr_test(code):
    if code != previous_qrcode:
        myObj = {'code': code}
        response = requests.post(url=basic_auth_url, data=myObj)
        print(response.content)
        previous_qrcode = code

Upvotes: -1

furas
furas

Reputation: 142631

As i wrote in comment you can keep last qrcode in variable and compare with new value. If values are the same then don't send request. If new value is different then send request and keep new value to compare it with next values.

Value last_qrcode has to be outside function to be global and keep value between function's executions. And inside function you have to use global to inform function that it has to assign value to external variable

last_code = None   # default value at start

def qr_test(code):
    global last_code

    if code != last_code:
       myObj = {"code": code}
       response = requests.post(
                    url=basic_auth_url,
                    data=myObj
                 )
   
       result = response.content        
       last_code = code

       print(result)

You may also keep all unique values in some list/dictionary - as a cache - to get it from dictionary instead of sending request. Because it will change value inside ndictionary so it doesn't need global

last_code = None   # default value at start
all_codes = {}     # empty dict at start

def qr_test(code):
    global last_code

    if code != last_code:

       if code in all_codes:
           result = all_codes[code]
           print('already seen before')
       else:
           myObj = {"code": code}
           response = requests.post(
                    url=basic_auth_url,
                    data=myObj
                 )
           result = response.content        
           all_codes[code] result

       last_code = code              

       print(result)

You could use standard functools.cache for cache but it would need write it in differnt way and it can't recognize if it was get from cache

import functools

last_code = None   # default value at start

@functools.cache
def check_code(code):
    myObj = {"code": code}
    response = requests.post(
                 url=basic_auth_url,
                 data=myObj
               )

    return response.content

def qr_test(code):
    global last_code

    if code != last_code:
       result = check_code(code)
       last_code = code              

       print(result)

Using @functools.lru_cache(maxsize=10) you could keep in cache only 10 last result.

Upvotes: 2

Related Questions