356 lines
10 KiB
Markdown
Raw Normal View History

2025-12-10 00:01:32 +08:00
# 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<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: 搜索相机并获取点云
```cpp
#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
```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 图像和深度图采集
- 支持相机内参获取
- 支持相机配置管理
## 许可
遵循项目整体许可协议
## 联系方式
如有问题请联系项目维护者