OpenCV指定pid和vid通过MSMF打开摄像头

在基于OpenCV的项目中,实际开发过程会面临设备上存在多个摄像头,需要指定摄像头的pid和vid打开摄像头。在OpenCV通过MSMF打开摄像头时,需要传入摄像头的index,因此需要在打开该摄像头前需要找出摄像头的index,下面给出通过微软的MF API找出MSMF枚举摄像头index的代码:

cpp 复制代码
#include <windows.h>
#include <mfapi.h>
#include <mfidl.h>
#include <mfreadwrite.h>
#include <string>
#include <vector>
#include <iostream>
#include <opencv2/opencv.hpp>

#pragma comment(lib, "mf.lib")
#pragma comment(lib, "mfplat.lib")
#pragma comment(lib, "mfreadwrite.lib")
#pragma comment(lib, "mfuuid.lib")

struct CameraInfo {
    int index;      // OpenCV 摄像头索引
    int vid;        // Vendor ID (e.g., 0x046D for Logitech)
    int pid;        // Product ID (e.g., 0x0825 for C920)
    std::string symbolicLink; // 设备符号链接
};

// 获取所有 Media Foundation 摄像头的 PID/VID
std::vector<CameraInfo> getMFCameraList() {
    std::vector<CameraInfo> cameras;

    IMFAttributes* pAttributes = nullptr;
    IMFActivate** ppDevices = nullptr;
    UINT32 count = 0;

    // 初始化 Media Foundation
    MFStartup(MF_VERSION);

    // 配置设备枚举参数(仅视频采集设备)
    MFCreateAttributes(&pAttributes, 1);
    pAttributes->SetGUID(
        MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
        MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
    );

    // 枚举设备
    MFEnumDeviceSources(pAttributes, &ppDevices, &count);

    for (UINT32 i = 0; i < count; i++) {
        WCHAR* symbolicLink = nullptr;
        UINT32 length = 0;

        // 获取设备 Symbolic Link(包含 VID/PID)
        ppDevices[i]->GetAllocatedString(
            MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK,
            &symbolicLink,
            &length
        );

        if (symbolicLink) {
            std::wstring ws(symbolicLink);
            std::string devicePath(ws.begin(), ws.end());

            // 解析 VID/PID(格式:\\?\usb#vid_xxxx&pid_xxxx...)
            size_t vidPos = devicePath.find("vid_");
            size_t pidPos = devicePath.find("pid_");

            if (vidPos != std::string::npos && pidPos != std::string::npos) {
                std::string vidStr = devicePath.substr(vidPos + 4, 4);
                std::string pidStr = devicePath.substr(pidPos + 4, 4);

                int vid = std::stoi(vidStr, nullptr, 16);
                int pid = std::stoi(pidStr, nullptr, 16);

                cameras.push_back({-1, vid, pid, devicePath});
            }

            CoTaskMemFree(symbolicLink);
        }
        ppDevices[i]->Release();
    }

    if (pAttributes) pAttributes->Release();
    if (ppDevices) CoTaskMemFree(ppDevices);
    MFShutdown();

    return cameras;
}

// 匹配 OpenCV 摄像头索引
int findOpenCVCameraIndex(int targetVid, int targetPid) {
    auto cameras = getMFCameraList();
    int opencvIndex = 0;

    while (true) {
        cv::VideoCapture cap(opencvIndex, cv::CAP_MSMF);
        if (!cap.isOpened()) {
            break; // 没有更多摄像头
        }

        // 检查当前摄像头是否匹配目标 PID/VID
        for (const auto& cam : cameras) {
            if (cam.vid == targetVid && cam.pid == targetPid) {
                std::cout << "Found camera at OpenCV index: " << opencvIndex << std::endl;
                cap.release();
                return opencvIndex;
            }
        }

        cap.release();
        opencvIndex++;
    }

    return -1; // 未找到
}

int main() {
    // 示例:查找 Logitech C920(VID=0x046D, PID=0x0825)
    int targetVid = 0x046D;
    int targetPid = 0x0825;

    int cameraIndex = findOpenCVCameraIndex(targetVid, targetPid);
    if (cameraIndex != -1) {
        cv::VideoCapture cap(cameraIndex, cv::CAP_MSMF);
        if (cap.isOpened()) {
            std::cout << "Successfully opened target camera!" << std::endl;
            // 进行视频捕获...
        }
    } else {
        std::cerr << "Target camera not found." << std::endl;
    }

    return 0;
}
相关推荐
zhaoshuzhaoshu11 分钟前
人工智能(AI)发展史:详细里程碑
人工智能·职场和发展
Luke~12 分钟前
阿里云计算巢已上架!3分钟部署 Loki AI 事故分析引擎,SRE 复盘时间直接砍掉 80%
人工智能·阿里云·云计算·loki·devops·aiops·sre
weixin_1562415757612 分钟前
基于YOLOv8深度学习花卉识别系统摄像头实时图片文件夹多图片等另有其他的识别系统可二开
大数据·人工智能·python·深度学习·yolo
QQ6765800818 分钟前
AI赋能轨道交通智能巡检 轨道交通故障检测 轨道缺陷断裂检测 轨道裂纹识别 鱼尾板故障识别 轨道巡检缺陷数据集深度学习yolo第10303期
人工智能·深度学习·yolo·智能巡检·轨道交通故障检测·鱼尾板故障识别·轨道缺陷断裂检测
小陈工20 分钟前
2026年4月7日技术资讯洞察:下一代数据库融合、AI基础设施竞赛与异步编程实战
开发语言·前端·数据库·人工智能·python
tq108620 分钟前
组织的本质:从科层制到伴星系统的决断理论
人工智能
科技与数码24 分钟前
互联网保险迎来新篇章,元保方锐分享行业发展前沿洞察
大数据·人工智能
云程笔记29 分钟前
002.计算机视觉与目标检测发展简史:从传统方法到深度学习
深度学习·yolo·目标检测·计算机视觉
汽车仪器仪表相关领域35 分钟前
NHFID-1000型非甲烷总烃分析仪:技术破局,重构固定污染源监测新体验
java·大数据·网络·人工智能·单元测试·可用性测试·安全性测试