This is the module called 'proc_capturer.py' with OpenCV code, capturing frames from the webcam and putting them in the queue.
def cam_loop(the_q, event): import cv2 width, height = 800, 600 cap = cv2.VideoCapture(0) cap.set(cv2.CAP_PROP_FRAME_WIDTH, width) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height) while True: _ , img = cap.read() if img is not None: img = cv2.flip(img, 1) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGBA) the_q.put(img) event.set()
And the Tkinter's module 'proc_tk_gui.py', starting the gui, receiving the frames from the queue and processing them in a hand-made 'mainloop':
def gui_mainloop(the_q, event): import Tkinter as tk from PIL import Image, ImageTk class TkGui(tk.Tk): def __init__(self): tk.Tk.__init__(self, None) self.parent = None self.lmain = tk.Label(self) self.lmain.pack() def update_frame(self, img): img = Image.fromarray(img) imgtk = ImageTk.PhotoImage(image=img) self.lmain.imgtk = imgtk self.lmain.configure(image=imgtk) self.update() gui = TkGui() while True: event.wait() img = the_q.get() gui.update_frame(img)
Finally, your 'multiprocess-orchestrator' module:
import multiprocessing from proc_tk_gui import gui_mainloop from proc_capturer import cam_loop if __name__ == '__main__': logger = multiprocessing.log_to_stderr() logger.setLevel(multiprocessing.SUBDEBUG) q_frames_captured = multiprocessing.Queue(1) e_frame_captured = multiprocessing.Event() p_cap = multiprocessing.Process(target=cam_loop,args=(q_frames_captured, e_frame_captured)) p_gui = multiprocessing.Process(target=gui_mainloop,args=(q_frames_captured, e_frame_captured)) try: p_cap.start() p_gui.start() p_cap.join() p_gui.join() except KeyboardInterrupt: p_cap.terminate() p_gui.terminate()
I like the idea of having a master module with the multiprocessing logic, and two independent parallel processes only linked with queues and event handlers.
This could develop into a more finite-state machine approach for my project, behave.
Thanks for this good inspiration:
http://www.briansimulator.org/docs/examples-multiprocessing_multiple_runs_with_gui.html
Edit:
It seems from comments in forums that doing your own update loop for tkinter is not really a good thing. The problem is that even though you can force Tkinter to "refresh the window", when it comes to handle events like mouse or button clicking without the mainloop(): you-are-fried. So, mainloop version of 'proc_tk_gui.py' using my dreaded "tkinter after method":
def gui_mainloop(the_q, event): import Tkinter as tk from PIL import Image, ImageTk class TkGui(tk.Tk): def __init__(self): tk.Tk.__init__(self, None) self.parent = None self.lmain = tk.Label(self) self.lmain.pack() def update_frame(self, the_q, the_e): img = the_q.get() img = Image.fromarray(img) imgtk = ImageTk.PhotoImage(image=img) self.lmain.imgtk = imgtk # remember you need to anchor the image!!! self.lmain.configure(image=imgtk) self.lmain.after(10, self.update_frame, the_q, the_e) gui = TkGui() gui.update_frame(img, event) gui.mainloop()
No comments:
Post a Comment