EpicEyeDevice 封装库

简介

EpicEyeDevice 是对 EpicEye SDK 的 C++ 封装库,提供了简洁易用的 3D 相机点云采集接口。EpicEye 是一款基于结构光的 3D 视觉相机,可以同时获取 2D 彩色图像和 3D 点云数据。

目录结构

EpicEyeDevice/
├── Inc/                          # 公共头文件目录
│   ├── IEpicEyeDevice.h         # 接口类定义
│   └── EpicEyeDevice_global.h   # 全局宏定义
├── _Inc/                         # 内部头文件目录
│   └── EpicEyeDevice.h          # 实现类定义
├── Src/                          # 源文件目录
│   └── EpicEyeDevice.cpp        # 实现类源文件
├── EpicEyeDevice.pro             # qmake 工程文件
└── README.md                     # 说明文档

特性

  • 支持相机搜索和设备信息查询
  • 支持通过 IP 地址连接相机
  • 支持触发式拍摄trigger + fetch
  • 支持获取点云数据(主要功能)
  • 支持获取 2D 彩色图像
  • 支持获取深度图
  • 支持获取相机内参(相机矩阵和畸变参数)
  • 支持获取/设置相机配置JSON 格式)
  • 便捷方法:一次性触发并获取点云/图像
  • 线程安全设计
  • 跨平台支持Windows x64 / Linux ARM

接口设计

核心接口

class IEpicEyeDevice
{
public:
    // 创建设备对象
    static int CreateObject(IEpicEyeDevice** ppDevice);

    // 搜索和连接
    virtual int SearchCameras(std::vector<EpicEyeDeviceInfo>& deviceList) = 0;
    virtual int Connect(const std::string& ipAddress) = 0;
    virtual int Disconnect() = 0;
    virtual bool IsConnected() = 0;

    // 获取设备信息
    virtual int GetDeviceInfo(EpicEyeDeviceInfo& deviceInfo) = 0;

    // 触发拍摄
    virtual int TriggerCapture(std::string& frameID, bool withPointCloud = true) = 0;

    // 获取数据(使用 frameID
    virtual int GetPointCloud(const std::string& frameID, PointCloudData& pointCloud) = 0;
    virtual int GetImage(const std::string& frameID, ImageData2D& image) = 0;
    virtual int GetDepth(const std::string& frameID, DepthData& depth) = 0;

    // 便捷方法(一步到位)
    virtual int CapturePointCloud(PointCloudData& pointCloud, unsigned int timeout = 5000) = 0;
    virtual int CaptureImage(ImageData2D& image, unsigned int timeout = 5000) = 0;

    // 相机参数
    virtual int GetCameraIntrinsics(CameraIntrinsics& intrinsics) = 0;
    virtual int GetConfig(std::string& configJson) = 0;
    virtual int SetConfig(const std::string& configJson) = 0;
};

使用示例

示例 1: 搜索相机并获取点云

#include "IEpicEyeDevice.h"
#include <iostream>

int main()
{
    // 1. 创建设备对象
    IEpicEyeDevice* pDevice = nullptr;
    if (IEpicEyeDevice::CreateObject(&pDevice) != 0)
    {
        std::cerr << "创建设备对象失败" << std::endl;
        return -1;
    }

    // 2. 搜索相机
    std::vector<EpicEyeDeviceInfo> deviceList;
    if (pDevice->SearchCameras(deviceList) != 0 || deviceList.empty())
    {
        std::cerr << "未找到相机" << std::endl;
        delete pDevice;
        return -1;
    }

    std::cout << "找到 " << deviceList.size() << " 个相机" << std::endl;
    std::cout << "第一个相机 IP: " << deviceList[0].ipAddress << std::endl;

    // 3. 连接第一个相机
    if (pDevice->Connect(deviceList[0].ipAddress) != 0)
    {
        std::cerr << "连接相机失败" << std::endl;
        delete pDevice;
        return -1;
    }

    std::cout << "成功连接到相机" << std::endl;

    // 4. 获取设备信息
    EpicEyeDeviceInfo info;
    pDevice->GetDeviceInfo(info);
    std::cout << "相机型号: " << info.modelName << std::endl;
    std::cout << "序列号: " << info.serialNumber << std::endl;
    std::cout << "分辨率: " << info.width << " x " << info.height << std::endl;

    // 5. 获取点云数据(一步到位)
    PointCloudData pointCloud;
    pointCloud.pData = nullptr;

    if (pDevice->CapturePointCloud(pointCloud) == 0)
    {
        std::cout << "成功采集点云数据" << std::endl;
        std::cout << "  点数: " << pointCloud.pointCount << std::endl;
        std::cout << "  宽度: " << pointCloud.width << std::endl;
        std::cout << "  高度: " << pointCloud.height << std::endl;

        // 使用点云数据...
        // 点云格式: x, y, z 交替存储
        // 例如: pointCloud.pData[0], pointCloud.pData[1], pointCloud.pData[2] 是第一个点
        for (unsigned int i = 0; i < 10 && i < pointCloud.pointCount; ++i)
        {
            float x = pointCloud.pData[i * 3 + 0];
            float y = pointCloud.pData[i * 3 + 1];
            float z = pointCloud.pData[i * 3 + 2];
            std::cout << "  点 " << i << ": (" << x << ", " << y << ", " << z << ")" << std::endl;
        }

        // 保存为 PLY 文件(可选)
        // saveToPLY("pointcloud.ply", pointCloud);

        // 释放点云数据
        if (pointCloud.pData != nullptr)
        {
            delete[] pointCloud.pData;
        }
    }

    // 6. 清理资源
    pDevice->Disconnect();
    delete pDevice;

    return 0;
}

