2

I want to get the Friendly Names and USB port numbers for external USB video capture devices using Python on a Windows platform. I’m using OpenCV to capture video from a USB capture device. OpenCV refers to the USB ports as “-1” (the first working camera found), “0” (for me, this is the webcam), and “1”, “2”, etc. for external USB video capture devices (EasyCap, Hauppauge USB Live-2, etc.). Here is a one-line example of connecting to the webcam in OpenCV:

cap = cv2.VideoCapture(0)

I have three external video capture devices and a webcam. Here is my code that successfully shows the friendly name of just these devices (I’m not sure this will work for every USB video capture device):

import wmi
c = wmi.WMI()
wql = "Select * From Win32_USBControllerDevice"
for item in c.query(wql):
    a = item.Dependent.PNPClass
    b = item.Dependent.Name.upper()
    if (a.upper() == 'MEDIA' or a.upper() == 'CAMERA') and 'AUDIO' not in b:
        print(item.Dependent.Name)

Results are:

Integrated Webcam
Hauppauge USB-Live2
USB TV Tuner
USB Video Device

I can print all the device information if I replace the print statement with

print(item.Dependent)

and then I get the following results:

instance of Win32_PnPEntity
{
        Caption = "Integrated Webcam";
        ClassGuid = "{ca3e7ab9-b4c3-4ae6-8251-579ef933890f}";
        CompatibleID = {"USB\\Class_0e&SubClass_03&Prot_00", "USB\\Class_0e&SubClass_03", "USB\\Class_0e"};
        ConfigManagerErrorCode = 0;
        ConfigManagerUserConfig = FALSE;
        CreationClassName = "Win32_PnPEntity";
        Description = "USB Video Device";
        DeviceID = "USB\\VID_0BDA&PID_5686&MI_00\\6&153A3DF0&0&0000";
        HardwareID = {"USB\\VID_0BDA&PID_5686&REV_5729&MI_00", "USB\\VID_0BDA&PID_5686&MI_00"};
        Manufacturer = "Microsoft";
        Name = "Integrated Webcam";
        PNPClass = "Camera";
        PNPDeviceID = "USB\\VID_0BDA&PID_5686&MI_00\\6&153A3DF0&0&0000";
        Present = TRUE;
        Service = "usbvideo";
        Status = "OK";
        SystemCreationClassName = "Win32_ComputerSystem";
        SystemName = "MY-LAPTOP";
};


instance of Win32_PnPEntity
{
        Caption = "Hauppauge USB-Live2";
        ClassGuid = "{4d36e96c-e325-11ce-bfc1-08002be10318}";
        CompatibleID = {"USB\\Class_ff&SubClass_ff&Prot_ff", "USB\\Class_ff&SubClass_ff", "USB\\Class_ff"};
        ConfigManagerErrorCode = 0;
        ConfigManagerUserConfig = FALSE;
        CreationClassName = "Win32_PnPEntity";
        Description = "Hauppauge USB-Live2";
        DeviceID = "USB\\VID_2040&PID_C200&MI_01\\6&19EA708B&0&0001";
        HardwareID = {"USB\\VID_2040&PID_C200&REV_4001&MI_01", "USB\\VID_2040&PID_C200&MI_01"};
        Manufacturer = "Hauppauge";
        Name = "Hauppauge USB-Live2";
        PNPClass = "MEDIA";
        PNPDeviceID = "USB\\VID_2040&PID_C200&MI_01\\6&19EA708B&0&0001";
        Present = TRUE;
        Service = "hcw10bda";
        Status = "OK";
        SystemCreationClassName = "Win32_ComputerSystem";
        SystemName = "MY-LAPTOP";
};


instance of Win32_PnPEntity
{
        Caption = "USB TV Tuner";
        ClassGuid = "{4d36e96c-e325-11ce-bfc1-08002be10318}";
        CompatibleID = {"USB\\Class_FF&SubClass_00&Prot_FF", "USB\\Class_FF&SubClass_00", "USB\\Class_FF"};
        ConfigManagerErrorCode = 0;
        ConfigManagerUserConfig = FALSE;
        CreationClassName = "Win32_PnPEntity";
        Description = "USB TV Tuner";
        DeviceID = "USB\\VID_1B71&PID_3002\\300000000002";
        HardwareID = {"USB\\VID_1B71&PID_3002&REV_0100", "USB\\VID_1B71&PID_3002"};
        Manufacturer = "Active Development Co., Ltd.";
        Name = "USB TV Tuner";
        PNPClass = "MEDIA";
        PNPDeviceID = "USB\\VID_1B71&PID_3002\\300000000002";
        Present = TRUE;
        Service = "X86BDA";
        Status = "OK";
        SystemCreationClassName = "Win32_ComputerSystem";
        SystemName = "MY-LAPTOP";
};


