2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > OpenCV:如何获取摄像头的型号以及USB设备的VID和PID信息?

OpenCV:如何获取摄像头的型号以及USB设备的VID和PID信息?

时间:2022-10-05 11:25:40

相关推荐

OpenCV:如何获取摄像头的型号以及USB设备的VID和PID信息?

VID和PID

PID/VID唯一标识一个设备,HardwareID是为了给系统识别的 ,他是根据PID/VID而生成的。这个与序列号没什么关系,序列号一般都是厂家固化到芯片中的信息而已。GUID只是为了标志你安装的设备是属于一个什么类当中,这个类可以显示再设备管理器中。比如:你可以定义一个类,当然这个类有与系统中任何类都不同的GUID,然后选择一个图标和类名,就可以同网卡等其他设备一起显示在设备管理器下的根目录中了

根据USB规范的规定,所有的USB设备都有供应商ID(VID)和产品识别码(PID),主机通过不同的VID和PID来区别不同的设备,VID和PID都是两个字节长,其中,供应商ID(VID)由供应商向USB执行论坛申请,每个供应商的VID是唯一的,PID由供应商自行决定,理论上来说,不同的产品、相同产品的不同型号、相同型号的不同设计的产品最好采用不同的PID,以便区别相同厂家的不同设备。

VID和PID通常情况下有两种存储方式,第一种是主控生产商的VID和PID,存储在主控的bootcode中;第二种是设备生产商的VID和PID,该VID和PID存储在主控外部的非易失性存储设备中(EEPROM或Flash)的设备固件中,当USB设备连接主机时,如果固件中有设备生产商的VID和PID,会将该VID和PID报告给主机,而忽略主控生产商的VID和PID。所以理论上一个USB存储设备的VID应该是设备生产商的VID,而不是主控生产商的VID,这两个VID应该是不同的(主控生产商自己生产的设备除外)。

由于VID和PID重复并不会对产品的使用带来严重影响,很多USB设备生产商(山寨厂居多)为了方便,并不会向USB执行论坛申请自己的VID,而是依然沿用主控生产商的VID或随便向产品写入VID和PID;同时,正规厂家只需要申请VID,PID由厂家自行确定,所以存在相同型号的产品,可能采用了不同的主控(商业需要,很正常),而他们的PID是一样的,基于上述原因通过VID和PID就不能准确识别USB设备的主控型号,这个问题大家在使用USB设备的过程中需要注意。

查看设备信息

1、鼠标右键“我的电脑”,选择“管理”,进入“计算机管理”。

2、在“计算机管理”界面,依次选择“设备管理器”、“图像设备”、摄像头的型号,选中点击鼠标右键,选择“属性”。

3、进入“属性”页面,就可已查看USB设备的VID和PID了。

获取摄像头型号

#include <opencv2/imgcodecs.hpp>#include <opencv2/highgui.hpp>#include "windows.h"#include "dshow.h"#include <iostream>#pragma comment(lib, "strmiids.lib")#pragma comment(lib, "quartz.lib")using namespace cv;using namespace std;int listDevices(vector<string>& list) {//COM Library Initialization//comInit();//if (!silent) DebugPrintOut("\nVIDEOINPUT SPY MODE!\n\n");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) {printf("SETUP: Looking For Capture Devices\n");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; // Skip this one, maybe the next one will work.}// Find the description or friendly name.VARIANT varName;VariantInit(&varName);hr = pPropBag->Read(L"Description", &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 };//int maxLen = sizeof(deviceNames[0]) / sizeof(deviceNames[0][0]) - 2;while (varName.bstrVal[count] != 0x00 && count < 255){tmp[count] = (char)varName.bstrVal[count];count++;}list.push_back(tmp);//deviceNames[deviceCounter][count] = 0;//if (!silent) DebugPrintOut("SETUP: %i) %s\n", deviceCounter, deviceNames[deviceCounter]);}pPropBag->Release();pPropBag = NULL;pMoniker->Release();pMoniker = NULL;deviceCounter++;}pDevEnum->Release();pDevEnum = NULL;pEnum->Release();pEnum = NULL;}//if (!silent) DebugPrintOut("SETUP: %i Device(s) found\n\n", deviceCounter);}//comUnInit();return deviceCounter;}int main(){vector<string> list;int capid0 = 0, capid1 = 0;//摄像头IDint divice_num = 0;divice_num = listDevices(list);//设备列表cout << "divice_num:" << divice_num << endl;for (int i = 0; i < list.size(); i++){/*if (list[i] == "3D Camera"){capid1 = i;cout << list[i]<< " is 3D Camera"<<endl;}if (list[i] == "USB2.0 HD UVC WebCam"){capid0 = i;cout << list[i] << " is USB2.0 HD UVC WebCam" << endl;}*/cout << "Device["<<i<<"]:"<< list[i] << endl;}VideoCapture cap;cout << "capid= " << capid1 << endl;cap.open(capid1);Mat frame;while (1){cap >> frame;imshow("capshow", frame);if (waitKey(30) == 27){break;}}return 0;}

获取设备的VID和PID

在使用多个摄像头的时候,如果使用同型号的摄像头,它们的VID和PID相同的。所以,依靠VID和PID不能区分同型号的摄像头,必须要知道设备的端口号,才可以确定调用的是哪个摄像头。

#include <iostream>#include <windows.h>#include <string>#include <setupapi.h>#include <initguid.h>using namespace std;#pragma comment(lib,"setupapi.lib")DEFINE_GUID(UsbClassGuid, 0xa5dcbf10L, 0x6530, 0x11d2, 0x90, 0x1f, 0x00, 0xc0, 0x4f, 0xb9, 0x51, 0xed);//获取USB设备VID和PIDstring GetUsbInfo(){HDEVINFO hDevInfo;SP_DEVICE_INTERFACE_DATA spDevData;PSP_DEVICE_INTERFACE_DETAIL_DATA pDetail;BOOL bRes = TRUE;int nCount = 0;string csResult;hDevInfo = ::SetupDiGetClassDevs((LPGUID)&UsbClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);if (hDevInfo != INVALID_HANDLE_VALUE){pDetail = (PSP_DEVICE_INTERFACE_DETAIL_DATA)::GlobalAlloc(LMEM_ZEROINIT, 1024);pDetail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);while (bRes){spDevData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);bRes = ::SetupDiEnumDeviceInterfaces(hDevInfo, NULL, (LPGUID)&UsbClassGuid, nCount, &spDevData);if (bRes){bRes = ::SetupDiGetInterfaceDeviceDetail(hDevInfo, &spDevData, pDetail, 1024, NULL, NULL);if (bRes){string szStr = pDetail->DevicePath;csResult += szStr + "\n";nCount++;}}}::GlobalFree(pDetail);::SetupDiDestroyDeviceInfoList(hDevInfo);}return csResult;}int main(void){string csStr = GetUsbInfo();cout << csStr << endl;system("PAUSE");return 0;}

注意:以上代码均在VS上测试通过,如果出现字符错误,请更换为“多字节字符集”,再进行调试。

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