简体   繁体   English

如何在python的GUI TKinter中从同一ImageLabel的另一个进程调用中替换正在进行的图像捕获进程

[英]how to replace an ongoing process of image capture from another process call over the same ImageLabel in python's GUI TKinter

i am trying to use the following code to create an interactive GUI which changes the color-space(HSV, RBG, grayscale etc) on the event of button click. 我试图使用以下代码创建一个交互式GUI,以在单击按钮时更改颜色空间(HSV,RBG,灰度等)。 Display an OpenCV video in tkinter using multiprocessing Being new to python i am having problems with multiprocessing and my attempts on making the GUI which would change it's color space on button clicks hangs the entire system. 使用多重处理在tkinter中显示OpenCV视频对python来说是新手,我遇到了多重处理问题,我试图制作可改变按钮颜色空间的GUI挂在整个系统上。 Any help on it's implementation will be highly appreciated. 对其实施的任何帮助将不胜感激。 Thankyou. 谢谢。 Below is my code: 下面是我的代码:

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()

Add some logging to the code to see which parts are executed when. 在代码中添加一些日志记录,以查看何时执行哪些部分。 Multithreaded code is always hard to debug (because things happen while the debugger waits for you). 多线程代码始终难以调试(因为调试器在等待您时会发生事情)。 Logging will give you a report of what happened when and that will allow you to track down unexpected behavior.$ 日志记录将为您提供有关何时何地发生的情况的报告,这将使您能够跟踪意外行为。

In this case, I see two problems: 在这种情况下,我看到两个问题:

except: continue

will silently ignore any problems in the frame capture loop. 将默默地忽略帧捕获循环中的任何问题。 So if something goes wrong, no image will be pushed to the queue. 因此,如果出现问题,则不会将任何图像推入队列。 But that should cause queue.get() to throw an Empty exception. 但这应该导致queue.get()抛出Empty异常。

The second problem is that you install update_all() twice. 第二个问题是您安装两次update_all() So you will have one process/loop which adds one image per N milliseconds to the queue but two callbacks in the main event loop that try to get an image. 因此,您将拥有一个进程/循环,该进程/循环每N毫秒将一幅图像添加到队列中,但是在主事件循环中有两个试图获取图像的回调。 That could cause Python to lock up. 这可能会导致Python锁定。

Again, use logging to see when processes are started, when images are put into the queue and taken from it and how many callbacks are registered to process images in the queue. 同样,使用日志记录来查看何时启动进程,何时将图像放入队列并从中获取图像,以及注册了多少回调以处理队列中的图像。

[EDIT] If the original code works, then use a different approach: [编辑]如果原始代码有效,则使用其他方法:

Instead of installing a second callback with after() set a flag. 而不是使用after()安装第二个回调,而是设置一个标志。 When the flag is set, change the colorspace. 设置标志后,更改色彩空间。 Otherwise, leave it alone. 否则,别管它。 When the button is clicked, toggle the flag. 单击按钮后,切换标志。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Python多处理和tkinter - 如何连接这个过程(GUI和衍生过程)? - Python multiprocessing and tkinter - how to connect this process (GUI and spawned process)? 如何在Python中读取正在进行的进程的stdout输出? - How to read stdout output of ongoing process in Python? 如何在python中生成另一个进程并捕获输出? - How to spawn another process and capture output in python? 如何将python多处理过程输出发送到Tkinter gui - How can I send python multiprocessing Process output to a Tkinter gui 在Python中调用另一个进程的方法 - Call another process's method in Python 使用 Python,如何从另一个 GUI 调用 tkinter GUI? - Using Python, how do you call a tkinter GUI from another GUI? 如何从Python多进程处理过程中捕获stderr - How to capture stderr from Python mulitprocessing process 如何从Python的连续过程中捕获输出? - How to capture output from continuous process in Python? 如何重新连接到GoogleColab上正在进行的流程 - How to reconnect to the ongoing process on GoogleColab 如何运行 python 脚本,其中 tkinter GUI 在同一个文件中? 您如何处理用户输入? - How do you run a python script where the tkinter GUI is in the same file? How do you process user entries?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM