You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure Kinect:如何关联Windows设备ID与设备序列号?

解决Azure Kinect设备ID与序列号的匹配问题

我之前处理过多台Azure Kinect的多设备识别场景,刚好碰到过和你一样的问题,给你两个实用的解决方案:

方案一:在C++程序中同时输出序列号和Windows设备ID

既然你的C程序负责和Kinect硬件交互,可以直接在C里把每个设备的序列号和对应的Windows设备ID关联起来,一起输出到文件中,这样C#程序就能直接一一对应了。

要在C++中获取Kinect对应的Windows设备ID,可以借助Windows的SetupAPI函数来遍历USB设备:

  1. 首先用k4a_device_get_installed_count()获取已连接的Kinect数量
  2. 遍历每个设备,用k4a_device_open()打开,再用k4a_device_get_serialnum()获取序列号
  3. 同时调用SetupAPI相关函数(SetupDiGetClassDevs、SetupDiEnumDeviceInterfaces、SetupDiGetDeviceInterfaceDetail),筛选出VID为045E、PID为097C的USB设备,提取其设备实例ID(就是你在C#里拿到的那种格式)
  4. 把每个设备的序列号和设备ID配对后写入输出文件

这里给你一段简化的代码片段参考:

#include <k4a/k4a.h>
#include <windows.h>
#include <setupapi.h>
#include <initguid.h>
#include <usbiodef.h>

// 遍历USB设备,匹配Kinect的VID/PID,获取设备ID
std::string get_kinect_device_id(const std::string& serial_num) {
    HDEVINFO hDevInfo = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
    if (hDevInfo == INVALID_HANDLE_VALUE) {
        return "";
    }

    SP_DEVICE_INTERFACE_DATA deviceInterfaceData = {0};
    deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
    for (DWORD i = 0; SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &GUID_DEVINTERFACE_USB_DEVICE, i, &deviceInterfaceData); i++) {
        // 获取设备详情
        DWORD requiredSize = 0;
        SetupDiGetDeviceInterfaceDetail(hDevInfo, &deviceInterfaceData, NULL, 0, &requiredSize, NULL);
        std::vector<BYTE> detailData(requiredSize);
        PSP_DEVICE_INTERFACE_DETAIL_DATA pDetailData = reinterpret_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(detailData.data());
        pDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

        SP_DEVINFO_DATA devInfoData = {0};
        devInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
        if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &deviceInterfaceData, pDetailData, requiredSize, NULL, &devInfoData)) {
            // 获取硬件ID
            char hardwareId[256];
            if (SetupDiGetDeviceRegistryProperty(hDevInfo, &devInfoData, SPDRP_HARDWAREID, NULL, reinterpret_cast<PBYTE>(hardwareId), sizeof(hardwareId), NULL)) {
                // 检查是否包含Kinect的VID/PID,以及序列号
                std::string hwId(hardwareId);
                if (hwId.find("VID_045E&PID_097C") != std::string::npos && hwId.find(serial_num) != std::string::npos) {
                    // 返回设备实例ID
                    char deviceId[256];
                    if (SetupDiGetDeviceInstanceId(hDevInfo, &devInfoData, deviceId, sizeof(deviceId), NULL)) {
                        SetupDiDestroyDeviceInfoList(hDevInfo);
                        return std::string(deviceId);
                    }
                }
            }
        }
    }
    SetupDiDestroyDeviceInfoList(hDevInfo);
    return "";
}

// 主逻辑中配对序列号和设备ID
int main() {
    int deviceCount = k4a_device_get_installed_count();
    for (int i = 0; i < deviceCount; i++) {
        k4a_device_t device = NULL;
        if (k4a_device_open(i, &device) == K4A_RESULT_SUCCEEDED) {
            char serial[K4A_SERIAL_NUMBER_SIZE];
            k4a_device_get_serialnum(device, serial, sizeof(serial));
            std::string deviceId = get_kinect_device_id(serial);
            // 将serial和deviceId写入输出文件
            printf("Serial: %s, Device ID: %s\n", serial, deviceId.c_str());
            k4a_device_close(device);
        }
    }
    return 0;
}

方案二:在C#中直接从设备ID提取序列号

这个方案更简单,不需要修改你的C++代码——仔细看你拿到的Windows设备ID:
\\.\\USB#VID_045E&PID_097C#001007692912#{A5DCBF10-6530-11D2-901F-00C04FB951ED}
其中#VID_045E&PID_097C#后面、下一个#前面的001007692912就是Kinect的序列号!

所以你只需要在C#里写个字符串处理逻辑,提取这部分内容即可。比如用正则表达式或者字符串分割:

用正则表达式提取的C#代码示例:

using System.Text.RegularExpressions;

public string ExtractKinectSerialFromDeviceId(string deviceId)
{
    // 匹配VID/PID之后的序列号部分
    var match = Regex.Match(deviceId, @"VID_045E&PID_097C#([^#]+)#");
    if (match.Success)
    {
        return match.Groups[1].Value;
    }
    return string.Empty;
}

用字符串分割的C#代码示例:

public string ExtractKinectSerialFromDeviceId(string deviceId)
{
    var parts = deviceId.Split('#');
    // 设备ID格式固定的话,parts[2]就是序列号
    if (parts.Length >= 3)
    {
        return parts[2];
    }
    return string.Empty;
}

提取出序列号后,直接和C++程序输出的序列号做匹配,就能对应上每台设备了。

我个人更推荐方案二,不需要改动现有C代码,几分钟就能搞定匹配逻辑。如果方案二因为设备ID格式特殊不生效,再考虑方案一的C代码改造。


内容的提问来源于stack exchange,提问作者guidout

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:08:23