# 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) ## 接口设计 ### 核心接口 ```cpp class IEpicEyeDevice { public: // 创建设备对象 static int CreateObject(IEpicEyeDevice** ppDevice); // 搜索和连接 virtual int SearchCameras(std::vector& 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: 搜索相机并获取点云 ```cpp #include "IEpicEyeDevice.h" #include int main() { // 1. 创建设备对象 IEpicEyeDevice* pDevice = nullptr; if (IEpicEyeDevice::CreateObject(&pDevice) != 0) { std::cerr << "创建设备对象失败" << std::endl; return -1; } // 2. 搜索相机 std::vector 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) ```cpp #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: 获取相机内参 ```cpp #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` 结构中: ```cpp struct PointCloudData { float* pData; // 点云数据指针 unsigned int width; // 点云宽度 unsigned int height; // 点云高度 unsigned int pointCount;// 点数 (width * height) std::string frameID; // 帧ID }; ``` - **数据排列**: x, y, z 交替存储,单位为米(m) - **访问方式**: ```cpp 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) ```bash qmake EpicEyeDevice.pro nmake ``` ### Linux (ARM) ```bash qmake EpicEyeDevice.pro make ``` ## 链接到你的项目 在你的 .pro 文件中添加: ```qmake # 头文件路径 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 图像和深度图采集 - 支持相机内参获取 - 支持相机配置管理 ## 许可 遵循项目整体许可协议 ## 联系方式 如有问题请联系项目维护者