使用 Queue 使用 opencv 图像源更新 customtkinter CTkImage 后,Python 程序变得无响应

问题描述 投票:0回答:1

我正在尝试使用存储在

CTkImage
中的 customtkinter
CTkLabel
创建实时视频源,代码如下:

self.image_w = customtkinter.CTkImage(
            light_image=Image.open(os.path.join(Constants.RESOURCES_PATH, 'blank_img.jpg')),
            size=(600, 600))
        self.img_label = customtkinter.CTkLabel(self.image_frame, image=self.image_w, text="")
        self.img_label.grid(row=0, column=0, padx=5, pady=10, sticky="")

有一个 QR_Daemon 类,它将使用 OpenCV 读取的图像添加到

Queue.queue

    def main(self):
        # Initialize the camera or read a video file
        itime = time.time()
        cap = cv2.VideoCapture(0)  # Change to the appropriate camera 
                                   # index or video file path
        print(time.time() - itime)

        while True:
            # Read a frame from the camera or video file
            ret, frame = cap.read()

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

            if not ret:
                break
            if not self.img_q.full():
                self.img_q.put(gray_frame)

            # Detect and decode QR codes in the frame
            self.read_qr_code(gray_frame)

            # Wait for 2 seconds before processing the next code
            time.sleep(0.5)

            # Close the displayed window if 'q' key is pressed
            if cv2.waitKey(1) & 0xFF == ord('q'):
                break

我正在使用此代码来更新 customtkinter 图像本身

    def read_cam_img(self):
        time.sleep(25)
        print("done waiting")
        if not self.img_queue.empty():
            self.image_w.configure(light_image=Image.fromarray(self.img_queue.get()))
            self.img_label.configure(image=self.image_w, text="")
            time.sleep(2)

然后他们都被叫进来:

    def launch_qr(self):
        qr_daemon = QRDaemon(member_list=self.member_section, img_q=self.img_queue)
        qr_daemon_thread = threading.Thread(target=qr_daemon.main)
        qr_daemon_thread.daemon = True
        qr_daemon_thread.start()

        img_update_thread = threading.Thread(target=self.read_cam_img())
        img_update_thread.daemon = True
        img_update_thread.start()

根据我读到的内容,似乎

Queue.queue
在 Python 中应该是线程安全的,但是,当我运行实际代码时,我最终得到以下结果: Unresponsive Application

我将

read_cam_img
中的“while”循环更改为
if
语句(因此它只会运行一次),当我这样做时,图像确实出现在 GUI(图像框架)中。这让我相信这是某种时间复杂度问题(也许?)。

然后我将代码更改为如下所示:

self.image_w.configure(light_image=Image.fromarray(self.img_queue.get()))
            self.img_label.configure(image=self.image_w, text="")
            time.sleep(2)
            self.image_w.configure(light_image=Image.fromarray(self.img_queue.get()))
            self.img_label.configure(image=self.image_w, text="")
            time.sleep(2)
            self.image_w.configure(light_image=Image.fromarray(self.img_queue.get()))
            self.img_label.configure(image=self.image_w, text="")
            time.sleep(2)
            self.image_w.configure(light_image=Image.fromarray(self.img_queue.get()))
            self.img_label.configure(image=self.image_w, text="")

而不是 while 循环,当我这样做时,图像仅更新一次(仅显示 GUI 中的第一帧),即使队列中有更多帧。

我还在这里提供了完整程序的链接以供参考:https://github.com/StarkOdinson612/QRAtendanceV2/tree/VideoFeed

python multithreading opencv tkinter video-capture
1个回答
0
投票

代码中的问题似乎仅存在于

img_update_thread
的线程创建中,正如 @tdelaney 在评论中指出的那样。更改为:

img_update_thread = threading.Thread(target=self.read_cam_img)

代码按预期工作,FPS 可以根据需要提高(我现在只是将其设置为 20)

© www.soinside.com 2019 - 2024. All rights reserved.