OpenCV VideoCapture device index / device number
Asked Answered
T

5

6

I have a python environment (on Windows 10) that uses OpenCV VideoCapture class to connect to multiple usb cameras.

As far as I know, there is no way to identify a specific camera in OpenCV other than the device parameter in the VideoCapture class constructor / open method.

The problem is that the device parameter changes depending on how many cameras are actually connected and to which usb ports.

I want to be able to identify a specific camera and find its "device index" or "camera index" no matter how many cameras are connected and to which usb ports.

Can somebody please suggest a way to achieve that functionality? python code is preferable but C++ will also do.

Toowoomba answered 23/12, 2016 at 9:23 Comment(1)
Which operating system?Bucella
W
3

As far as I know, openCV enumerates devices and uses the index of it as a camera index. But the way it enumerates can differ among backends. Anyway, if you can enumerate devices as OpenCV do, you can match the index of the device and its information depend on your code.

So, In Windows environment, you can use MSMF or DSHOW as a backend. If you are using MSMF as a backend, I made a simple function to list devices and match its name to its index. Here: https://github.com/pvys/CV-camera-finder.

If you are using DSHOW as a background, here's a nice article: https://www.codeproject.com/Articles/1274094/Capturing-Images-from-Camera-using-Python-and-Dire

Wortham answered 2/3, 2020 at 18:15 Comment(2)
CV-camera-finder (function get_MF_devices()) works great! My other approaches sometimes had the friendly name out of order with the OpenCV device numbersStilton
As mentioned in my last comment, CV-camera-finder works great. Unfortunately, is is tied to Python 3.7. Is there anyway it can be updated to any version of Python 3?Stilton
B
2

Preface, I do not use windows, and this hasn't been tested, but is a combination of answers and source found from online, with some modifications.

Walk the USB registry keys and parse the sub_key strings:

import _winreg
usb_devices=[]
index = 0
with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Enum\USB') as root_usb:
    while True:
        try:
            subkey = _winreg.EnumKey(root_usb, index)
            usb_devices.append(subkey)
            index += 1
        except WindowError as e:
            if e[0] == 259: # No more data is available
                break
            elif e[0] == 234: # more data is available
                index += 1
                continue
            raise e
print('parse these', usb_devices)

Or possibly Popen a wmic subprocess and parse the stdout:

from subprocess import Popen, PIPE
results1 = Popen(['wmic', 'path', 'win32_pnpentity', 'get', 'caption' '/format:list'], stdout=PIPE)
results2 = Popen(['wmic','path','Win32_SerialPort','get','DeviceID^,Caption^,Description^,Name^,ProviderType','/format:list'], stdout=PIPE)
print('parse these', results1.stdout.read())
print('parse these', results2.stdout.read())

Related, linux, mac, and windows c++:

Bucella answered 23/12, 2016 at 10:48 Comment(1)
For some reason winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Enum\USB') gives me a SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 29-30: truncated \UXXXXXXXX escape on Python 3.7/Windows 10. If I descend the key hierarchy one level at a time I can eventually enumerate the USB values but these are in the form 'VID_056A&PID_033C&MI_01' etc, so I don't know how to relate these to the OpenCV camera index.Wrung
P
0

I wrote a python package based on opencv's videoio source code to list the cameras available on different backends. It might solve your problem.

Install cv2_enumerate_cameras

pip install cv2_enumerate_cameras

Enumerate camera information

from cv2_enumerate_cameras import enumerate_cameras

for camera_info in enumerate_cameras():
    print(f'{camera_info.index}: {camera_info.name}')

Create VideoCapture

cap = cv2.VideoCapture(camera_info.index, camera_info.backend)
Plunger answered 28/2, 2024 at 3:23 Comment(1)
this is a neat solution, the c++ backend checks outGoddamned
H
0

Here is a lightweight method that uses directshow under the hood.

https://github.com/JohnHardy/pyusbcameraindex

from pyusbcameraindex import enumerate_usb_video_devices_windows

devices = enumerate_usb_video_devices_windows()
for device in devices:
    print(f"{device.index} == {device.name} (VID: {device.vid}, PID: {device.pid}, Path: {device.path}")
Had answered 10/6, 2024 at 14:57 Comment(0)
H
-1

If you can differentiate the cameras by their serial number or device and vendor id, you can loop through all video devices before opening with opencv and search for the camera device you want to open.

Hypoploid answered 23/12, 2016 at 9:59 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.