使用Ninja配置Msvc编译
This commit is contained in:
@@ -2,43 +2,70 @@
|
||||
|
||||
## 1. 系统概述
|
||||
|
||||
本系统是一个基于立体视觉的仓库巡检图像采集与处理系统。它集成了图漾(Percipio)工业相机SDK和海康(MVS)相机SDK进行多相机图像采集,使用OpenCV进行图像处理,Qt6作为用户界面框架,并通过Redis与外部系统(如机器人控制系统)进行通信和任务调度。
|
||||
本系统是一个基于立体视觉的仓库巡检图像采集与处理系统。它集成了图漾(Percipio)工业深度相机SDK和海康(MVS)工业2D相机SDK进行多相机图像采集,使用OpenCV进行图像处理,Qt6作为用户界面框架,并通过Redis与外部系统(如WMS仓库管理系统、机器人控制系统)进行通信和任务调度。
|
||||
|
||||
系统主要功能包括:
|
||||
- 多相机同步采集(深度图与彩色图)
|
||||
- 实时图像预览与状态监控
|
||||
- 基于Redis的任务触发与结果上报
|
||||
- 多种检测算法(货位占用、横梁/立柱变形、托盘偏差等)
|
||||
- 系统配置管理与日志记录
|
||||
- **多相机统一管理**:同时支持深度相机(Percipio)和2D相机(MVS)的数据采集
|
||||
- **实时图像预览与状态监控**:GUI界面实时显示相机图像,支持深度图伪彩色显示
|
||||
- **基于Redis的任务触发与结果上报**:支持跨数据库的任务监听和结果写入
|
||||
- **多种检测算法**:
|
||||
- 货位占用检测(Flag 1):基于2D图像的目标检测
|
||||
- 托盘位置偏移检测(Flag 2):基于深度数据的3D位置计算
|
||||
- 横梁/立柱变形检测(Flag 3):基于深度数据的结构变形测量
|
||||
- 视觉盘点检测(Flag 4):基于Halcon的QR码识别,支持连续扫描和去重
|
||||
- 盘点停止信号(Flag 5):停止Flag 4的连续扫描循环
|
||||
- **智能相机分配**:根据任务类型自动选择合适的相机设备
|
||||
- **系统配置管理与日志记录**:支持参数持久化、实时日志显示和错误处理
|
||||
|
||||
## 2. 目录结构说明
|
||||
|
||||
```text
|
||||
scripts/ # 批处理脚本 (数据库配置、模拟任务等)
|
||||
scripts/ # 批处理脚本 (Redis数据库配置、模拟WMS任务等)
|
||||
docs/ # 项目文档
|
||||
├── project_architecture.md # 项目架构文档 (本文档)
|
||||
├── project_class_interaction.md # 类交互关系文档
|
||||
└── cmake_configuration_summary.md # CMake构建配置文档
|
||||
|
||||
image_capture/
|
||||
├── CMakeLists.txt # 主构建配置文件
|
||||
├── cmake/ # CMake模块配置
|
||||
│ ├── CompilerOptions.cmake # 编译器选项配置
|
||||
│ ├── Dependencies.cmake # 依赖项管理 (Qt6, OpenCV, Open3D)
|
||||
│ └── PercipioSDK.cmake # Percipio相机SDK配置
|
||||
├── config.json # 系统配置文件 (相机参数、算法阈值、Redis配置等)
|
||||
└── src/
|
||||
├── algorithm/ # 核心算法库
|
||||
│ ├── core/ # 算法基类与结果定义 (DetectionBase, DetectionResult)
|
||||
│ ├── detections/ # 具体检测算法实现 (SlotOccupancy, BeamRackDeflection等)
|
||||
│ └── utils/ # 图像处理工具 (ImageProcessor)
|
||||
│ ├── core/ # 算法基类与结果定义
|
||||
│ │ ├── detection_base.h/cpp # 检测算法基类
|
||||
│ │ └── detection_result.h/cpp # 检测结果数据结构
|
||||
│ ├── detections/ # 具体检测算法实现
|
||||
│ │ ├── slot_occupancy/ # 货位占用检测
|
||||
│ │ ├── pallet_offset/ # 托盘偏移检测
|
||||
│ │ ├── beam_rack_deflection/ # 横梁立柱变形检测
|
||||
│ │ └── visual_inventory/ # 视觉盘点检测
|
||||
│ └── utils/ # 图像处理工具
|
||||
├── camera/ # 相机驱动层
|
||||
│ ├── ty_multi_camera_capture.cpp/h # 图漾(Percipio) 3D相机封装
|
||||
│ └── mvs_multi_camera_capture.cpp/h # 海康(MVS) 2D相机封装
|
||||
│ ├── ty_multi_camera_capture.h/cpp # 图漾(Percipio)深度相机封装
|
||||
│ └── mvs_multi_camera_capture.h/cpp # 海康(MVS)2D相机封装
|
||||
├── common/ # 通用设施
|
||||
│ ├── config_manager.cpp/h # 配置管理单例
|
||||
│ ├── log_manager.cpp/h # 日志管理
|
||||
│ ├── config_manager.h/cpp # 配置管理单例 (JSON配置加载/保存)
|
||||
│ ├── log_manager.h/cpp # 日志管理 (spdlog封装)
|
||||
│ └── log_streambuf.h # std::cout重定向到GUI
|
||||
├── device/ # 硬件设备管理
|
||||
│ └── device_manager.cpp/h # 相机设备单例管理
|
||||
├── gui/ # 用户界面
|
||||
│ └── mainwindow.cpp/h/ui # 主窗口实现 (集成Settings Tab)
|
||||
│ └── device_manager.h/cpp # 相机设备单例管理 (统一设备接口)
|
||||
├── gui/ # 用户界面 (Qt6)
|
||||
│ └── mainwindow.h/cpp/ui # 主窗口实现 (实时预览+设置界面)
|
||||
├── redis/ # 通信模块
|
||||
│ └── redis_communicator.cpp/h # Redis客户端封装
|
||||
│ └── redis_communicator.h/cpp # Redis客户端封装 (跨数据库支持)
|
||||
├── task/ # 任务调度
|
||||
│ └── task_manager.cpp/h # 任务分发与执行逻辑
|
||||
│ └── task_manager.h/cpp # 任务管理器 (队列+线程+算法调度)
|
||||
├── vision/ # 系统控制
|
||||
│ └── vision_controller.cpp/h # 顶层控制器,协调Redis与Task
|
||||
├── common_types.h # 通用数据类型 (Point3D, CameraIntrinsics)
|
||||
│ └── vision_controller.h/cpp # 顶层控制器 (Redis+Task协调)
|
||||
├── common_types.h # 通用数据类型 (Point3D, CameraIntrinsics等)
|
||||
├── tools/ # 工具程序目录
|
||||
│ ├── calibration_tool/ # 相机标定工具
|
||||
│ ├── slot_algo_tuner/ # 货位算法调参工具
|
||||
│ └── intrinsic_dumper/ # 相机内参导出工具
|
||||
└── main.cpp # 程序入口
|
||||
```
|
||||
|
||||
@@ -46,11 +73,11 @@ image_capture/
|
||||
|
||||
系统采用分层架构设计,各模块职责明确:
|
||||
|
||||
- **展示层 (GUI)**: `MainWindow` 负责界面显示、手动控制、参数配置及日志展示。
|
||||
- **控制层 (Controller)**: `VisionController` 作为系统级控制器,负责服务的启动/停止,协调 `RedisCommunicator` 和 `TaskManager`。
|
||||
- **业务逻辑层 (Task/Manager)**: `TaskManager` 解析任务指令,`DeviceManager` 管理硬件资源。
|
||||
- **算法层 (Algorithm)**: 提供具体的视觉检测功能,继承自 `DetectionBase`。
|
||||
- **驱动层 (Driver)**: `CameraCapture` 封装底层SDK调用。
|
||||
- **展示层 (Presentation)**: `MainWindow` 负责Qt6界面显示、实时相机预览、手动控制、参数配置及日志展示。
|
||||
- **控制层 (Control)**: `VisionController` 作为系统级控制器,负责服务的启动/停止,协调Redis通信和任务管理,使用回调机制解耦模块间依赖。
|
||||
- **业务逻辑层 (Business Logic)**: `TaskManager` 负责任务队列管理、算法调度和结果处理;`DeviceManager` 作为硬件资源的统一访问点(单例模式)。
|
||||
- **算法层 (Algorithm)**: 提供具体的视觉检测功能,所有算法继承自 `DetectionBase`,支持统一的 `execute()` 接口。
|
||||
- **基础设施层 (Infrastructure)**: `CameraCapture` 封装底层相机SDK调用,`RedisCommunicator` 处理跨数据库通信,`ConfigManager` 管理系统配置。
|
||||
|
||||
### 系统分层架构图
|
||||
|
||||
@@ -112,101 +139,187 @@ graph TB
|
||||
classDiagram
|
||||
class MainWindow {
|
||||
+VisionController visionController_
|
||||
+QTimer imageTimer_
|
||||
+updateImage()
|
||||
+onSaveSettings()
|
||||
+showLogMessage()
|
||||
}
|
||||
|
||||
class VisionController {
|
||||
+RedisCommunicator redis_comm_
|
||||
+TaskManager task_manager_
|
||||
+shared_ptr<RedisCommunicator> redis_comm_
|
||||
+shared_ptr<RedisCommunicator> redis_result_comm_
|
||||
+shared_ptr<TaskManager> task_manager_
|
||||
+initialize()
|
||||
+start()
|
||||
+stop()
|
||||
-onTaskReceived()
|
||||
}
|
||||
|
||||
class DeviceManager {
|
||||
<<Singleton>>
|
||||
+CameraCapture camera_capture_
|
||||
+shared_ptr<CameraCapture> capture_
|
||||
+unique_ptr<MvsMultiCameraCapture> mvs_cameras_
|
||||
+initialize()
|
||||
+startAll()
|
||||
+getLatestImages()
|
||||
+computePointCloud()
|
||||
+get2DCameraImage()
|
||||
}
|
||||
|
||||
class TaskManager {
|
||||
+executeTask()
|
||||
-algorithms_ map
|
||||
+queue<RedisTaskData> task_queue_
|
||||
+map<int, DetectionBase*> detectors_
|
||||
+thread execution_thread_
|
||||
+handleTask()
|
||||
+executeDetectionTask()
|
||||
-executeVisualInventoryLoop()
|
||||
-processResult()
|
||||
-addWarningAlarmSignals()
|
||||
}
|
||||
|
||||
class CameraCapture {
|
||||
+vector<CameraInfo> cameras_
|
||||
+getLatestImages()
|
||||
+computePointCloud()
|
||||
+start()
|
||||
-captureThreadFunc()
|
||||
}
|
||||
|
||||
class MvsMultiCameraCapture {
|
||||
+vector<CameraInfo> cameras_
|
||||
+getLatestImage()
|
||||
+start()
|
||||
}
|
||||
|
||||
class RedisCommunicator {
|
||||
+connect()
|
||||
+listenForTasks()
|
||||
+publishResult()
|
||||
+startListening()
|
||||
+writeString()
|
||||
+setTaskCallback()
|
||||
}
|
||||
|
||||
class ConfigManager {
|
||||
<<Singleton>>
|
||||
+json config_data_
|
||||
+loadConfig()
|
||||
+saveConfig()
|
||||
+getValue()
|
||||
}
|
||||
|
||||
MainWindow --> VisionController : 只有与管理
|
||||
VisionController --> RedisCommunicator : 使用
|
||||
VisionController --> TaskManager : 使用
|
||||
class DetectionBase {
|
||||
<<Abstract>>
|
||||
+execute(depth, color, side, result, point_cloud, beam_length)
|
||||
}
|
||||
|
||||
VisionController ..> DeviceManager : 依赖(全局)
|
||||
TaskManager ..> DeviceManager : 获取图像/点云
|
||||
DeviceManager --> CameraCapture : 拥有
|
||||
class SlotOccupancyDetection {
|
||||
+execute()
|
||||
}
|
||||
|
||||
MainWindow ..> ConfigManager : 读写配置
|
||||
TaskManager ..> ConfigManager : 读取参数
|
||||
class PalletOffsetDetection {
|
||||
+execute()
|
||||
}
|
||||
|
||||
class BeamRackDeflectionDetection {
|
||||
+execute()
|
||||
}
|
||||
|
||||
class VisualInventoryDetection {
|
||||
+execute()
|
||||
}
|
||||
|
||||
MainWindow --> VisionController : 拥有并管理
|
||||
VisionController --> RedisCommunicator : 管理 (任务监听)
|
||||
VisionController --> TaskManager : 分发任务
|
||||
RedisCommunicator --> VisionController : 回调通知 (onTaskReceived)
|
||||
|
||||
VisionController ..> DeviceManager : 依赖(全局单例)
|
||||
TaskManager ..> DeviceManager : 获取图像数据 (Dependency)
|
||||
DeviceManager --> CameraCapture : 拥有 (深度相机)
|
||||
DeviceManager --> MvsMultiCameraCapture : 拥有 (2D相机)
|
||||
|
||||
TaskManager --> DetectionBase : 调用算法
|
||||
DetectionBase <|-- SlotOccupancyDetection : 继承
|
||||
DetectionBase <|-- PalletOffsetDetection : 继承
|
||||
DetectionBase <|-- BeamRackDeflectionDetection : 继承
|
||||
DetectionBase <|-- VisualInventoryDetection : 继承
|
||||
|
||||
MainWindow ..> ConfigManager : 读写配置 (Dependency)
|
||||
TaskManager ..> ConfigManager : 读取参数 (Dependency)
|
||||
MainWindow ..> DeviceManager : 图像显示 (Dependency)
|
||||
```
|
||||
|
||||
## 4. 关键模块详解
|
||||
|
||||
### 4.1 GUI与主入口 (MainWindow)
|
||||
- **职责**: 程序的主要入口,负责UI渲染、用户交互、参数配置及系统状态反馈。
|
||||
- **职责**: Qt6应用程序主窗口,负责UI渲染、用户交互、参数配置、实时预览及日志展示。
|
||||
- **调用关系**:
|
||||
- 初始化时创建 `VisionController`。
|
||||
- 通过 `QTimer` 定期从 `DeviceManager` 获取图像更新界面。
|
||||
- **Settings Tab**: 直接在 `MainWindow` 中实现,提供 "Beam/Rack Deflection", "Pallet Offset" 等算法参数配置界面。
|
||||
- 通过 `ConfigManager` 加载和保存配置项,包括ROI点坐标和各类阈值。
|
||||
- 程序启动时创建 `VisionController` 并初始化系统。
|
||||
- 通过 `QTimer` (30FPS) 定期从 `DeviceManager` 获取最新图像更新界面显示。
|
||||
- **实时预览**: 支持深度图伪彩色显示和彩色图显示,带自适应缩放。
|
||||
- **设置界面**: Settings Tab提供完整的算法参数配置,包括:
|
||||
- Beam/Rack Deflection: 横梁/立柱变形检测阈值和ROI配置
|
||||
- Pallet Offset: 托盘位置偏移检测参数
|
||||
- 系统配置: Redis连接参数、相机设置等
|
||||
- **日志显示**: 通过 `LogStreamBuf` 将 `std::cout/cerr` 重定向到GUI日志窗口。
|
||||
- 通过 `ConfigManager` 加载和保存 `config.json` 配置,支持热重载。
|
||||
|
||||
### 4.2 视觉控制器 (VisionController)
|
||||
- **职责**: 系统的"大脑",不依赖于GUI运行(设计上支持无头模式)。
|
||||
- **流程**:
|
||||
1. `initialize()`: 连接Redis。
|
||||
2. `start()`: 启动Redis监听线程。
|
||||
3. `onTaskReceived()`: 当Redis收到任务时,转发给 `TaskManager`。
|
||||
- **职责**: 系统的核心控制器,协调Redis通信和任务管理,支持无头模式运行。
|
||||
- **架构特点**:
|
||||
- 使用智能指针管理 `RedisCommunicator` 和 `TaskManager` 生命周期。
|
||||
- 支持跨数据库Redis操作:任务监听DB(输入)和结果写入DB(输出)。
|
||||
- 通过回调机制实现模块解耦,避免循环依赖。
|
||||
- **工作流程**:
|
||||
1. `initialize()`: 创建并初始化两个Redis连接器(任务DB和结果DB)。
|
||||
2. 初始化 `TaskManager`,传入Redis连接器用于结果写入和任务状态清空。
|
||||
3. `start()`: 启动Redis任务监听线程,设置任务接收回调。
|
||||
4. `onTaskReceived()`: 收到Redis任务时,通过回调转发给 `TaskManager::handleTask()`。
|
||||
|
||||
### 4.3 任务管理 (TaskManager)
|
||||
- **职责**: 解析Redis下发的JSON指令,选择合适的算法执行。
|
||||
- **职责**: 任务队列管理、算法调度、结果处理和跨线程执行的核心业务逻辑处理器。
|
||||
- **架构特点**:
|
||||
- **异步处理**: 使用任务队列 + 独立执行线程,避免阻塞Redis监听和GUI。
|
||||
- **相机智能分配**: 根据任务Flag自动选择合适的相机设备和数据类型。
|
||||
- **去重机制**: Flag 4视觉盘点支持连续扫描和QR码去重。
|
||||
- **状态管理**: 提供任务执行状态查询接口,支持外部监控。
|
||||
- **工作流**:
|
||||
1. 接收任务ID和参数。
|
||||
2. 从 `DeviceManager` 获取当前最新的一帧图像(深度+彩色)。
|
||||
3. **点云生成**: 对于需要3D数据的任务(Flag 2/3),调用 `DeviceManager::computePointCloud()` 生成点云。
|
||||
4. 根据任务类型实例化或调用相应的 `DetectionBase` 子类。
|
||||
5. 执行 `detect()`,传入图像和点云数据。
|
||||
6. 将结果打包为JSON,通过回调或直接通过 `RedisCommunicator` 返回。
|
||||
1. `handleTask()`: 接收Redis任务,加入线程安全的任务队列。
|
||||
2. `taskExecutionThreadFunc()`: 后台线程持续处理队列任务。
|
||||
3. **相机选择**: 根据Flag选择相机:
|
||||
- Flag 1: MVS 2D相机 (SN: DA8743029左/DA8742900右)
|
||||
- Flag 2/3: Percipio深度相机 (SN: 207000146458左/207000146703右)
|
||||
- Flag 4: MVS 2D相机 (SN: DA8789631) + 连续扫描循环
|
||||
4. **数据获取**: 调用 `DeviceManager` 获取图像,Flag 2/3时生成点云。
|
||||
5. **算法执行**: 调用对应的 `DetectionBase::execute()` 方法。
|
||||
6. **结果处理**: `processResult()` 格式化JSON、计算警告/报警、写入Redis结果DB。
|
||||
|
||||
### 4.4 设备管理 (DeviceManager)
|
||||
- **职责**: 硬件资源的全局访问点(单例模式)。
|
||||
- **封装**: 内部持有 `CameraCapture` 实例,确保相机资源全生命周期只被初始化一次。
|
||||
- **职责**: 多类型相机的统一管理接口,全系统硬件资源的单例访问点。
|
||||
- **架构特点**:
|
||||
- **双SDK支持**: 同时管理Percipio深度相机和MVS 2D相机。
|
||||
- **统一接口**: 提供一致的设备枚举、启动/停止和数据获取接口。
|
||||
- **线程安全**: 所有接口都是线程安全的,支持并发访问。
|
||||
- **资源管理**: 使用智能指针和RAII确保相机资源正确释放。
|
||||
- **功能**:
|
||||
- 提供线程安全的图像获取接口 `getLatestImages()`。
|
||||
- 提供点云计算接口 `computePointCloud()`,利用SDK内部参数生成高精度点云。
|
||||
- `initialize()`: 扫描并初始化所有类型的相机设备。
|
||||
- `getLatestImages()`: 统一的图像获取接口,支持深度图+彩色图。
|
||||
- `get2DCameraImage()`: 专门的2D相机图像获取接口。
|
||||
- `computePointCloud()`: 基于深度图和相机内参计算3D点云。
|
||||
- **相机索引映射**: 内部管理深度相机和2D相机的索引映射。
|
||||
|
||||
### 4.5 相机驱动 (CameraCapture)
|
||||
- **实现**: `ty_multi_camera_capture.cpp`
|
||||
- **机制**:
|
||||
- 为每个相机开启独立采集线程。
|
||||
- 维护内部帧缓冲区。
|
||||
- 将SDK的 `TYImage` 转换为 OpenCV `cv::Mat`。
|
||||
- **点云优化**: 内部集成 `TYMapDepthImageToPoint3d`,利用相机标定参数直接计算3D点云,消除畸变。
|
||||
### 4.5 相机驱动层
|
||||
- **Percipio深度相机** (`ty_multi_camera_capture.cpp`):
|
||||
- 基于图漾工业相机SDK,支持TY系列深度相机。
|
||||
- 为每个相机维护独立采集线程和帧缓冲区。
|
||||
- 支持深度图和彩色图同步采集,内部处理时间戳对齐。
|
||||
- **点云计算**: 集成 `TYMapDepthImageToPoint3d`,利用相机标定参数生成精确3D点云。
|
||||
- 自动畸变校正和深度数据滤波。
|
||||
|
||||
- **MVS 2D相机** (`mvs_multi_camera_capture.cpp`):
|
||||
- 基于海康工业相机SDK,支持MV系列2D相机。
|
||||
- 支持连续采集模式,内部缓冲区管理。
|
||||
- 提供高帧率彩色图像采集,适用于快速检测场景。
|
||||
- 支持相机序列号匹配,便于多相机场景下的设备识别。
|
||||
|
||||
### 4.6 配置管理 (ConfigManager)
|
||||
- **职责**: 管理 `config.json` 文件,集中管理系统配置。
|
||||
@@ -220,87 +333,181 @@ classDiagram
|
||||
## 5. 系统执行与数据流
|
||||
|
||||
### 5.1 初始化流程
|
||||
1. `main()` 启动 `QApplication`。
|
||||
2. `MainWindow` 构造:
|
||||
- 初始化UI。
|
||||
- **调用 `ConfigManager::getInstance().loadConfig()` 加载本地配置。**
|
||||
- 调用 `DeviceManager::getInstance().initialize()` 初始化相机。
|
||||
- 创建并初始化 `VisionController`(连接 Redis,但暂不启动监听)。
|
||||
- 启动定时器调用 `updateImage()` 刷新界面显示。
|
||||
3. 启动设备采集:调用 `DeviceManager::startAll()`。
|
||||
4. 设备启动成功后再调用 `VisionController::start()` 开启 Redis 监听,确保任务到来时设备已就绪。
|
||||
1. **程序启动**: `main.cpp` 创建Qt6应用程序,设置Fusion样式。
|
||||
2. **MainWindow构造**:
|
||||
- 初始化Qt6 UI界面(主窗口 + Settings选项卡)。
|
||||
- **配置加载**: 调用 `ConfigManager::loadConfig()` 从 `config.json` 加载系统配置。
|
||||
- **设备初始化**: 调用 `DeviceManager::initialize()` 扫描Percipio和MVS相机。
|
||||
- **控制器创建**: 实例化 `VisionController`,传入Redis配置参数。
|
||||
- **Redis初始化**: `VisionController::initialize()` 创建任务监听和结果写入的Redis连接器。
|
||||
- **定时器启动**: 启动30FPS的 `QTimer` 用于实时图像预览。
|
||||
3. **设备启动**: 调用 `DeviceManager::startAll()` 启动所有相机采集线程。
|
||||
4. **服务启动**: 调用 `VisionController::start()` 开启Redis监听,确保设备就绪后再接收任务。
|
||||
|
||||
### 5.2 自动任务执行流 (Redis触发)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Redis
|
||||
participant RC as RedisCommunicator
|
||||
participant WMS as WMS/外部系统
|
||||
participant Redis_Task as Redis_Task_DB
|
||||
participant RC_Task as RedisCommunicator_Task
|
||||
participant VC as VisionController
|
||||
participant TM as TaskManager
|
||||
participant DM as DeviceManager
|
||||
participant Algo as DetectionAlgorithm
|
||||
participant RC_Result as RedisCommunicator_Result
|
||||
participant Redis_Result as Redis_Result_DB
|
||||
|
||||
Redis->>RC: Publish Task (JSON)
|
||||
RC->>VC: onTaskReceived(data)
|
||||
VC->>TM: executeTask(data)
|
||||
WMS->>Redis_Task: SET vision_task_flag=1,side=left,time=xxx
|
||||
Redis_Task->>RC_Task: Key change notification
|
||||
RC_Task->>VC: onTaskReceived(task_data)
|
||||
VC->>TM: handleTask(task_data)
|
||||
|
||||
activate TM
|
||||
TM->>DM: getLatestImages()
|
||||
DM-->>TM: depth_img, color_img
|
||||
TM->>TM: Queue task (async)
|
||||
TM->>DM: getLatestImages() or get2DCameraImage()
|
||||
DM-->>TM: images (depth+color or 2D only)
|
||||
|
||||
alt Flag 2/3 (需要点云)
|
||||
TM->>DM: computePointCloud(depth)
|
||||
DM-->>TM: point_cloud (vector<Point3D>)
|
||||
end
|
||||
|
||||
TM->>Algo: execute(images, point_cloud)
|
||||
TM->>Algo: execute(images, point_cloud, ...)
|
||||
activate Algo
|
||||
Algo-->>TM: DetectionResult
|
||||
deactivate Algo
|
||||
|
||||
TM->>TM: processResult()
|
||||
TM->>RC: writeString(key, value)
|
||||
RC->>Redis: Set Key-Value
|
||||
TM->>TM: processResult() + addWarningAlarmSignals()
|
||||
TM->>RC_Result: writeDetectionResult(json_map)
|
||||
RC_Result->>Redis_Result: MSET key1=value1 key2=value2 ...
|
||||
|
||||
TM->>RC_Task: writeString(vision_task_flag, "0")
|
||||
TM->>RC_Task: writeString(vision_task_side, "")
|
||||
TM->>RC_Task: writeString(vision_task_time, "")
|
||||
RC_Task->>Redis_Task: Clear task flags
|
||||
deactivate TM
|
||||
```
|
||||
|
||||
1. **外部触发**: Redis 发布任务消息。
|
||||
2. **接收**: `RedisCommunicator` 监听到消息,触发回调。
|
||||
3. **调度**: `VisionController` 调用 `TaskManager::executeTask()`。
|
||||
4. **获取数据**: `TaskManager` 从 `DeviceManager` 获取最新帧。
|
||||
5. **算法处理**: 调用相应算法(如 `SlotOccupancyDetection::detect`)。
|
||||
6. **结果反馈**: 结果封装成JSON,通过 `RedisCommunicator` 写入Redis结果队列。
|
||||
7. **任务复位**: 结果写入完成后,将 `vision_task_flag` 置 `0`、`vision_task_side`/`vision_task_time` 置空,避免程序重启后被旧任务自动触发。
|
||||
1. **外部触发**: WMS系统通过Redis Task DB发布任务(设置 `vision_task_flag`、`side`、`time`)。
|
||||
2. **异步接收**: `RedisCommunicator_Task` 监听Task DB,触发回调给 `VisionController`。
|
||||
3. **任务队列**: `VisionController` 将任务加入 `TaskManager` 的线程安全队列。
|
||||
4. **后台执行**: `TaskManager` 执行线程处理任务,根据Flag选择相机和算法:
|
||||
- **Flag 1**: MVS 2D相机 → `SlotOccupancyDetection`
|
||||
- **Flag 2**: Percipio深度相机 → `PalletOffsetDetection` (带点云)
|
||||
- **Flag 3**: Percipio深度相机 → `BeamRackDeflectionDetection` (带点云)
|
||||
- **Flag 4**: MVS 2D相机 → `VisualInventoryDetection` (连续循环+QR识别)
|
||||
5. **智能数据获取**: 根据任务类型调用相应的 `DeviceManager` 接口。
|
||||
6. **结果处理**: 计算警告/报警信号,格式化JSON结果。
|
||||
7. **跨DB写入**: 结果写入Redis Result DB,任务状态清理写入Task DB。
|
||||
|
||||
### 5.3 实时监控执行流 (GUI)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Timer as QTimer
|
||||
participant Timer as QTimer (30FPS)
|
||||
participant MainWin as MainWindow
|
||||
participant DM as DeviceManager
|
||||
|
||||
loop 每33ms
|
||||
Timer->>MainWin: timeout()
|
||||
activate MainWin
|
||||
MainWin->>DM: getLatestImages()
|
||||
DM-->>MainWin: depth_img, color_img
|
||||
MainWin->>DM: getLatestImages(0) + get2DCameraImage(0)
|
||||
DM-->>MainWin: depth_img, color_img, mvs_img
|
||||
|
||||
MainWin->>MainWin: Convert to QImage
|
||||
MainWin->>MainWin: update QLabel
|
||||
alt 深度相机活跃
|
||||
MainWin->>MainWin: applyColorMap(depth_img) → 伪彩色显示
|
||||
else 2D相机活跃
|
||||
MainWin->>MainWin: 显示彩色图像
|
||||
end
|
||||
|
||||
MainWin->>MainWin: MatToQImage() + scaleToFit()
|
||||
MainWin->>MainWin: update QLabel displays
|
||||
deactivate MainWin
|
||||
end
|
||||
```
|
||||
|
||||
1. **定时刷新**: `MainWindow` 的 `QTimer` 触发 `updateImage()`。
|
||||
2. **数据拉取**: 调用 `DeviceManager::getInstance().getLatestImages()`。
|
||||
3. **渲染**: 将OpenCV Mat 转换为 QImage 并显示在 `QLabel` 上。
|
||||
- 深度图进行伪彩色处理以便观察。
|
||||
- 自适应窗口大小缩放。
|
||||
1. **高频刷新**: `QTimer` 以30FPS触发 `updateImage()`,确保流畅的实时预览。
|
||||
2. **多相机预览**: 同时获取深度相机和2D相机的最新图像,支持混合显示。
|
||||
3. **图像处理**: 深度图应用伪彩色映射,便于观察深度信息;彩色图直接显示。
|
||||
4. **自适应渲染**: OpenCV Mat转换为QImage,支持窗口大小自适应缩放。
|
||||
5. **状态同步**: 图像显示与任务执行异步进行,不影响检测性能。
|
||||
|
||||
## 6. 异常处理与日志
|
||||
- **日志**: 使用 `LogManager` 和 `spdlog` (如果集成) 或标准输出。
|
||||
- **重定向**: `LogStreamBuf` 将 `std::cout/cerr` 重定向到GUI的日志窗口,方便现场调试。
|
||||
- **错误恢复**: 相机掉线重连机制(在驱动层实现或计划中)。
|
||||
|
||||
## 6. 检测算法详解
|
||||
|
||||
### 6.1 算法框架 (DetectionBase)
|
||||
所有检测算法继承自 `DetectionBase` 抽象基类,提供统一的接口:
|
||||
```cpp
|
||||
virtual bool execute(const cv::Mat& depth_img,
|
||||
const cv::Mat& color_img,
|
||||
const std::string& side,
|
||||
DetectionResult& result,
|
||||
const std::vector<Point3D>* point_cloud = nullptr,
|
||||
double beam_length = 0.0) = 0;
|
||||
```
|
||||
|
||||
### 6.2 具体算法实现
|
||||
|
||||
#### Flag 1: 货位占用检测 (SlotOccupancyDetection)
|
||||
- **输入**: 2D彩色图像 (MVS相机)
|
||||
- **算法**: 基于图像处理的目标检测和位置判断
|
||||
- **输出**: 货位占用状态 (occupied/free)
|
||||
- **相机**: DA8743029 (左侧), DA8742900 (右侧)
|
||||
|
||||
#### Flag 2: 托盘位置偏移检测 (PalletOffsetDetection)
|
||||
- **输入**: 深度图 + 彩色图 + 3D点云
|
||||
- **算法**: 基于点云的3D位置计算,检测托盘相对于基准位置的偏移
|
||||
- **输出**: 左右偏移(mm)、前后偏移(mm)、插孔变形(mm)、旋转角度(°)
|
||||
- **相机**: 207000146458 (左侧), 207000146703 (右侧)
|
||||
- **警告/报警**: 基于阈值的四级判断 (正常/警告/报警)
|
||||
|
||||
#### Flag 3: 横梁/立柱变形检测 (BeamRackDeflectionDetection)
|
||||
- **输入**: 深度图 + 彩色图 + 3D点云
|
||||
- **算法**: 基于点云的结构变形测量
|
||||
- **输出**: 横梁弯曲量(mm)、立柱弯曲量(mm)
|
||||
- **相机**: 207000146458 (左侧), 207000146703 (右侧)
|
||||
- **警告/报警**: 基于阈值的四级判断
|
||||
|
||||
#### Flag 4: 视觉盘点检测 (VisualInventoryDetection)
|
||||
- **输入**: 2D彩色图像 (MVS相机)
|
||||
- **算法**: 基于Halcon的QR码识别,支持连续扫描和去重
|
||||
- **特殊机制**: 循环执行直到收到Flag 5停止信号,支持实时去重
|
||||
- **输出**: JSON格式的条码列表 `{"side": ["BOX001", "BOX002", ...]}`
|
||||
- **相机**: DA8789631 (专用盘点相机)
|
||||
|
||||
#### Flag 5: 盘点停止信号
|
||||
- **功能**: 停止Flag 4的连续扫描循环
|
||||
- **无算法执行**: 仅作为控制信号
|
||||
|
||||
### 6.3 相机分配策略
|
||||
系统根据任务Flag智能选择相机:
|
||||
|
||||
| Flag | 相机类型 | 序列号 | 位置 | 数据类型 |
|
||||
|------|---------|--------|------|----------|
|
||||
| 1 | MVS 2D | DA8743029 / DA8742900 | 左/右 | 彩色图 |
|
||||
| 2 | Percipio深度 | 207000146458 / 207000146703 | 左/右 | 深度+彩色+点云 |
|
||||
| 3 | Percipio深度 | 207000146458 / 207000146703 | 左/右 | 深度+彩色+点云 |
|
||||
| 4 | MVS 2D | DA8789631 | 盘点专用 | 彩色图 |
|
||||
|
||||
## 7. 编译与构建
|
||||
- **工具**: CMake
|
||||
- **依赖**: Qt6, OpenCV 4.x, Percipio SDK, (Redis库通常被封装或作为源码包含)
|
||||
- **平台**: Windows (MSVC/MinGW)
|
||||
- **构建系统**: CMake 3.10+
|
||||
- **编程语言**: C++17
|
||||
- **目标平台**: Windows 10/11 (MSVC 2022 v143)
|
||||
- **主要依赖**:
|
||||
- **Qt6**: Widgets组件 (GUI框架)
|
||||
- **OpenCV 4.x**: 图像处理和计算机视觉
|
||||
- **Open3D 0.17+**: 3D点云处理
|
||||
- **Percipio SDK**: 图漾工业相机驱动
|
||||
- **MVS SDK**: 海康工业相机驱动
|
||||
- **Redis C++ Client**: hiredis + redis-plus-plus (Redis通信)
|
||||
- **可选依赖**: Halcon (用于QR码识别,在Flag 4中使用)
|
||||
- **构建流程**: 标准CMake流程,支持Release/Debug配置
|
||||
|
||||
---
|
||||
|
||||
*文档更新时间: 2025-01-06*
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
# 支持 MSVC
|
||||
# 注意:配置 CMake 时请选择合适的生成器(例如 "Visual Studio 17 2022" )
|
||||
# 注意:配置 CMake 时请选择合适的生成器(例如 "Visual Studio 17 2022" 或 "Ninja")
|
||||
|
||||
project(image_capture LANGUAGES CXX)
|
||||
|
||||
if(NOT MSVC)
|
||||
message(FATAL_ERROR "This project requires MSVC (Visual Studio) compiler. Please use a Visual Studio generator (e.g., -G \"Visual Studio 17 2022\").")
|
||||
# 检查是否使用 MSVC 风格的编译器
|
||||
if(NOT (MSVC OR CMAKE_CXX_COMPILER_ID STREQUAL "MSVC"))
|
||||
message(FATAL_ERROR "This project requires MSVC (Visual Studio) compiler. Please use Ninja with MSVC or Visual Studio generator.")
|
||||
endif()
|
||||
|
||||
# ============================================================================
|
||||
@@ -106,7 +107,10 @@ target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/third_party/mvs/Libraries/win64/MvCameraControl.lib
|
||||
)
|
||||
|
||||
target_link_directories(${PROJECT_NAME} PRIVATE ${OpenCV_LIB_DIRS})
|
||||
target_link_directories(${PROJECT_NAME} PRIVATE
|
||||
${OpenCV_LIB_DIRS}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/third_party/percipio/lib/win/x64
|
||||
)
|
||||
|
||||
if(Open3D_RUNTIME_DLLS)
|
||||
foreach(DLL_FILE ${Open3D_RUNTIME_DLLS})
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <Eigen/Dense>
|
||||
|
||||
#include "../../../common_types.h"
|
||||
|
||||
Reference in New Issue
Block a user