OpenCV crash on OS X when reading USB cam in separate process
Question: I'm running OpenCV 2.4.5 via the cv2 python bindings, using OS X (10.8.4). I'm
trying to capture images from a USB webcam in a separate process via the
multiprocessing module. Everything seems to work if I use my laptop's (2011
macbook air) internal webcam, but when I attempt to read from a usb webcam
(Logitech C920), I get a crash (no crash when I use the USB cam without the
multiprocessing encapsulation). The crash log is
[here](https://gist.github.com/mike-lawrence/6306597). Code I'm using that
will reliably reproduce the crash is below. Getting this working is pretty
mission-critical for me, so any help would be greatly appreciated!

    
    
    import multiprocessing
    import cv2 #doesn't matter if you import here or in cam()
    
    def cam():
        vc = cv2.VideoCapture(0) #modify 0/1 to toggle between USB and internal camera
        while True:
            junk,image = vc.read()
    
    camProcess = multiprocessing.Process( target=cam )
    camProcess.start()
    
    while True:
        pass
    


Answer: Your problem stems from the way python spans its subprocess using os.fork. The
OpenCV video backend on Mac uses QTKit which uses CoreFoundation these parts
of MacOS are not save to run in a forked subprocess, sometimes they just
complain, sometimes they crash.

You need to create the subprocess without using os.fork. This can be achieved
with python 2.7.

You need to use billiard
(<https://github.com/celery/billiard/tree/master/billiard>) It serves as a
replacement for pythons multiprocessing and has some very useful improvements.

    
    
    from billiard import Process, forking_enable
    import cv2 #does matter where this happens when you don't use fork
    
    def cam():
        vc = cv2.VideoCapture(0) #modify 0/1 to toggle between USB and internal camera
        while True:
            junk,image = vc.read()
    
    forking_enable(0) # Is all you need!
    camProcess = Process( target=cam )
    camProcess.start()
    
    while True:
        pass
    

alright, lets add a more complete example:

    
    
    from billiard import Process, forking_enable
    
    def cam(cam_id):
        import cv2 #doesn't matter if you import here or in cam()
        vc = cv2.VideoCapture(cam_id) #modify 0/1 to toggle between USB and internal camera
        while True:
            junk,image = vc.read()
            cv2.imshow("test",image)
            k = cv2.waitKey(33)
            if k==27:    # Esc key to stop
                break
    
    def start():
    
        forking_enable(0) # Is all you need!
        camProcess = Process(target=cam, args=(0,))
        camProcess.start()
    
    
    if __name__ == '__main__':
        start()
        cam(1)
    

You need two cameras attached for this:It should open a window and run each
camera in a separate process (one on the main process one in a spawned one). I
use this strategy to stream images form multiple cameras at once each in its
own python process.

