用户界面 - 如何在python的GUI TKinter中通过同一ImageLabel替换另一个进程调用的正在进行的图像捕获过程



我试图使用以下代码来创建一个交互式GUI,改变颜色空间(HSV, RBG,灰度等)在按钮点击的事件。使用多处理在tkinter中显示OpenCV视频作为新的python,我有多处理的问题,我试图使GUI改变它的颜色空间上的按钮点击挂起整个系统。对它的实施任何帮助将非常感激。谢谢。下面是我的代码:

import cv2
from PIL import Image,ImageTk
import Tkinter as tk
import numpy as np
from multiprocessing import Process , Queue
def quit_it(root,process):
    root.destroy()
    process.terminate()
def black_andwhite(root,process):
    process.terminate
    p=Process(target=capture_image, args=(5,queue, ))
    p.start()
    root.after(0, func=lambda: update_all(root, image_label, queue))
def update_image(image_label, queue):
    frame = queue.get()
    a = Image.fromarray(frame)
    b = ImageTk.PhotoImage(image=a)
    image_label.configure(image=b)
    image_label._image_cache = b
    root.update()
def update_all(root, image_label, queue):
    update_image(image_label, queue)
    root.after(0, func=lambda: update_all(root, image_label, queue))
def capture_image(var,queue):
    vidFile = cv2.VideoCapture(0)
    while True:
       try:
          flag, frame=vidFile.read()
          if flag==0:
             break
          if(var==5):
             frame1=cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
          else:
             frame1=cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
          queue.put(frame1)
          cv2.waitKey(20)
       except:
          continue

if __name__ == '__main__':
    queue=Queue();
    root=tk.Tk()
    root.geometry("1500x1200+2+2")
    image_label=tk.Label(master=root)
    image_label.pack()
    p=Process(target=capture_image, args=(7,queue, ))
    p.start()
    quit_button=tk.Button(master=root, text='Quit', command=lambda:quit_it(root,p))
    quit_button.pack()
    bandw_button=tk.Button(master=root, text='black_and_white',command=lambda:black_andwhite(root,p))
    bandw_button.pack()
    root.after(5, func=lambda: update_all(root, image_label, queue,))
    root.mainloop()
    p.terminate()

在代码中添加一些日志记录,以查看哪些部分在何时执行。多线程代码总是很难调试(因为在调试器等待您的时候会发生一些事情)。日志记录会给你一份报告,告诉你什么时候发生了什么,这将允许你追踪意外的行为。$

在这个例子中,我看到了两个问题:

except: continue

将静默地忽略帧捕获循环中的任何问题。因此,如果出现问题,不会将任何图像推送到队列中。但是这会导致queue.get()抛出Empty异常。

第二个问题是您安装了两次update_all()。所以你将有一个进程/循环,它每N毫秒向队列添加一张图像,但在主事件循环中有两个回调,它们试图获取一张图像。这可能会导致Python锁定。

同样,使用日志记录来查看进程何时启动,何时将图像放入队列并从队列中取出,以及注册了多少回调来处理队列中的图像。

[EDIT]如果原始代码可以工作,那么使用不同的方法:

设置一个标志,而不是用after()安装第二个回调。设置标志后,更改颜色空间。否则,不要管它。当按钮被点击时,切换标志

相关内容

  • 没有找到相关文章

最新更新