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;//摄像头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上测试通过,如果出现字符错误,请更换为“多字节字符集”,再进行调试。

评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值