IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> Opencv根据USB摄像头PID |VID号,获取对应摄像头索引 -> 正文阅读

[人工智能]Opencv根据USB摄像头PID |VID号,获取对应摄像头索引

1.引言

电脑插多个USB摄像头时,当插拔或者开机之后,Opencv对应的摄像头索引会发生改变,导致Opencv打开摄像头会开错,比如笔记本自带一个摄像头,插上一个USB摄像头时,有时自带的摄像头索引是0,有时是1。十分困扰,因此本文通过获取摄像头设备的VID与PID号(这两个号是出厂自带的,不会发生改变),获取对应的Opencv索引值,打开摄像头。为了方便使用,本人将其导出动态库文件,并采用C++或Python调用该动态库。

2.C++程序导出动态库

windows下获取所有摄像头VIDPID,及其索引的程序参考【通过Opencv打开指定摄像头的方法】。本人环境为vs2019,注意在属性设置里面,高级→字符集→使用多字节字符集

#include <iostream>
#include <string>
#include <vector>
#include <DShow.h>
#include <CString>
#include <atlstr.h>
#pragma   comment(lib,"Strmiids.lib")


#define LRDLLTEST_EXPORTS //先定义宏

#ifdef LRDLLTEST_EXPORTS
#define LRDLLTEST_API __declspec(dllexport)
#else
#define LRDLLTEST_API __declspec(dllimport)
#endif

extern "C" LRDLLTEST_API int getCamIDFromPidVid(const char* pidvid);

LRDLLTEST_API int getCamIDFromPidVid(const char* pidvid)
{
	// example std::string pidvid = "0001";
	std::vector<std::string> devList; //设备列表
	int iCameraNum = 0;			//设备个数

	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);
					
					std::string strStr;
					strStr = sdev.GetBuffer(0);
					//std::cout << "----:\n" << strStr<<std::endl;
					devList.push_back(strStr);


					iCameraNum++;
					pPropBag->Release();
				}

				pMoniker->Release();
			}
		}
	}
	//std::cout << devList.size() << std::endl;
	for (int i = 0; i < devList.size(); i++) {
		std::cout << devList[i] << std::endl;
	}
	int iRet = -1;
	//对比,得到id,没有符合的就返回-1
	for (int i = 0; i < devList.size(); i++)
	{
		int index = devList[i].find(pidvid);
		if (index != -1)
		{
			iRet = i;
			break;
		}
	}
	CoUninitialize();
	return iRet;
}

程序编写完毕之后,在配置一下属性,方便导出动态库,如下。然后生成解决方案

?生成完毕,将在x64/release文件夹下生成python_ues_cpp.dll与python_ues_cpp.lib,python_ues_cpp是我自己的名字,实际名字是根据你的方案来的。

3.python调用

查看usb设备的vid和pid,输出是这样的

?所以我们在程序中指定一些关键词就可,简单的调用程序如下:

# -*- coding: utf-8 -*-
from ctypes import *
import cv2
fileName="python_use_cpp.dll"
func=cdll.LoadLibrary(fileName)
string=bytes("vid_0001&pid_0001",encoding="utf-8")
#string="vid_0001&pid_0001".encode()
a=func.getCamIDFromPidVid(string)
print(a)
cap = cv2.VideoCapture(a,cv2.CAP_DSHOW) # 摄像头的ID不同设备上可能不同


while 1:
    ret,img0=cap.read()
    if not ret:
        continue

    cv2.imshow('result', img0)
    key =cv2.waitKey(1)  # 1 millisecond

    if key & 0xFF == ord('q') or key == 27:
        break
cv2.destroyAllWindows()

3.C++调用

#include <iostream>
#include <opencv2/opencv.hpp>
//
//#pragma comment (lib,"python_use_cpp.lib")
extern "C" __declspec(dllexport) int getCamIDFromPidVid(const char* pidvid);
int main(int avgc, char** argv) {

	const char* pidvid = "vid_0001&pid_0001";
	int A = getCamIDFromPidVid(pidvid);
	//int A=getCamIDFromPidVid(argv[1]);
	std::cout << A << std::endl;

	cv::VideoCapture camera0(A, cv::CAP_DSHOW);

	if (!camera0.isOpened()) {
		std::cout << "can not open" << std::endl;
		return 1;
	}
	while (true)
	{
		cv::Mat frame0;
		camera0 >> frame0;
		cv::imshow("frame", frame0);
		char c = cv::waitKey(1);
		if (c == 27)
		{
			break;
			cv::destroyAllWindows();
		}
	}
	return 0;
}

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-05-10 11:54:11  更:2022-05-10 11:55:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 6:47:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码