python - 如何在 python GUI TKinter 中通过相同图像标签的另一个进程调用替换正在进行的图像捕获过程

标签 python user-interface opencv tkinter multiprocessing

我正在尝试使用以下代码创建一个交互式 GUI,它会在单击按钮时更改颜色空间(HSV、RBG、灰度等)。
Display an OpenCV video in tkinter using multiprocessing
作为 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异常(exception)。

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

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

[编辑] 如果原始代码有效,则使用不同的方法:

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

关于python - 如何在 python GUI TKinter 中通过相同图像标签的另一个进程调用替换正在进行的图像捕获过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31386251/

相关文章:

python - 如何使用 setup.cfg 设置 Python 包配置文件

java - 从事件监听器开始

python - OpenCV 3 VideoWriter 插入额外的帧

opencv - 'CV_LOAD_IMAGE_UNCHANGED' : undeclared identifier

python - Python 内部 hash() 函数的复杂性

android - 在 C++ 应用程序中使用 TensorFlow 模型

user-interface - 如何在 Julia 中制作 GUI?

opencv - 在 Mac OS X Lion : symbol(s) not found for architecture x86_64 中链接 OpenCV 2.3 程序

python - Pandas DataFrame 自动将错误值作为索引

python - 在 Jython 中使用 JavaCV