Warning: It's ugly due to a Tkinter/multiprocessing bug in Linux/Mac.
http://bugs.python.org/issue5527#msg195480
import cv2
import multiprocessing
def cam_loop(the_q, event):
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()
if __name__ == '__main__':
try:
logger = multiprocessing.log_to_stderr()
logger.setLevel(multiprocessing.SUBDEBUG)
the_q = multiprocessing.Queue(1)
event = multiprocessing.Event()
cam_process = multiprocessing.Process(target=cam_loop,args=(the_q, event))
cam_process.start()
# Bug in Tkinter, must be imported after processes are forked:
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.bind('', lambda e: self.quit())
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()
def gui_mainloop(the_q, event):
gui = TkGui()
while True:
event.wait()
img = the_q.get()
gui.update_frame(img)
gui_mainloop(the_q, event)
cam_process.join()
except KeyboardInterrupt:
cam_process.terminate()
The idea is to have a camera-capture process running in parallel to the gui one.
So, the "cam_loop" method is transformed into a separate process (#27), images are captured from the webcam in a loop, a bit of make-up for them(#13-14), puts one of them into a queue, and sends a signal to the event saying: hey! there is something here.
At the same time, the main process has been importing the gui, creates a simple Tkinter root, enters in a hand made "mainloop", and awaits for the signal from the cam_process(#53). Once it receives it, tells the gui to update, so it shows the new image received.
The events are not really needed, but they seem to be a nice way of not wasting cycles in the gui loop, that is, only refresh when there is a frame waiting.
Goods news is that CPU usage is less than previous tests, around 55-60%:



