H-Barrio

Nov 3, 20232 min

Quick and Inefficient Way to Stream Multiple Webcams with Python

In this post, we will use Python and OpenCV to inefficiently find all available webcams in our system and display their image. OpenCV works in mysterious ways when looking for installed USB camera devices in your system, depending on the backend and the operating system. We are going to loop through a sensible range of possible camera indexes, -100 to 100 in this case, using this function:

def explore_cameras(search_range=100):
 
found_cam_ids = []
 
for i in range(-search_range, search_range):
 
print(f"Testing camera index: {i}")
 
cam = cv2.VideoCapture(i)
 
while True:
 
ret, img = cam.read()
 
if ret:
 
found_cam_ids.append(i)
 
cam.release()
 
break
 
else:
 
break
 

 
return found_cam_ids

This function, explore_cameras, will loop through indexes -100 to 100, trying to obtain a returning frame. If it can grab a frame, we will add the found index to found_cam_ids and return a list with all these camera indexes that answer with a frame. We will pass this list to our main function that will start parallel threads for each of these camera indexes that have been found:

import cv2
 
import threading
 

 
def main():
 
cams = explore_cameras()
 
if len(cams) == 0:
 
print("No cameras found. Exiting")
 
return
 
threads = []
 
for cam in cams:
 
threads.append(threading.Thread(target=show_webcam, args=(cam,)))
 
for thread in threads:
 
thread.start()
 

The target function for each thread is show_webcam, which will create a new display window for each camera and proceed to display its feed:

def show_webcam(idx):
 
cam = cv2.VideoCapture(idx)
 
window_name = f"Cam{idx}"
 
cv2.namedWindow(window_name, cv2.WINDOW_AUTOSIZE)
 
while True:
 
ret, img = cam.read()
 
if not ret:
 
print("Not Capturing")
 
continue
 
cv2.imshow(window_name, img)
 
if cv2.waitKey(1) == 27:
 
break # esc to quit

Running this code will result in multiple windows with the stream from each USB camera; note that the cameras cannot be connected to the same USB hub or concentrator as they will share an address and bandwidth that can become exhausted, resulting in no image being fed.

The complete code is here, using Python 3.11 and opencv-contrib-python 4.8.1.78:

import cv2
 
import threading
 

 

 
def show_webcam(idx):
 
cam = cv2.VideoCapture(idx)
 
window_name = f"Cam{idx}"
 
cv2.namedWindow(window_name, cv2.WINDOW_AUTOSIZE)
 
while True:
 
ret, img = cam.read()
 
if not ret:
 
print("Not Capturing")
 
continue
 
cv2.imshow(window_name, img)
 
if cv2.waitKey(1) == 27:
 
break # esc to quit
 

 

 
def explore_cameras(search_range=100):
 
found_cam_ids = []
 
for i in range(-search_range, search_range):
 
print(f"Testing camera index: {i}")
 
cam = cv2.VideoCapture(i)
 
print(cam)
 
while True:
 
ret, img = cam.read()
 
if ret:
 
found_cam_ids.append(i)
 
cam.release()
 
break
 
else:
 
break
 

 
return found_cam_ids
 

 

 
def main():
 
cams = explore_cameras()
 
if len(cams) == 0:
 
print("No cameras found. Exiting")
 
return
 
threads = []
 
for cam in cams:
 
threads.append(threading.Thread(target=show_webcam, args=(cam,)))
 
for thread in threads:
 
thread.start()
 

 

 
if __name__ == '__main__':
 
main()
 

Do not hesitate to contact us if you require quantitative model development, deployment, verification, or validation. We will gladly help you with your machine learning or artificial intelligence challenges when applied to asset management, automation, or intelligence gathering from satellite, drone, or fixed-point imagery.

    180
    0