我正在尝试使用存储在
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 中应该是线程安全的,但是,当我运行实际代码时,我最终得到以下结果:
我将
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
代码中的问题似乎仅存在于
img_update_thread
的线程创建中,正如 @tdelaney 在评论中指出的那样。更改为:
img_update_thread = threading.Thread(target=self.read_cam_img)
代码按预期工作,FPS 可以根据需要提高(我现在只是将其设置为 20)