示例 2: 分步获取点云Trigger + Fetch

#include "IEpicEyeDevice.h"

int main()
{
    IEpicEyeDevice* pDevice = nullptr;
    IEpicEyeDevice::CreateObject(&pDevice);

    // 连接相机
    pDevice->Connect("192.168.1.100");

    // 步骤1: 触发拍摄
    std::string frameID;
    if (pDevice->TriggerCapture(frameID, true) == 0)  // true = 包含点云
    {
        std::cout << "触发拍摄成功, frameID: " << frameID << std::endl;

        // 步骤2: 获取点云数据
        PointCloudData pointCloud;
        pointCloud.pData = nullptr;

        if (pDevice->GetPointCloud(frameID, pointCloud) == 0)
        {
            std::cout << "获取点云成功" << std::endl;

            // 处理点云数据...

            // 释放内存
            delete[] pointCloud.pData;
        }

        // 步骤3: 也可以获取对应的2D图像
        ImageData2D image;
        image.pData = nullptr;

        if (pDevice->GetImage(frameID, image) == 0)
        {
            std::cout << "获取图像成功" << std::endl;

            // 处理图像数据...

            // 释放内存
            delete[] image.pData;
        }
    }

    pDevice->Disconnect();
    delete pDevice;

    return 0;
}

示例 3: 获取相机内参

#include "IEpicEyeDevice.h"

int main()
{
    IEpicEyeDevice* pDevice = nullptr;
    IEpicEyeDevice::CreateObject(&pDevice);

    pDevice->Connect("192.168.1.100");

    // 获取相机内参
    CameraIntrinsics intrinsics;
    if (pDevice->GetCameraIntrinsics(intrinsics) == 0)
    {
        std::cout << "相机内参矩阵 (3x3):" << std::endl;
        for (int i = 0; i < 3; ++i)
        {
            for (int j = 0; j < 3; ++j)
            {
                std::cout << intrinsics.cameraMatrix[i * 3 + j] << " ";
            }
            std::cout << std::endl;
        }

        std::cout << "畸变参数:" << std::endl;
        for (float dist : intrinsics.distortion)
        {
            std::cout << dist << " ";
        }
        std::cout << std::endl;
    }

    pDevice->Disconnect();
    delete pDevice;

    return 0;
}

点云数据格式

点云数据存储在 PointCloudData 结构中:

struct PointCloudData
{
    float* pData;           // 点云数据指针
    unsigned int width;     // 点云宽度
    unsigned int height;    // 点云高度
    unsigned int pointCount;// 点数 (width * height)
    std::string frameID;    // 帧ID
};
  • 数据排列: x, y, z 交替存储单位为米m
  • 访问方式:
    for (unsigned int i = 0; i < pointCloud.pointCount; ++i)
    {
        float x = pointCloud.pData[i * 3 + 0];
        float y = pointCloud.pData[i * 3 + 1];
        float z = pointCloud.pData[i * 3 + 2];
    }
    
  • 内存管理: 调用者负责释放 pData 内存

编译

Windows (MSVC)

qmake EpicEyeDevice.pro
nmake

Linux (ARM)

qmake EpicEyeDevice.pro
make

链接到你的项目

在你的 .pro 文件中添加:

# 头文件路径
INCLUDEPATH += $$PWD/../../Device/EpicEyeDevice/Inc

# 库链接
win32:CONFIG(debug, debug|release) {
    LIBS += -L$$PWD/../../Device/EpicEyeDevice/debug -lEpicEyeDevice
}
win32:CONFIG(release, debug|release) {
    LIBS += -L$$PWD/../../Device/EpicEyeDevice/release -lEpicEyeDevice
}
unix:!macx {
    LIBS += -L$$PWD/../../Device/EpicEyeDevice -lEpicEyeDevice
}

注意事项

  1. 网络连接: EpicEye 相机通过以太网连接,确保网络可达
  2. IP 地址: 相机默认 IP 可能需要通过 Web UI 或工具配置
  3. 内存释放: 所有通过 Get* 方法获取的数据(点云、图像、深度图)需要手动释放内存
  4. 线程安全: 单个设备对象不支持多线程同时调用
  5. frameID: 触发拍摄后返回的 frameID 用于获取对应的点云和图像数据
  6. 点云单位: 点云坐标单位为米m

与其他设备封装的对比

特性 VrEyeDevice IKapDevice EpicEyeDevice
SDK VzNLSDK IKapLibrary EpicEye SDK
设备类型 激光线扫描 3D 相机 通用工业 2D 相机 结构光 3D 相机
主要数据 3D 激光线点云 2D 图像 3D 点云 + 2D 图像
通信方式 USB/以太网 GigE/USB3/CameraLink/CXP 以太网HTTP REST API
特殊功能 RGBD、摆动机构 ROI、触发模式 深度图、相机内参

版本历史

  • v1.0.0 (2025-01-XX) - 初始版本
    • 支持相机搜索和连接
    • 支持点云采集
    • 支持 2D 图像和深度图采集
    • 支持相机内参获取
    • 支持相机配置管理

许可

遵循项目整体许可协议

联系方式

如有问题请联系项目维护者