一台电脑连接多个同种USB摄像头区分测试

       最近忙于处理摄像头测试的事,发现电脑连接多个同种USB视频设备时设备的名字都是一样的,GUID也是一样的,不能再像以前使用opencv通过名字直接打开摄像头采集图像,摆在眼前的是同台电脑如何同时打开多个摄像头同时进行测试呢?在网上搜了很多资料,也没找到相关的资料,没有相关的经验可以借鉴,或许有没有分享出来,只能摸着石头过河,硬着头皮探索。

       通过比对计算机的设备管理器发现对应的设备属性之间有关位置信息存在差异(port,hub),思考是否可以通过这个差异区分出不同的视屏设备呢?

      

     因此 朝着这个思路去寻找方法,通过opencv 写的demo打开摄像头是通过 VideoCapture capture = VideoCapture(camID);  当连接多个视频设备时,会枚举出所有视屏设备,代码如下(Vedioinput,directshow 都有介绍。):

int EnumDevices(CStringArray& listCamera)
{
	//枚举视频设备
	ICreateDevEnum *pCreateDevEnum;
	HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pCreateDevEnum);
	if (hr != NOERROR)return -1;

	CComPtr<IEnumMoniker> pEm;
	hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEm, 0);
	if (hr != NOERROR)return -1;

	pEm->Reset();

	int id = 0;
	ULONG cFetched;
	IMoniker *pM;
	while (hr = pEm->Next(1, &pM, &cFetched), hr == S_OK)
	{
		IPropertyBag *pBag;
		hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pBag);
		if (SUCCEEDED(hr))
		{
			VARIANT var;
			CString tempstr;
			var.vt = VT_BSTR;
			hr = pBag->Read(L"FriendlyName", &var, NULL);
			if (hr == NOERROR)
			{
				id++;
				LPWSTR* str = var.pbstrVal;
				listCamera.Add(var.bstrVal);
				SysFreeString(var.bstrVal);
			}
			pBag->Release();
		}
		pM->Release();
	}
	return id;
}

尝试更新VideoCapture capture = VideoCapture(camID);中的camID, 发现camID 跟枚举出来的视屏设备的顺序一致,打开的也是对应顺序的视频设备,因此猜想对应的设备ID就是对应枚举出来的顺序号(当然还可以根据对应的port 来控制不同的视频设备,不过后面没有尝试),后来也证明了这个猜想是对的。

解决了视频设备号的问题,可以这个只能打开了摄像头才知道打开的是对应哪个USB port 口的设备,如何想要打开连接哪个USB Port 口的就打开哪个port 口的设备呢?这就回到了开篇讲的设备位置信息。通过设备名称和设备位置信息绑定就知道到打开了哪个USB port口的对应视频设备, 上面的方法已经不适用了没有找到对应的属性,因此重新研究,参考文章如下:https://stackoverflow.com/questions/3438366/setupdigetdeviceproperty-usage-example

void EnumDevices(vector<CString> &listCamera)
{
	CONST GUID *pClassGuid = NULL;
	CString strDevice_Friendly_Name, strDevice_Location_Info;
	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];
	
	USES_CONVERSION;
	Sleep(1000); //防止更新模组时,USB camera 没有识别
	// List all connected USB devices  
	hDevInfo = SetupDiGetClassDevs(pClassGuid, _T("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++)
	{
		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;
			}

			if (strDevice_Location_Info.Find(_T("0000.0014"), 0) != -1)
			{
				CString TempStr;
				TempStr.Format(_T("%s-%s"), strDevice_Friendly_Name, strDevice_Location_Info);
				listCamera.push_back(TempStr);
			}
		}

	}

	return ;
}

 

至此完美收关,能够随心所欲打开所要打开的视频设备了。

  • 7
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
要绘制同种电荷电场线,可以使用 Python 中的 Matplotlib 库进行绘图。以下是一个简单的示例代码,可以绘制出两个同种电荷的电场线: ```python import numpy as np import matplotlib.pyplot as plt # 定义电荷的电荷量和位置 q1 = 1.0 x1, y1 = 0, 0 q2 = 1.0 x2, y2 = 2, 0 # 定义电场强度函数 def E(q, r0, x, y): """返回电荷q在点(x,y)处产生的电场强度""" den = np.hypot(x - r0[0], y - r0[1])**3 return q * (x - r0[0]) / den, q * (y - r0[1]) / den # 定义网格和坐标轴 nx, ny = 64, 64 x = np.linspace(-3, 3, nx) y = np.linspace(-3, 3, ny) X, Y = np.meshgrid(x, y) # 计算电场强度 Ex, Ey = np.zeros((ny, nx)), np.zeros((ny, nx)) for i in range(nx): for j in range(ny): # 计算第一个电荷的电场强度 ex1, ey1 = E(q1, (x1, y1), x[i], y[j]) # 计算第二个电荷的电场强度 ex2, ey2 = E(q2, (x2, y2), x[i], y[j]) # 计算总电场强度 Ex[j, i] = ex1 + ex2 Ey[j, i] = ey1 + ey2 # 绘制电场线 plt.streamplot(x, y, Ex, Ey, color='k', linewidth=1, density=2) # 添加标题和坐标轴标签 plt.title('Same Charge Electric Field Lines') plt.xlabel('x') plt.ylabel('y') # 显示图形 plt.show() ``` 上述代码中,我们首先定义了两个电荷的电荷量和位置,然后定义了一个计算电场强度的函数,接着定义了网格和坐标轴。最后,我们通过计算电场强度并使用 `streamplot()` 函数绘制了电场线。运行上述代码可以得到如下所示的电场线图像: ![Same Charge Electric Field Lines](https://img-blog.csdnimg.cn/20210428151527523.png)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值