我试图使用以下代码来创建一个交互式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()
安装第二个回调。设置标志后,更改颜色空间。否则,不要管它。当按钮被点击时,切换标志