Files
material_box_storage_detect…/docs/project_architecture.md
2026-01-06 10:49:45 +08:00

22 KiB
Raw Blame History

项目架构及调用关系文档

1. 系统概述

本系统是一个基于立体视觉的仓库巡检图像采集与处理系统。它集成了图漾(Percipio)工业深度相机SDK和海康(MVS)工业2D相机SDK进行多相机图像采集使用OpenCV进行图像处理Qt6作为用户界面框架并通过Redis与外部系统如WMS仓库管理系统、机器人控制系统进行通信和任务调度。

系统主要功能包括:

  • 多相机统一管理同时支持深度相机Percipio和2D相机MVS的数据采集
  • 实时图像预览与状态监控GUI界面实时显示相机图像支持深度图伪彩色显示
  • 基于Redis的任务触发与结果上报:支持跨数据库的任务监听和结果写入
  • 多种检测算法
    • 货位占用检测Flag 1基于2D图像的目标检测
    • 托盘位置偏移检测Flag 2基于深度数据的3D位置计算
    • 横梁/立柱变形检测Flag 3基于深度数据的结构变形测量
    • 视觉盘点检测Flag 4基于Halcon的QR码识别支持连续扫描和去重
    • 盘点停止信号Flag 5停止Flag 4的连续扫描循环
  • 智能相机分配:根据任务类型自动选择合适的相机设备
  • 系统配置管理与日志记录:支持参数持久化、实时日志显示和错误处理

2. 目录结构说明

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/           # 算法基类与结果定义
    │   │   ├── detection_base.h/cpp        # 检测算法基类
    │   │   └── detection_result.h/cpp      # 检测结果数据结构
    │   ├── detections/     # 具体检测算法实现
    │   │   ├── slot_occupancy/             # 货位占用检测
    │   │   ├── pallet_offset/              # 托盘偏移检测
    │   │   ├── beam_rack_deflection/       # 横梁立柱变形检测
    │   │   └── visual_inventory/           # 视觉盘点检测
    │   └── utils/          # 图像处理工具
    ├── camera/             # 相机驱动层
    │   ├── ty_multi_camera_capture.h/cpp   # 图漾(Percipio)深度相机封装
    │   └── mvs_multi_camera_capture.h/cpp  # 海康(MVS)2D相机封装
    ├── common/             # 通用设施
    │   ├── config_manager.h/cpp    # 配置管理单例 (JSON配置加载/保存)
    │   ├── log_manager.h/cpp       # 日志管理 (spdlog封装)
    │   └── log_streambuf.h         # std::cout重定向到GUI
    ├── device/             # 硬件设备管理
    │   └── device_manager.h/cpp    # 相机设备单例管理 (统一设备接口)
    ├── gui/                # 用户界面 (Qt6)
    │   └── mainwindow.h/cpp/ui     # 主窗口实现 (实时预览+设置界面)
    ├── redis/              # 通信模块
    │   └── redis_communicator.h/cpp # Redis客户端封装 (跨数据库支持)
    ├── task/               # 任务调度
    │   └── task_manager.h/cpp      # 任务管理器 (队列+线程+算法调度)
    ├── vision/             # 系统控制
    │   └── vision_controller.h/cpp # 顶层控制器 (Redis+Task协调)
    ├── common_types.h      # 通用数据类型 (Point3D, CameraIntrinsics等)
    ├── tools/              # 工具程序目录
    │   ├── calibration_tool/        # 相机标定工具
    │   ├── slot_algo_tuner/         # 货位算法调参工具
    │   └── intrinsic_dumper/        # 相机内参导出工具
    └── main.cpp            # 程序入口

3. 核心架构设计

系统采用分层架构设计,各模块职责明确:

  • 展示层 (Presentation): MainWindow 负责Qt6界面显示、实时相机预览、手动控制、参数配置及日志展示。
  • 控制层 (Control): VisionController 作为系统级控制器,负责服务的启动/停止协调Redis通信和任务管理使用回调机制解耦模块间依赖。
  • 业务逻辑层 (Business Logic): TaskManager 负责任务队列管理、算法调度和结果处理;DeviceManager 作为硬件资源的统一访问点(单例模式)。
  • 算法层 (Algorithm): 提供具体的视觉检测功能,所有算法继承自 DetectionBase,支持统一的 execute() 接口。
  • 基础设施层 (Infrastructure): CameraCapture 封装底层相机SDK调用RedisCommunicator 处理跨数据库通信,ConfigManager 管理系统配置。

