未检测到代码时退出 Python QR 扫描器,但在处理代码时保持 运行

Quit Python QR Scanner when no code is detected but keep running while processing the code

我正在创建一个 python 脚本来扫描二维码,然后处理代码中的信息。 python-脚本将通过 RBPI 上 systemd 中的计时器每隔几秒启动一次,但在扫描代码时 - 如果 5 秒内未检测到任何代码,则脚本应终止。但是,如果检测到代码,则处理应保持 运行,并且脚本应仅在处理完成后退出。

这是我的代码:

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

所以当没有检测到代码时,5 的超时应该是可以的,但是应该忽略 while 运行 while-loop inside decoder(image)

在搜索了一天之后,以及 Yves 对这个问题的评论,我得出的结论是我的工作方式是错误的。所以现在我添加了一个全局计时器,如果开始处理 QR 码,它会被取消。

现在我的代码看起来像这样,而且似乎可以工作。如果有更好的方法,或者这种使用全局变量的做法是不好的做法,我很想听听。

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