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