356 lines
10 KiB
Markdown
356 lines
10 KiB
Markdown
# 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 图像和深度图采集
|
||
- 支持相机内参获取
|
||
- 支持相机配置管理
|
||
|
||
## 许可
|
||
|
||
遵循项目整体许可协议
|
||
|
||
## 联系方式
|
||
|
||
如有问题请联系项目维护者
|