概述
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!nn");
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 Devicesn");
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) %sn", 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) foundnn", deviceCounter);
}
//comUnInit();
return deviceCounter;
}
int main()
{
vector<string> list;
int capid0 = 0, capid1 = 0;//摄像头ID
int 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和PID
string 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;
}
注意:以上代码均在VS2015上测试通过,如果出现字符错误,请更换为“多字节字符集”,再进行调试。
最后
以上就是忧郁大碗为你收集整理的OpenCV:如何获取摄像头的型号以及USB设备的VID和PID信息?的全部内容,希望文章能够帮你解决OpenCV:如何获取摄像头的型号以及USB设备的VID和PID信息?所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复