系统分层架构图

graph TB
    subgraph Presentation ["展示层 (Presentation)"]
        direction TB
        GUI[MainWindow]
    end

    subgraph Control ["控制层 (Control)"]
        VC[VisionController]
    end

    subgraph Business ["业务逻辑层 (Business Logic)"]
        direction TB
        TM[TaskManager]
        DM[DeviceManager]
    end

    subgraph Algorithm ["算法层 (Algorithm)"]
        direction TB
        DB[DetectionBase]
        Det[Concrete Detections<br/>(Slot, Beam, etc.)]
    end

    subgraph Infrastructure ["基础设施层 (Infrastructure)"]
        direction TB
        Cam[CameraCapture]
        Redis[RedisCommunicator]
        Conf[ConfigManager]
    end

    %% 层级调用关系
    GUI --> VC
    VC --> TM
    VC --> Redis
    
    TM --> DM
    TM --> DB
    DB <|-- Det
    
    DM --> Cam
    DM --> MVS[MvsMultiCameraCapture]
    
    %% 跨层辅助调用
    GUI -.-> Conf
    TM -.-> Conf
    
    style Presentation fill:#e1f5fe,stroke:#01579b
    style Control fill:#e8f5e9,stroke:#2e7d32
    style Business fill:#fff3e0,stroke:#ef6c00
    style Algorithm fill:#f3e5f5,stroke:#7b1fa2
    style Infrastructure fill:#eceff1,stroke:#455a64

系统类图

classDiagram
    class MainWindow {
        +VisionController visionController_
        +QTimer imageTimer_
        +updateImage()
        +onSaveSettings()
        +showLogMessage()
    }

    class VisionController {
        +shared_ptr<RedisCommunicator> redis_comm_
        +shared_ptr<RedisCommunicator> redis_result_comm_
        +shared_ptr<TaskManager> task_manager_
        +initialize()
        +start()
        +stop()
        -onTaskReceived()
    }

    class DeviceManager {
        <<Singleton>>
        +shared_ptr<CameraCapture> capture_
        +unique_ptr<MvsMultiCameraCapture> mvs_cameras_
        +initialize()
        +startAll()
        +getLatestImages()
        +computePointCloud()
        +get2DCameraImage()
    }

    class TaskManager {
        +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()
        +startListening()
        +writeString()
        +setTaskCallback()
    }

    class ConfigManager {
        <<Singleton>>
        +json config_data_
        +loadConfig()
        +saveConfig()
        +getValue()
    }

    class DetectionBase {
        <<Abstract>>
        +execute(depth, color, side, result, point_cloud, beam_length)
    }

    class SlotOccupancyDetection {
        +execute()
    }

    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)

  • 职责: Qt6应用程序主窗口负责UI渲染、用户交互、参数配置、实时预览及日志展示。
  • 调用关系:
    • 程序启动时创建 VisionController 并初始化系统。
    • 通过 QTimer (30FPS) 定期从 DeviceManager 获取最新图像更新界面显示。
    • 实时预览: 支持深度图伪彩色显示和彩色图显示,带自适应缩放。
    • 设置界面: Settings Tab提供完整的算法参数配置包括
      • Beam/Rack Deflection: 横梁/立柱变形检测阈值和ROI配置
      • Pallet Offset: 托盘位置偏移检测参数
      • 系统配置: Redis连接参数、相机设置等
    • 日志显示: 通过 LogStreamBufstd::cout/cerr 重定向到GUI日志窗口。
    • 通过 ConfigManager 加载和保存 config.json 配置,支持热重载。

4.2 视觉控制器 (VisionController)

  • 职责: 系统的核心控制器协调Redis通信和任务管理支持无头模式运行。
  • 架构特点:
    • 使用智能指针管理 RedisCommunicatorTaskManager 生命周期。
    • 支持跨数据库Redis操作任务监听DB(输入)和结果写入DB(输出)。
    • 通过回调机制实现模块解耦,避免循环依赖。
  • 工作流程:
    1. initialize(): 创建并初始化两个Redis连接器任务DB和结果DB
    2. 初始化 TaskManager传入Redis连接器用于结果写入和任务状态清空。
    3. start(): 启动Redis任务监听线程设置任务接收回调。
    4. onTaskReceived(): 收到Redis任务时通过回调转发给 TaskManager::handleTask()

