You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
12 KiB
12 KiB
Lx相机服务使用说明
概述
本系统提供了完整的Lx相机服务管理方案,包括:
- LxCameraService: 统一的相机操作接口
- LxCameraServiceImpl: 服务实现类
- CaptureConfig: 拍照配置类
- CaptureResult: 拍照结果类
- ImageCropper: 图像裁剪服务
文件保存路径格式
所有保存的文件按照以下格式组织:
basePath/
├── 20250325/ # 日期文件夹(yyyyMMdd)
│ ├── amplitude/ # 强度图
│ │ ├── 192.168.1.100_amplitude_20250325_143022.png
│ │ └── 192.168.1.101_amplitude_20250325_143023.png
│ ├── rgb/ # RGB图
│ │ ├── 192.168.1.100_rgb_20250325_143022.png
│ │ └── 192.168.1.101_rgb_20250325_143023.png
│ ├── depth/ # 深度图
│ │ ├── 192.168.1.100_depth_20250325_143022.png
│ │ └── 192.168.1.101_depth_20250325_143023.png
│ ├── depthColor/ # 彩色深度图
│ │ ├── 192.168.1.100_depth_color_20250325_143022.png
│ │ └── 192.168.1.101_depth_color_20250325_143023.png
│ └── pointCloud/ # 点云
│ ├── 192.168.1.100_pointcloud_20250325_143022.pcd
│ └── 192.168.1.101_pointcloud_20250325_143023.pcd
├── 20250326/
│ └── ...
└── 20250327/
└── ...
路径格式说明:
basePath/日期/类型/SN_类型_时间戳.扩展名
- basePath: 基础保存路径(如
D:/output) - 日期: 格式为
yyyyMMdd(如20250325) - 类型: 文件类型(
amplitude、rgb、depth、depthColor、pointCloud) - SN: 相机序列号(如
192.168.1.100) - 类型: 重复文件类型(与类型文件夹一致)
- 时间戳: 格式为
yyyyMMdd_HHmmss(如20250325_143022) - 扩展名: 文件扩展名(
.png或.pcd)
示例:
D:/output/20250325/pointcloud/192.168.1.100_pointcloud_20250325_143022.pcd
这种组织方式的优点:
- 按日期分类:便于按天管理和查找
- 按类型分类:便于按类型批量处理
- 时间戳唯一:确保文件名不会重复
- 结构清晰:一目了然
初始化
自动初始化
系统会在启动时自动初始化所有配置的Lx相机:
# application.yml
app:
lxCamera:
- ip: "192.168.1.100"
id: 1
savePath: "D:/output/camera1"
- ip: "192.168.1.101"
id: 2
savePath: "D:/output/camera2"
手动初始化
如果需要手动初始化:
@Autowired
private LxCameraService lxCameraService;
// 手动初始化
lxCameraService.initCameras();
基本使用
1. 拍照(默认配置)
只拍照点云数据:
@Autowired
private LxCameraService lxCameraService;
// 拍照并保存
CaptureResult result = lxCameraService.capture("192.168.1.100", "D:/output");
if (result.isSuccess()) {
System.out.println("拍照成功!");
System.out.println("重试次数: " + result.getActualRetryCount());
System.out.println("文件路径: " + result.getFilePaths());
} else {
System.out.println("拍照失败: " + result.getErrorDescription());
}
2. 拍照(自定义配置)
拍摄多种类型图片:
// 创建全类型拍照配置
CaptureConfig config = CaptureConfig.createFullCapture();
// 或自定义配置
CaptureConfig config = CaptureConfig.createCustomConfig(
true, // 强度图
true, // RGB图
true, // 深度图
true, // 彩色深度图
true // 点云
);
// 设置重试参数
config.setMaxConnectRetries(3); // 最大连接重试次数
config.setMaxCaptureRetries(3); // 最大拍照重试次数
config.setRetryInterval(500); // 重试间隔(毫秒)
// 设置深度图参数
config.setMaxDepthValue(1000.0); // 最大深度值(毫米)
config.setColormapType(0); // 颜色映射类型(0=JET, 1=RAINBOW, 2=HOT, 3=OCEAN, 4=PARULA)
// 拍照
CaptureResult result = lxCameraService.capture("192.168.1.100", "D:/output", config);
// 获取各类型图片路径
String pointCloudPath = result.getFilePath("pointCloud");
String rgbPath = result.getFilePath("rgb");
String depthPath = result.getFilePath("depth");
// ...
3. 重连相机
boolean success = lxCameraService.reconnect("192.168.1.100");
if (success) {
System.out.println("重连成功");
} else {
System.out.println("重连失败");
}
4. 检查连接状态
boolean connected = lxCameraService.isConnected("192.168.1.100");
System.out.println("相机连接状态: " + (connected ? "已连接" : "未连接"));
5. 关闭相机
// 关闭指定相机
lxCameraService.closeCamera("192.168.1.100");
// 关闭所有相机
lxCameraService.closeAllCameras();
图像裁剪
基本裁剪
@Autowired
private ImageCropper imageCropper;
// 裁剪单个BMP图像
boolean success = imageCropper.cropBmpImage(
"D:/input/image.bmp",
"D:/output/image_cropped.bmp"
);
// 裁剪任意格式图像(使用OpenCV)
boolean success = imageCropper.cropImage(
"D:/input/image.png",
"D:/output/image_cropped.png"
);
批量裁剪
// 裁剪文件夹中所有BMP图像
imageCropper.cropAllBmpImagesInFolder(
"D:/input",
"D:/output"
);
// 裁剪文件夹中指定格式的图像
imageCropper.cropImagesInFolder(
"D:/input",
"D:/output",
"png" // 文件扩展名
);
自定义裁剪区域
import org.opencv.core.Rect;
// 自定义裁剪区域
Rect cropRect = new Rect(100, 100, 800, 800);
boolean success = imageCropper.cropImageWithOpenCV(
"D:/input/image.jpg",
"D:/output/image_cropped.jpg",
cropRect
);
HTTP API接口
1. 拍照(默认配置)
POST /api/lxcamera/capture?cameraSn=192.168.1.100&basePath=D:/output
响应示例:
{
"success": true,
"errorCode": 0,
"errorMessage": null,
"errorDescription": "成功",
"retryCount": 1,
"cameraSn": "192.168.1.100",
"filePaths": {
"pointCloud": "D:/output/20250325/pointCloud/192.168.1.100_pointcloud_20250325_143022.pcd"
}
}
2. 拍照(自定义配置)
POST /api/lxcamera/capture/config
Content-Type: application/json
{
"cameraSn": "192.168.1.100",
"basePath": "D:/output",
"config": {
"captureAmplitude": true,
"captureRgb": true,
"captureDepth": true,
"captureDepthColor": true,
"capturePointCloud": true,
"maxConnectRetries": 3,
"maxCaptureRetries": 3,
"retryInterval": 500,
"maxDepthValue": 1000.0,
"colormapType": 0
}
}
响应示例:
{
"success": true,
"errorCode": 0,
"errorMessage": null,
"errorDescription": "成功",
"retryCount": 1,
"cameraSn": "192.168.1.100",
"filePaths": {
"amplitude": "D:/output/20250325/amplitude/192.168.1.100_amplitude_20250325_143022.png",
"rgb": "D:/output/20250325/rgb/192.168.1.100_rgb_20250325_143022.png",
"depth": "D:/output/20250325/depth/192.168.1.100_depth_20250325_143022.png",
"depthColor": "D:/output/20250325/depthColor/192.168.1.100_depth_color_20250325_143022.png",
"pointCloud": "D:/output/20250325/pointCloud/192.168.1.100_pointcloud_20250325_143022.pcd"
}
}
3. 重连相机
POST /api/lxcamera/reconnect?cameraSn=192.168.1.100
响应示例:
{
"success": true,
"cameraSn": "192.168.1.100",
"message": "重连成功"
}
4. 查询相机状态
GET /api/lxcamera/status?cameraSn=192.168.1.100
响应示例:
{
"cameraSn": "192.168.1.100",
"connected": true,
"status": "已连接"
}
5. 关闭相机
POST /api/lxcamera/close?cameraSn=192.168.1.100
响应示例:
{
"success": true,
"cameraSn": "192.168.1.100",
"message": "关闭成功"
}
6. 关闭所有相机
POST /api/lxcamera/closeAll
响应示例:
{
"success": true,
"message": "所有相机已关闭"
}
错误码说明
| 错误码 | 说明 | 处理建议 |
|---|---|---|
| 0 | 成功 | 无需处理 |
| -1 | 保存失败 | 检查磁盘空间和权限 |
| -2 | 目录创建失败 | 检查路径和权限 |
| -3 | 句柄获取失败 | 检查相机连接,尝试重连 |
| -4 | 连接失败 | 检查网络和相机状态 |
| -5 | 其他错误 | 查看日志详情 |
架构说明
DLL管理
系统采用"一个DLL对应一个DcLibrary"的策略:
libs/plc/
├── LxCameraApi.dll # 原始DLL
├── LxCameraApi-1.dll # 相机1专用DLL
├── LxCameraApi-2.dll # 相机2专用DLL
└── ...
这样可以避免多个相机共享同一个DLL可能产生的冲突。
设备句柄管理
每个相机有独立的设备句柄,存储在 handleMap 中:
Map<String, DeviceInfo> handleMap;
重试机制
- 连接重试:默认最多3次,间隔500ms
- 拍照重试:默认最多3次,间隔500ms
- 自动重连:拍照失败时自动尝试重连相机
性能优化建议
- 批量操作:一次处理多个相机时,使用并行处理
- 合理重试:根据网络状况调整重试次数和间隔
- 及时释放:使用完毕后及时关闭相机连接
- 异常处理:捕获并记录异常信息,便于排查问题
示例代码
完整的拍照流程
@Service
public class CameraCaptureService {
@Autowired
private LxCameraService lxCameraService;
@Autowired
private ImageCropper imageCropper;
public void captureAndProcess(String cameraSn, String basePath) {
// 1. 检查连接
if (!lxCameraService.isConnected(cameraSn)) {
log.warn("相机未连接,尝试重连");
lxCameraService.reconnect(cameraSn);
}
// 2. 创建拍照配置
CaptureConfig config = CaptureConfig.createFullCapture();
config.setMaxCaptureRetries(3);
// 3. 拍照
CaptureResult result = lxCameraService.capture(cameraSn, basePath, config);
if (result.isSuccess()) {
log.info("拍照成功,共 {} 张图片", result.getFilePaths().size());
// 4. 裁剪RGB图像
String rgbPath = result.getFilePath("rgb");
if (rgbPath != null) {
String croppedPath = basePath + "/cropped_" + new File(rgbPath).getName();
imageCropper.cropImage(rgbPath, croppedPath);
log.info("图像裁剪完成: {}", croppedPath);
}
} else {
log.error("拍照失败: {}", result.getErrorDescription());
}
}
}
注意事项
- 路径格式:Windows路径使用正斜杠
/或双反斜杠\\ - 权限问题:确保程序有读写指定路径的权限
- 相机配置:确保每个相机的IP、ID等信息配置正确
- 网络稳定:相机与服务器之间的网络连接需要稳定
- 磁盘空间:确保有足够的磁盘空间保存图片
- OpenCV初始化:确保OpenCV库已正确加载
兼容性说明
本系统保留了 LxPointCloudSaveImage 类以保持向后兼容性,但建议使用新的 LxCameraService 接口。
旧的API仍然可以继续使用:
// 旧API(仍然支持)
LxPointCloudSaveImage.saveImage("192.168.1.100", "D:/output/test.pcd");
// 新API(推荐)
CaptureResult result = lxCameraService.capture("192.168.1.100", "D:/output");
技术支持
如有问题,请查看:
- 日志文件:
logs/camera.log - 控制台输出
- API响应的错误信息