1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 一台电脑同时连接多个相同的USB摄像头并根据USB口进行区分

一台电脑同时连接多个相同的USB摄像头并根据USB口进行区分

时间:2019-01-05 12:41:25

相关推荐

一台电脑同时连接多个相同的USB摄像头并根据USB口进行区分

一台电脑同时连接多个相同的USB摄像头并根据USB口进行区分

百度搜了下,

/kingston110/article/details/112060113?spm=1001..3001.5506

这位老哥给的方案最靠谱,但是这老哥貌似有点保留,根据他的代码是没办法对相同摄像头by不同的USB口进行区分。

最后小研究了下找到解决方案。

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. 根据USB口找到上面对应的信息:

这个位置可以通过SetupDiGetDevicePropertyW这个API 传入DEVPKEY_Device_LocationInfo得到,

对应的信息如下:

“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",和上面取到的信息一样,当然大小写不一样需要转换下。

这段代码如下:

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());}}}}}

这样基本就可以了,可以把需要区分的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对应的USB摄像头!\n");return 0;}auto itFind = camIDlist.find(strDeviceID);if (itFind!=camIDlist.end()){iCamID = itFind->second;}else{printf("没有找到对应的USB摄像头!\n");return 0;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。