4.3 任务管理 (TaskManager)

  • 职责: 任务队列管理、算法调度、结果处理和跨线程执行的核心业务逻辑处理器。
  • 架构特点:
    • 异步处理: 使用任务队列 + 独立执行线程避免阻塞Redis监听和GUI。
    • 相机智能分配: 根据任务Flag自动选择合适的相机设备和数据类型。
    • 去重机制: Flag 4视觉盘点支持连续扫描和QR码去重。
    • 状态管理: 提供任务执行状态查询接口,支持外部监控。
  • 工作流:
    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)

  • 职责: 多类型相机的统一管理接口,全系统硬件资源的单例访问点。
  • 架构特点:
    • 双SDK支持: 同时管理Percipio深度相机和MVS 2D相机。
    • 统一接口: 提供一致的设备枚举、启动/停止和数据获取接口。
    • 线程安全: 所有接口都是线程安全的,支持并发访问。
    • 资源管理: 使用智能指针和RAII确保相机资源正确释放。
  • 功能:
    • initialize(): 扫描并初始化所有类型的相机设备。
    • getLatestImages(): 统一的图像获取接口,支持深度图+彩色图。
    • get2DCameraImage(): 专门的2D相机图像获取接口。
    • computePointCloud(): 基于深度图和相机内参计算3D点云。
    • 相机索引映射: 内部管理深度相机和2D相机的索引映射。

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 文件,集中管理系统配置。
  • 管理内容:
    • Redis 连接信息。
    • 算法阈值 (Beam/Rack, Pallet Offset 等)。
    • ROI (Region of Interest) 坐标点。
    • 系统通用参数 (最小/最大深度等)。
  • 特性: 单例模式,支持热加载(部分参数)和持久化保存。程序启动时由 MainWindow 加载确保算法使用持久化的用户设置。GUI中的Settings Tab直接操作此模块。

5. 系统执行与数据流

5.1 初始化流程

  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触发)

sequenceDiagram
    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

    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->>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, ...)
    activate Algo
    Algo-->>TM: DetectionResult
    deactivate Algo

    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. 外部触发: WMS系统通过Redis Task DB发布任务设置 vision_task_flagsidetime)。
  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)

sequenceDiagram
    participant Timer as QTimer (30FPS)
    participant MainWin as MainWindow
    participant DM as DeviceManager

    loop 每33ms
        Timer->>MainWin: timeout()
        activate MainWin
        MainWin->>DM: getLatestImages(0) + get2DCameraImage(0)
        DM-->>MainWin: depth_img, color_img, mvs_img

        alt 深度相机活跃
            MainWin->>MainWin: applyColorMap(depth_img) → 伪彩色显示
        else 2D相机活跃
            MainWin->>MainWin: 显示彩色图像
        end

        MainWin->>MainWin: MatToQImage() + scaleToFit()
        MainWin->>MainWin: update QLabel displays
        deactivate MainWin
    end
  1. 高频刷新: QTimer 以30FPS触发 updateImage(),确保流畅的实时预览。
  2. 多相机预览: 同时获取深度相机和2D相机的最新图像支持混合显示。
  3. 图像处理: 深度图应用伪彩色映射,便于观察深度信息;彩色图直接显示。
  4. 自适应渲染: OpenCV Mat转换为QImage支持窗口大小自适应缩放。
  5. 状态同步: 图像显示与任务执行异步进行,不影响检测性能。

6. 异常处理与日志

  • 日志: 使用 LogManagerspdlog (如果集成) 或标准输出。
  • 重定向: LogStreamBufstd::cout/cerr 重定向到GUI的日志窗口方便现场调试。
  • 错误恢复: 相机掉线重连机制(在驱动层实现或计划中)。

6. 检测算法详解

6.1 算法框架 (DetectionBase)

所有检测算法继承自 DetectionBase 抽象基类,提供统一的接口:

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 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