GitHub 您所在的位置:网站首页 windows照相机参数 GitHub

GitHub

2024-07-17 11:33| 来源: 网络整理| 查看: 265

描述:根据摄像头硬件标识(如vid_1234&pid_4321)获取OpenCV打开照相机中所需参数index下标,适用于Windows平台,cv.VideoCapture(int index, CAP_DSHOW)。

关键词:Python;OpenCV;VideoCapture;camera_id;index;下标;索引

为什么需要这样一个函数?

如果电脑中只有 1 个照相机设备,那么我们使用 OpenCV 打开时,传递的下标参数使用默认的 0 即可;

但是但电脑中有多个照相机设备时,我们需要打开特定照相机时,我们就不知道哪个设备对应那个下标了,而且当设备的插口发生变化时其下标也会变化。

通过查看 OpenCV 源码可得知(可参考cap_dshow.cppvideoInput::getDevice函数),在打开照相机时,是通过枚举系统照相机设备找到对应下标的照相机,那么我们只需要通过同样的方式枚举,通过照相机特定标识判断是否匹配,返回对应下标即可。

具体源码及已编译动态链接库:Myles Yang/CvCameraIndex (gitee.com)

如何在Python中使用:

import ctypes # 加载对应位数动态链接库 _CvCameraIndex = ctypes.cdll.LoadLibrary('lib/CvCameraIndex_x64.dll') _CvCameraIndex.getCameraIndex.argtypes = [ctypes.c_char_p] _CvCameraIndex.getCameraIndex.restype = ctypes.c_int def get_camera_index(hwid: str) -> int: """ 获取cv.VideoCapture(camera_index, cv2.CAP_DSHOW)参数camera_index :param hwid: 硬件标识,不区分大小写,如vid_1234&pid_4321 :return: 索引下标,返回 -1 时获取失败 """ b_hwid = bytes(hwid, encoding='utf-8') return _CvCameraIndex.getCameraIndex(b_hwid) if __name__ == '__main__': camera_index = get_camera_index('vid_1234&pid_4321') print(camera_index)

C++实现(CvCameraIndex.cpp):

#include #include #include #pragma comment(lib, "Strmiids.lib") #define DllExport _declspec(dllexport) #define MAX_DEVICE_PATH_LENGTH 255 extern "C" DllExport int getCameraIndex(const char* hwid); /** * Get the index of the camera opened by the opencv function VideoCapture(int index, CAP_DSHOW) * Only available on windows platforms. * For the method, refer to opencv ver.4.6 source code cap_dshow.cpp function videoInput::getDevice. * * @param hwid: Camera hardware ID (Case insensitive): e.g."vid_1234&pid_4321" * @return int: Index of the camera, return -1 in case of acquisition failure * * @author Myles Yang */ DllExport int getCameraIndex(const char* hwid) { bool done = false; int deviceCounter = 0; int cameraIndex = -1; // Initialize COM HRESULT hr = NULL; hr = CoInitialize(NULL); // always true when python is called //if (FAILED(hr)) //{ // return cameraID; //} // Create the System Device Enumerator. ICreateDevEnum* pSysDevEnum = NULL; hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, reinterpret_cast(&pSysDevEnum)); if (FAILED(hr)) { CoUninitialize(); return cameraIndex; } // Obtain a class enumerator for the video input category. IEnumMoniker* pEnumCat = NULL; hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0); if (hr == S_OK) { // Enumerate the monikers. IMoniker* pMoniker = NULL; ULONG cFetched; while ((!done) && (pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)) { // Bind the first moniker to an object IPropertyBag* pPropBag; hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPropBag); if (SUCCEEDED(hr)) { // To retrieve the filter's DevicePath, do the following: VARIANT varName; varName.vt = VT_BSTR; VariantInit(&varName); hr = pPropBag->Read(L"DevicePath", &varName, 0); if (SUCCEEDED(hr)) { // convert DevicePath to char* char devicePath[MAX_DEVICE_PATH_LENGTH] = { 0 }; int count = 0; while (varName.bstrVal[count] != 0x00) { devicePath[count] = varName.bstrVal[count]; count++; } std::string devicePathString = devicePath; // lower string // to lower std::string hwidString = hwid; std::transform(hwidString.begin(), hwidString.end(), hwidString.begin(), ::tolower); // match int matched = devicePathString.find(hwidString); if (matched >= 0) { cameraIndex = deviceCounter; done = true; } } deviceCounter++; VariantClear(&varName); pPropBag->Release(); pPropBag = NULL; } pMoniker->Release(); pMoniker = NULL; } pEnumCat->Release(); pEnumCat = NULL; } pSysDevEnum->Release(); pSysDevEnum = NULL; CoUninitialize(); return cameraIndex; }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有