2025-12-10 00:01:32 +08:00

356 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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