instance of Win32_PnPEntity
{
        Caption = "USB Video Device";
        ClassGuid = "{ca3e7ab9-b4c3-4ae6-8251-579ef933890f}";
        CompatibleID = {"USB\\Class_0e&SubClass_03&Prot_00", "USB\\Class_0e&SubClass_03", "USB\\Class_0e"};
        ConfigManagerErrorCode = 0;
        ConfigManagerUserConfig = FALSE;
        CreationClassName = "Win32_PnPEntity";
        Description = "USB Video Device";
        DeviceID = "USB\\VID_1E4E&PID_701F&MI_00\\6&3543E1D5&0&0000";
        HardwareID = {"USB\\VID_1E4E&PID_701F&REV_0100&MI_00", "USB\\VID_1E4E&PID_701F&MI_00"};
        Manufacturer = "Microsoft";
        Name = "USB Video Device";
        PNPClass = "Camera";
        PNPDeviceID = "USB\\VID_1E4E&PID_701F&MI_00\\6&3543E1D5&0&0000";
        Present = TRUE;
        Service = "usbvideo";
        Status = "OK";
        SystemCreationClassName = "Win32_ComputerSystem";
        SystemName = "MY-LAPTOP";
};

There must be something in these results that indicate the port that the external devices are connected to, but I don’t see it. Suggestions on how I can associate the friendly name with a port number that OpenCV recognizes?

slalomchip
  • 779
  • 2
  • 9
  • 25
  • I don't use Windows but I *think*, if you use the `ffmpeg` command to list devices, the order they come up in matches the OpenCV numbering. I have been wrong before though, but if someone shows me to be wrong, that may help us find the answer and I'm cool with that! – Mark Setchell Feb 08 '20 at 21:18
  • 1
    Sounds like a logical idea, but it didn't work. I moved the devices around to different USB ports but the the order remained the same in the response to the command line `ffmpeg -list_devices true -f dshow -i dummy` – slalomchip Feb 09 '20 at 16:06
  • Ok, but did they change in OpenCV? – Mark Setchell Feb 09 '20 at 16:07
  • I'm having issues with OpenCV reading from the devices. It doesn't want o recognize one of them and I can read from another one about 10% of the time that I try to connect. That's another problem I'm trying to solve. But back to this problem, when I move the devices around the ports and execute the WMI script (above), the response from the script varies, but not consistently with how the devices were moved. – slalomchip Feb 09 '20 at 16:12
  • My point was that I think the OpenCV numbering matches the `ffmpeg` numbering. So the question is not whether or not the numbering changes when you move devices but rather does the ffmpeg ordering still match the OpenCV ordering? If it does, it means you can use `ffmpeg` to know the OpenCV ordering - which is what you were asking, I think :-) – Mark Setchell Feb 09 '20 at 16:43
  • Two of the three devices I'm working with capture analog NTSC. The third device is an HDMI capture device. The two analog devices are the ones giving OpenCV troubles but the HDMI capture device works flawlessly with OpenCV. When I am able to capture from one of the analog devices, the internal webcam is port 0 and the capture device is port 1. When using the HDMI capture device, it's reversed - the HDMI capture device is port 0 and the internal webcam is port 1. Both analog devices work fine with their bundled capture software. – slalomchip Feb 09 '20 at 16:46
  • But to answer your question, it appears that the ffmpeg order may be the same as OpenCV. When the HDMI capture card is connected it is listed first by ffmpeg and is port 0 in OpenCV. When the Hauppauge (analog) device is connected (and works), the webcam is listed first and is port 0 in OpenCV. Thanks for the suggestion - your hunch is correct. Sorry to be so thick. – slalomchip Feb 09 '20 at 16:55
  • @slalomchip I'm facing the same problem. Was the answer: "use ffmpeg to enumerate cameras because OpenCv does the same"? Have you ever understood why WMI gets a different order? In my opinion OpenCv shows the order in which the devices got connected, but I don't find this information in WMI output to order by it. – Francesco Bonizzi Jun 15 '20 at 17:05
  • 1
    @Francesco Bonizzi - Sorry for the late delay - just saw it. You have it correct. Use ffmpeg to enumerate the cameras because OpenCV also uses ffmpeg. I have found this to be generally true. I have one instance when a USB capture device is not in the same order as presented. However, using ffmpeg will list the same device as an audio device and a video device. In my case, I'm only interested in video and not audio, so I had to exclude anything with "Audio" in the list. It isn't perfect, but it works most of the time - good enough for me. – slalomchip Jul 08 '20 at 02:40

1 Answers1

2

I found a solution that works great. CV-camera-finder can be found here: https://github.com/pvys/CV-camera-finder.

slalomchip
  • 779
  • 2
  • 9
  • 25