I’m creating a python script that scans QR codes, and then processes the info in the code. The python-script will launch every few seconds via a timer in systemd on RBPI, but while scanning for a code – if no code has been detected in 5 seconds, the script should terminate. However, if a code is detected, the processing should keep running, and the script should only exit when the processing is done.
This is my code:
import cv2 import numpy as np from pyzbar.pyzbar import decode from multiprocessing import Process import time def decoder(image): gray_img = cv2.cvtColor(image,0) barcode = decode(gray_img) for obj in barcode: points = obj.polygon (x,y,w,h) = obj.rect pts = np.array(points, np.int32) pts = pts.reshape((-1, 1, 2)) barcodeData = obj.data.decode("utf-8") barcodeType = obj.type string = str(barcodeData) cv2.destroyAllWindows() # stop timeout on action_process and keep it running # processMyQRCode(barcodeData) Demo: i = 0 while i < 10: print("processing code for " + str(i) + " seconds") i += 1 time.sleep(1) print(string + " is processed") exit() def open_scanner(): #add cv2.CAP_DSHOW on windows while developing, remove on RBPI cap = cv2.VideoCapture(0 , cv2.CAP_DSHOW) while True: ret, frame = cap.read() decoder(frame) cv2.imshow('My Title', frame) code = cv2.waitKey(1) if code == ord('q'): exit() if __name__ == '__main__': action_process = Process(target=open_scanner) action_process.start() action_process.join(timeout=5) action_process.terminate()
So when no code is detected, the timeout of 5 should be ok, but should be ignored while running the while-loop inside decoder(image)
Advertisement
Answer
After searching on this for the day, and with Yves’ comment on the question, I came to the conclusion that I was working the wrong way around. So now I added a global Timer, which get canceled if the processing of the QR code gets started.
Now my code looks like this, and it seems to work. Would love to hear it if there is a better way, or if this use of globals is bad practise.
import cv2 import numpy as np from pyzbar.pyzbar import decode import time from threading import Timer import os def decoder(image): gray_img = cv2.cvtColor(image,0) barcode = decode(gray_img) for obj in barcode: points = obj.polygon (x,y,w,h) = obj.rect pts = np.array(points, np.int32) pts = pts.reshape((-1, 1, 2)) barcodeData = obj.data.decode("utf-8") barcodeType = obj.type process_code(barcodeData) def process_code(barcodeData): print("cancel timer") myTimer.cancel() i = 0 while i < 10: print("processing code for " + str(i) + " seconds") i += 1 time.sleep(1) print(str(barcodeData) + " is processed") os._exit(0)() def time_out_exit() : print("No QR Code Found") os._exit(0)() def open_scanner(): myTimer.start() #add cv2.CAP_DSHOW on windows while developing, remove on RBPI cap = cv2.VideoCapture(0 , cv2.CAP_DSHOW) #cap = cv2.VideoCapture(0) while True: ret, frame = cap.read() decoder(frame) #cv2.imshow('My Title', frame) code = cv2.waitKey(1) if code == ord('q'): exit() globals()['myTimer'] = Timer(10.0, time_out_exit) if __name__ == '__main__': open_scanner()