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%:



