插拔usb摄像头时候,调用cap=cv2.VideoCapture(ID)时,其ID会改变,查了网上的做法,很多都是C++的程序编的,那么如果用python怎么获取,想到一个土办法,就是将c++获取USB摄像头的名称及ID号输出到控制台编译成exe,python调用exe,截取控制台输出字符串,就可以得到windows下的所有摄像头名称及对应cv2.VideoCapture(ID)的ID。
c++的程序根据网上提供的代码改了改,如有侵权请联系,C++代码如下:
#include<iostream>
#include "strmif.h"
#include <initguid.h>
#include<vector>
#include<string>
#include "windows.h"
#include "tchar.h"
#include <setupapi.h>
#include <functional>
#include <map>
#pragma comment(lib, "setupapi.lib")
using namespace std;
#define VI_MAX_CAMERAS 20
DEFINE_GUID(CLSID_SystemDeviceEnum, 0x62be5d10, 0x60eb, 0x11d0, 0xbd, 0x3b, 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86);
DEFINE_GUID(CLSID_VideoInputDeviceCategory, 0x860bb310, 0x5d01, 0x11d0, 0xbd, 0x3b, 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86);
DEFINE_GUID(IID_ICreateDevEnum, 0x29840822, 0x5b84, 0x11d0, 0xbd, 0x3b, 0x00, 0xa0, 0xc9, 0x11, 0xce, 0x86);
int listDevices(vector<string>& list){
ICreateDevEnum *pDevEnum = NULL;
IEnumMoniker *pEnum = NULL;
int deviceCounter = 0;
CoInitialize(NULL);
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
reinterpret_cast<void**>(&pDevEnum));
if (SUCCEEDED(hr))
{
hr = pDevEnum->CreateClassEnumerator(
CLSID_VideoInputDeviceCategory,
&pEnum, 0);
if (hr == S_OK){
IMoniker *pMoniker = NULL;
while (pEnum->Next(1, &pMoniker, NULL) == S_OK){
IPropertyBag *pPropBag;
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
(void**)(&pPropBag));
if (FAILED(hr)){
pMoniker->Release();
continue;
}
VARIANT varName;
VariantInit(&varName);
hr = pPropBag->Read(L"DevId", &varName, 0);
if (FAILED(hr)) {
hr = pPropBag->Read(L"FriendlyName", &varName, 0);
}
if (SUCCEEDED(hr)){
hr = pPropBag->Read(L"FriendlyName", &varName, 0);
int count = 0;
char tmp[255] = {0};
while (varName.bstrVal[count] != 0x00 && count < 255) {
tmp[count] = (char)varName.bstrVal[count];
count++;
}
list.push_back(tmp);
}
pPropBag->Release();
pPropBag = NULL;
pMoniker->Release();
pMoniker = NULL;
deviceCounter++;
}
pDevEnum->Release();
pDevEnum = NULL;
pEnum->Release();
pEnum = NULL;
}
}
return deviceCounter;
}
int main()
{
vector<string> CameraName;
int num = listDevices(CameraName);
for (int i = 0; i < num;i++){
cout <<"@camera"<< i << ":" << CameraName[i] << endl;
}
return 11;
}
将以上代码编译成exe,然后通过python调用,即可获得摄像头和id:
import os
main='CameraEnum.exe'
rs=os.popen(main)
#print(rs.read())
a=rs.read()
sa = a.split('\n')
for line in sa:
if len(line)>=7:
if line[:7]=='@camera':
camera=line[7:].split(":")
print("摄像头名字:",camera[1])
print("摄像头的ID:",camera[0])
输出如下:这样就可以不用担心USB摄像头插拔导致的ID变换,只要去匹配摄像头的友好名字就能找到对应的ID,输入cv2.VideoCapture(ID)