How do you capture video from two or more cameras at once (or nearly) with OpenCV, using the Python API?
I have three webcams, all capable of video streaming, located at /dev/video0, /dev/video1, and /dev/video2.
Using the tutorial as an example, capturing images from a single camera is simply:
import cv2 cap0 = cv2.VideoCapture(0) ret0, frame0 = cap0.read() cv2.imshow('frame', frame0) cv2.waitKey()
And this works fine.
However, if I try to initialize a second camera, attempting to read()
from it returns None:
import cv2 cap0 = cv2.VideoCapture(0) cap1 = cv2.VideoCapture(1) ret0, frame0 = cap0.read() assert ret0 # succeeds ret1, frame1 = cap1.read() assert ret1 # fails?!
Just to ensure I wasn't accidentally giving OpenCV a bad camera index, I tested each camera index individually and they all work by themselves. e.g.
import cv2 #cap0 = cv2.VideoCapture(0) cap1 = cv2.VideoCapture(1) #ret0, frame0 = cap0.read() #assert ret0 ret1, frame1 = cap1.read() assert ret1 # now it works?!
What am I doing wrong?
Edit: My hardware is a Macbook Pro running Ubuntu. Researching the issue specifically on Macbooks, I've found others that have run into this problem too, both on OSX and with different types of cameras. If I access the iSight, both calls in my code fail.
To capture multiple streams with OpenCV, I recommend using threading which can improve performance by alleviating the heavy I/O operations to a separate thread. Since accessing the webcam/IP/RTSP stream using cv2. VideoCapture().
MultiCam Capture makes it easy to capture video across multiple cameras, record your screen, and present demos or products—all at the same time. Plug in your cameras, press record, and let MultiCam Capture transform your computer into a capture hub that synchronizes all sources automatically for professional results.
For desktops, you can use either two USB-Webcams or combine a webcam with a video camera. To connect a video camera as your second camera, you will need a small device to connect your video camera to a USB port on your computer.
Using OPENCV and two standard USB cameras, I was able to do this using multithreading. Essentially, define one function which opens an opencv window and VideoCapture element. Then, create two threads with the camera ID and window name as inputs.
import cv2 import threading class camThread(threading.Thread): def __init__(self, previewName, camID): threading.Thread.__init__(self) self.previewName = previewName self.camID = camID def run(self): print "Starting " + self.previewName camPreview(self.previewName, self.camID) def camPreview(previewName, camID): cv2.namedWindow(previewName) cam = cv2.VideoCapture(camID) if cam.isOpened(): # try to get the first frame rval, frame = cam.read() else: rval = False while rval: cv2.imshow(previewName, frame) rval, frame = cam.read() key = cv2.waitKey(20) if key == 27: # exit on ESC break cv2.destroyWindow(previewName) # Create two threads as follows thread1 = camThread("Camera 1", 1) thread2 = camThread("Camera 2", 2) thread1.start() thread2.start()
Great resource for learning how to thread in python: https://www.tutorialspoint.com/python/python_multithreading.htm
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With