一台电脑同时连接多个相同的USB摄像头并根据USB口进行区分
一臺電腦同時連接多個相同的USB攝像頭并根據(jù)USB口進行區(qū)分
百度搜了下,
https://blog.csdn.net/kingston110/article/details/112060113?spm=1001.2014.3001.5506
這位老哥給的方案最靠譜,但是這老哥貌似有點保留,根據(jù)他的代碼是沒辦法對相同攝像頭by不同的USB口進行區(qū)分。
最后小研究了下找到解決方案。
1.OPENCV中打開攝像頭都是打開攝像頭的Index,這個Index是通過COM來遍歷“CLSID_VideoInputDeviceCategory”,這里可以查詢到不同Index的“DevicePath”。
比如:
Index: 0->"\\?\usb#vid_xxxx&pid_xxxx&mi_00#6&53e1f6&0&0000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}\global"
。
。
。
這里用“#”作為字符串的分割點,取出“6&53e1f6&0&0000”作為后面USB端口比較的字符串
代碼:
int listDevices(std::map<std::string,int>& 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)){// Create an enumerator for the video capture category.hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEnum, 0);if (hr == S_OK){IMoniker *pMoniker = NULL;int iCamID = 0;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; // Skip this one, maybe the next one will work.}// Find the description or friendly name.VARIANT varName;VariantInit(&varName);hr = pPropBag->Read(L"DevicePath", &varName, 0);if (SUCCEEDED(hr)){_bstr_t bstr(varName);std::string strtmp = bstr;std::vector<std::string> listtmp;tool_StringA::split(strtmp, listtmp, '#');strtmp = listtmp[2];std::transform(strtmp.begin(), strtmp.end(), strtmp.begin(), ::tolower);list.emplace(strtmp,iCamID++);printf("ID:%d - %s\n", iCamID - 1, strtmp.c_str());}pPropBag->Release();pPropBag = NULL;pMoniker->Release();pMoniker = NULL;deviceCounter++;}pDevEnum->Release();pDevEnum = NULL;pEnum->Release();pEnum = NULL;}//if (!silent)printf("SETUP: %i Device(s) found\n\n", deviceCounter);}//comUnInit();return deviceCounter; }2. 根據(jù)USB口找到上面對應(yīng)的信息:
這個位置可以通過SetupDiGetDevicePropertyW這個API 傳入DEVPKEY_Device_LocationInfo得到,
對應(yīng)的信息如下:
“USB\VID_xxxx&PID_xxxx&MI_00\6&53e1f6&0&0000”->"0000.0014.0000.005.000.000.000.000.000"
“USB\VID_xxxx&PID_xxxx&MI_00\6&53e1f6&0&0000”分割‘\\’,得到"6&53e1f6&0&0000",和上面取到的信息一樣,當然大小寫不一樣需要轉(zhuǎn)換下。
這段代碼如下:
void EnumDevices(std::map<std::string, std::string> &listCamera) {CONST GUID *pClassGuid = NULL;unsigned i, j;DWORD dwSize, dwPropertyRegDataType;DEVPROPTYPE ulPropertyType;CONFIGRET status;HDEVINFO hDevInfo;SP_DEVINFO_DATA DeviceInfoData;const static LPCTSTR arPrefix[3] = { TEXT("VID_"), TEXT("PID_"), TEXT("MI_") };TCHAR szDeviceInstanceID[MAX_DEVICE_ID_LEN];TCHAR szDesc[1024], szHardwareIDs[4096];WCHAR szBuffer[4096] = { 0 };LPTSTR pszToken, pszNextToken;TCHAR szVid[MAX_DEVICE_ID_LEN], szPid[MAX_DEVICE_ID_LEN], szMi[MAX_DEVICE_ID_LEN];// List all connected USB devices hDevInfo = SetupDiGetClassDevs(pClassGuid, ("USB"), NULL, pClassGuid != NULL ? DIGCF_PRESENT : DIGCF_ALLCLASSES | DIGCF_PRESENT);if (hDevInfo == INVALID_HANDLE_VALUE)return;// Find the ones that are driverless for (i = 0; ; i++){std::wstring strDevice_Friendly_Name, strDevice_Location_Info;DeviceInfoData.cbSize = sizeof(DeviceInfoData);if (!SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData))break;status = CM_Get_Device_ID(DeviceInfoData.DevInst, szDeviceInstanceID, MAX_PATH, 0);if (status != CR_SUCCESS)continue;if (SetupDiGetDevicePropertyW(hDevInfo, &DeviceInfoData, &DEVPKEY_Device_BusReportedDeviceDesc,&ulPropertyType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize, 0)){memset(szBuffer, 0, sizeof(WCHAR) * 4096);if (SetupDiGetDevicePropertyW(hDevInfo, &DeviceInfoData, &DEVPKEY_Device_FriendlyName,&ulPropertyType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize, 0)){strDevice_Friendly_Name = szBuffer;}memset(szBuffer, 0, sizeof(WCHAR) * 4096);if (SetupDiGetDevicePropertyW(hDevInfo, &DeviceInfoData, &DEVPKEY_Device_LocationInfo,&ulPropertyType, (BYTE*)szBuffer, sizeof(szBuffer), &dwSize, 0)){strDevice_Location_Info = szBuffer;}std::string Location, FriendlyName;//Location = Cto_string(strDevice_Location_Info);//FriendlyName = Cto_string(strDevice_Friendly_Name);Unicode2ANSI(strDevice_Location_Info, Location);Unicode2ANSI(strDevice_Friendly_Name, FriendlyName);std::string::size_type pos = Location.find("0000.0014");if (pos != std::string::npos){pos = FriendlyName.find("Camera");if (pos != std::string::npos){std::string strtmp = szDeviceInstanceID;std::vector<std::string> listtmp;tool_StringA::split(strtmp, listtmp, '\\');strtmp = listtmp[2];std::transform(strtmp.begin(), strtmp.end(), strtmp.begin(), ::tolower);listCamera.emplace(Location, strtmp);printf("%s - %s\n", strtmp.c_str(), Location.c_str());}}}} }這樣基本就可以了,可以把需要區(qū)分的usb端口號“0000.0014.0000.006.000.000.000.000”寫入你的配置文件中即可~
std::map<std::string, int> camIDlist; listDevices(camIDlist);inih::INIReader r = inih::INIReader{ "./setting.ini" };const auto& v3 = r.Get<std::string>("Setting", "CamUSBPortLocation");std::map<std::string, std::string> camList; EnumDevices(camList);auto pos = camList.find(v3);decltype (pos->second) strDeviceID;if (pos != camList.end()){bFind = true;strDeviceID = pos->second;}else{printf("沒有找到Setting.ini對應(yīng)的USB攝像頭!\n");return 0;}auto itFind = camIDlist.find(strDeviceID);if (itFind!=camIDlist.end()){iCamID = itFind->second;}else{printf("沒有找到對應(yīng)的USB攝像頭!\n");return 0;}?
?
總結(jié)
以上是生活随笔為你收集整理的一台电脑同时连接多个相同的USB摄像头并根据USB口进行区分的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在conda中安装pytorch
- 下一篇: 保险行业-团险-投保单位所属行业类别整理