赞
踩
我们使用Opencv打开摄像头,一般是使用VideoCapture的open接口。
CV_WRAP virtual bool open(int index);
open接口要传入一个标识符,如果只有1个摄像机,那么就是0,如果系统中有多个摄像机,那么只要将其向上增加即可。
系统:
银河麒麟linux系统
问题:
现在我插入了一个双目摄像头(两个USB线,一个彩色,一个红外),那我就想打开彩色的,怎么办呢?每次我插入USB线,系统都会默认给设备分配一个video路径,例如 /dev/video3,根据插入USB线的顺序,每次分配的都不一样,这样通过open就不能指定打开哪一个。
解决思路:
每个设备都有自己的pid和vid,我要通过pid和vid找到特定的/dev/video,例如我获取到了路径 /dev/video3,那么取最后的数字3,通过open(3),即可打开指定的摄像头。需要使用libudev。
下面的函数是通过遍历所有的视频设备,再用摄像头的pid和vid与其对比,最后得到摄像头的路径。(这里注意麒麟linux和UOS系统,打开的序号可能会相差1,所以UOS系统需要可能要再-1)
- int findCameraVideoPath(char *pid, char *vid, char *dpath)
- {
- struct udev *udev = NULL;
- struct udev_enumerate *udev_enumerate = NULL;
- struct udev_list_entry *list_entry = NULL;
- int count = 0;
- int flag = 0;
- char devName[128]={0};
-
- udev = udev_new();
- if(udev == NULL)
- {
- //tips
- return 0;
- }
- udev_enumerate = udev_enumerate_new(udev);
- if(udev_enumerate == NULL)
- {
- //tips
- return 0;
- }
-
- udev_enumerate_add_match_subsystem(udev_enumerate, "video4linux");
- udev_enumerate_scan_devices(udev_enumerate);
- udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(udev_enumerate))
- {
- struct udev_device *device;
- device = udev_device_new_from_syspath(udev_enumerate_get_udev(udev_enumerate), udev_list_entry_get_name(list_entry));
- if(device!=NULL)
- {
- //tips
- );
-
- if(udev_device_get_property_value(device, "ID_VENDOR_ID")!=NULL &&
- udev_device_get_property_value(device, "ID_MODEL_ID")!=NULL &&
- !strcmp(vid, udev_device_get_property_value(device, "ID_VENDOR_ID")) &&
- !strcmp(pid, udev_device_get_property_value(device, "ID_MODEL_ID")))
- {
- sprintf(devName,"/dev/video%s", udev_device_get_sysnum(device));
- flag = 1;
- count++;
- }
- udev_device_unref(device);
-
- }
- else
- {
- //tips
- }
- }
-
- if(flag!=0)
- {
- if(strlen(devName)>0)
- memcpy(dpath, devName, strlen(devName));
- }
-
- udev_enumerate_unref(udev_enumerate);
- udev_unref(udev);
-
- return flag;
- }
下面附上win系统MFC的事例,与上面思路类似:
- #include <iostream>
- #include <string>
- #include <vector>
- #include <DShow.h>
- #include <CString>
- #pragma comment(lib,"Strmiids.lib")
-
- using namespace std;
- //输入:pidvid exp: vid_1234&pid_1234
- //输出:ID, 为-1则找不到设备
- int getCamIDFromPidVid(char* pidvid)
- {
- int iRet = -1;
- int iCameraNum = 0; //设备个数
- vector<CString> devList; //设备列表
-
- CString str ;
- ICreateDevEnum *pDevEnum = NULL;
- IEnumMoniker *pEnum = NULL;
- HRESULT hr = NULL;
- CoInitialize(NULL);
- hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,reinterpret_cast<void**>(&pDevEnum));
- if (SUCCEEDED(hr))
- {
- hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEnum,0);
- if (hr == S_OK)
- {
- //枚举捕获设备
- IMoniker *pMoniker = NULL;
- ULONG cFetched;
- while (pEnum->Next(1, &pMoniker, &cFetched) == S_OK)
- {
- IPropertyBag* pPropBag;
- hr = pMoniker->BindToStorage(0,0,IID_IPropertyBag,reinterpret_cast<void**>(&pPropBag));
- if (SUCCEEDED(hr))
- {
- //获取设备路径,路径里包含pidvid的信息
- VARIANT varName;
- varName.vt = VT_BSTR;
- VariantInit(&varName);
- hr = pPropBag->Read(L"DevicePath", &varName, 0); //read函数只能够读取CLSID, FriendlyName, DevicePath这三种
-
- CString sdev(varName);
- devList.push_back(sdev);
-
- iCameraNum ++;
- pPropBag->Release();
- }
-
- pMoniker->Release();
- }
- }
- }
-
- //对比,得到id
- for(int i = 0;i<devList.size();i++)
- {
- int index = devList[i].Find(pidvid);
- if(index != -1)
- {
- iRet = i;
- break;
- }
- }
-
- CoUninitialize();
- return iRet;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。