LuxVideoDet 整体架构

跨平台工业视频检测系统的整体架构梳理——单一视频源分发、多算法并行推理流水线、可插拔算法框架(描述符 + 状态机)、多推理引擎体系与三宿主形态的完整设计

🎥 LuxVideoDet 整体架构

跨平台工业视频检测系统 — 单一视频源 + 多算法并行推理的通用框架 技术栈:C# / .NET 8 · OpenCvSharp · ONNX Runtime / OpenVINO · Avalonia UI · ASP.NET Core


1. 系统定位

LuxVideoDet 是一个面向工业制造现场的视频行为检测与流程合规判定平台。它从一路视频源(RTSP 摄像头 / 本地视频文件 / MQTT 推流 / 本地摄像头)读取画面,同时并行运行一个或多个「检测算法」,对画面中的目标进行识别、对作业流程进行状态机判定,并在命中违规/异常时触发多渠道告警(Webhook / 企业微信 / 语音播报 / PLC),同时落盘 NG 截图、录像与生产统计。

核心设计原则:

  1. 一源多用:视频流只拉取一次,分发给 N 个算法各自独立推理,避免带宽与解码浪费。
  2. 算法可插拔:每个算法是一个「描述符 + 算法类」的组合,通过反射自动注册,新增算法无需改动框架代码。
  3. 三宿主形态:同一套 Core 引擎由 Desktop(Avalonia 桌面端)、Web(ASP.NET Core 控制台)、Headless(无头服务)三种前端复用。
  4. 状态机驱动:每个流程类算法内部用显式状态机描述「上一步完成 → 检测下一步」的语义,而非散落的 if/else。

2. 解决方案结构

解决方案 LuxVideoDet.sln 由 6 个项目 + 1 个测试分组构成:

项目 类型 职责
LuxVideoDet.Core 类库 核心引擎:算法框架、推理引擎、视频源、通知、配置、存储、区域、渲染。所有业务逻辑所在,不依赖任何 UI。
LuxVideoDet.Desktop Avalonia 可执行 桌面客户端(MVVM + AXAML),配置编辑、实时预览、区域绘制、日志查看、NG 回放。
LuxVideoDet.Web ASP.NET Core 可执行 Web 控制台:REST API + MJPEG 视频流 + 静态页面,远程配置与监控。
LuxVideoDet.Headless 控制台可执行 无头检测服务:命令行启动、Serilog 日志、Ctrl+C 优雅停机,用于服务器/盒子部署。
LuxVideoDet.Localization 类库 UI 本地化:AppLocalizer + UiKeys,支持 zh-CN / en-US / vi-VN 三语。
tests/LuxVideoDet.Tests 测试 单元测试 + 集成测试(含各算法定向测试子项目)。

依赖方向:Desktop / Web / Headless → Core + Localization,三者互不依赖,共享同一套 Core 引擎。


3. Core 分层架构

LuxVideoDet.Core 内部按职责划分为以下命名空间(目录):

目录 职责 关键类型
Algorithm/ 算法框架(接口、基类、工厂、结果模型、UI 动作) IDetectionAlgorithm、IAlgorithmDescriptor、DetectionAlgorithmBase、DetectionAlgorithmFactory、DetectionResult
Algorithm/Implementations/ 21+ 个具体算法(每个一个目录) 见 §5 算法清单
Algorithm/Pipeline/ 多算法并行流水线 MultiAlgorithmPipeline、AlgorithmWorker、PipelineFactory
Inference/ 推理引擎抽象与实现 IInferenceEngine、OnnxInferenceEngine、OpenVinoInferenceEngine、RemoteHttpInferenceEngine、MqttInferenceEngine
Inference/Postprocessors/ 模型输出后处理(按任务类型) DetectionPostprocessor、ObbPostprocessor、PosePostprocessor、SegmentationPostprocessor、ClassificationPostprocessor、PostprocessorFactory
VideoSource/ 视频源抽象与实现 IVideoSource、RtspSource、CameraSource、LocalVideoSource、MqttVideoSource、VideoSourceFactory
Notification/ 告警通知渠道 INotificationService、WebhookNotificationService、WeChatNotificationService、SpeakerNotificationService、PlcNotificationService、NotificationServiceFactory
Configuration/ 配置加载、存储、校验 ConfigurationService、JsonConfigurationStore、SingleFileConfigurationStore、DetectionConfigurationValidator
Configuration/Models/ 配置数据模型 DetectionConfiguration、AlgorithmConfig、VideoSourceConfig、InferenceConfig、RegionConfig、NotificationConfig
Region/ 检测区域(多边形 ROI)管理 Region、RegionManager、RegionRenderer
Aoi/ AOI 检测器(可插拔视觉算子) IAoiDetector、AoiDetectorBase、AoiDetectorFactory、HandLandmark、UDet
Storage/ 截图/录像/统计落盘 StorageManager、RecordingManager、VideoRecorder、ProductionStatisticsStore、CrossPlatformMediaWriter
Rendering/ 标注渲染 TaskAwareDetectionRenderer、ClassificationOverlayRenderer
Common/ 基础类型 Frame(Mat 封装)
Utils/ 工具 ChineseTextRenderer(帧内中文)、FpsCounter、CooldownTimer、RollingMinute*Stats(滑动窗口统计)、PythonNetRuntimeHost
Logging/ · Extensions/ 日志与 DI 扩展 AddLuxVideoDetCore() 服务注册入口

4. 运行时数据流

一次检测会话(Session)从启动到产出的完整链路如下:

关键机制:

  • 单帧多投:BroadcastLoopAsync 是唯一的取帧线程,读取一帧后分发给所有 AlgorithmWorker。单算法时直接传原始帧(零克隆),多算法时前 N-1 个收到克隆、最后一个收到原始帧,避免引用冲突。
  • 异步解耦:每个 Worker 拥有独立的 Queue<Frame> 与处理线程,以各自节奏推理,互不阻塞;队列满时丢弃最旧帧(RTSP 式跳帧),保证实时预览不堆积。
  • 本地视频节流:LocalVideoSource 按标称帧率节流,防止文件被以最大速度解码导致播放加速。
  • 录像解耦:录像帧由 IngestFrameForRecording(Mat) 在取帧线程全速喂入环形缓冲,与算法推理速度无关,保证慢推理(如远程 HTTP)下 NG 视频帧仍充足。
  • 多算法结果合成:以「处理帧数最多」的算法画面为底图,叠加其他算法的检测框与区域轮廓,避免快慢算法并行时画面「跳回过去」。

5. 算法开发框架

5.1 三层抽象

  • IAlgorithmDescriptor:算法的「元数据 + 工厂」。框架启动时通过反射扫描程序集中所有实现自动注册,无需手动改工厂代码。它声明了算法类型键、显示名、默认类别、所需区域、可配置的「其他参数」(DefaultOtherArgs)与 AOI 使用声明(AlgorithmAoiUsages)。
  • DetectionAlgorithmBase:模板方法基类。子类只需实现 ProcessDetections(核心判定逻辑);可选覆写 GetDetectionClassBindings 完成「业务键 ↔ 模型类名 ↔ ClassId」映射,基类会在配色前统一处理类别绑定。
  • IDetectionAlgorithm:运行实例接口,Process(frame) 是每帧入口。

5.2 每个算法的标准文件结构

一个算法目录通常包含以下协作文件(以 E9_2F_NXT_PDA_Feeding_Monitor 为例):

文件 职责
*Algorithm.cs 算法主体:ProcessDetections 每帧算标志位、驱动状态机、构造结果/通知
*Descriptor.cs 描述符:TypeKey/DisplayName/类别/区域/参数定义
*StateMachine.cs 状态机:状态转移、超时判定、错误处理
*Context.cs 上下文:跨帧状态、信号锁存、每帧输入的中间标志
*WorkState.cs 状态枚举
*DetectionBindings.cs 类别绑定:业务键 ↔ 模型类名
*Regions.cs 区域定义(多边形 ROI 的默认形状/颜色)
*UiActions.cs UI 动作(可选,如「确认错误」「手动置 NG」按钮)
*PipelineChecklistRenderer.cs 清单渲染(可选,帧内步骤清单)
*CameraFlagReporter.cs 摄像头 Flag 上报(可选,与 SimpleX 摄像头标志位联动)

5.3 状态机模式

流程类算法采用「检测下一步」的状态机语义:

  • 每个状态对应一个实际步骤;TransitionTo 进入新状态时重置 CurrentStateEnterTime 计时起点。
  • 每帧 ProcessDetections 先计算各信号的确认值(经 ConfirmWithFrames 连续 N 帧抗抖动),再交给状态机 Update() 判定推进或超时。
  • 步骤超时:每个中间步骤可配独立的 *_timeout_seconds 参数,超时即报「操作错误」并进入 ERROR 状态,等待恢复或手动确认。

5.4 算法清单

算法目录 说明
Example 示例模板(新算法开发起点)
E1_2F_Material_Distribution E1_2F 物料配送
E9_2F_NXT_PDA_Feeding_Monitor E9_2F NXT PDA 上料监测(备料→刷备料台→刷料架)
ExpansionRoomPdDieBarcodeStation 扩展间 PD 晶粒条码站(11 步状态机)
GenericPipeline 通用可配置流水线(声明式步骤/区域条件)
MidFrameScanLoose / MidFrameScanStrict / MidFrameScanLooseHand 中框扫描(宽松 / 严格 / 含手部)
NtxSmt NXT SMT 上料(备料→扫卷码→扫料架)
OvenDet 烤箱检测(门/绿灯/手/料/料车/鼠标/扫描枪)
OVEN 烤箱(另一套实现)
TwoOven 双烤箱(OvenDet 变体,料车放空用 Empty_Cart 类)
PackagingBehavior 包装行为
ProneSleepingDetection 趴桌睡觉检测(YOLO-pose 关键点三层判定)
ReelFoilBagPackagingStation 卷膜袋包装站
SafetyPpeWork 安全 PPE 着装
SmtFeeder / SmtFeeders SMT 供料器(单/多,TypeKey 与目录分开)
U7Lite U7 精简
UCS / UCSHand UCS / UCS 手部

6. 推理引擎体系

6.1 引擎抽象

所有推理引擎实现 IInferenceEngine 接口,通过 InferenceEngineFactory 按配置实例化:

引擎 实现 说明
ONNX Runtime OnnxInferenceEngine 默认引擎,支持 CPU / CUDA(GPU)
OpenVINO OpenVinoInferenceEngine Intel 硬件加速
远程 HTTP RemoteHttpInferenceEngine 将图像发往远程推理服务,支持按类置信度过滤
MQTT MqttInferenceEngine 经 MQTT 主题接收远端推理结果

设备注册表 InferenceDeviceRegistry 提供 CPU / CUDA / QNN / CoreML 等设备描述。

6.2 模型输出布局

DetectionOutputLayout 自动区分两种导出格式:

  • 标准格式:[1, 4+nc, anchors](YOLO 原始输出,需本框架做 NMS)。
  • end2end 格式:[1, max_det, 6](导出时已内嵌 NMS),按 dim2==6 && dim1>6 自动识别,不重复 NMS。

预处理:letterbox + BGR→RGB + /255 + NCHW。后处理按任务类型由 PostprocessorFactory 分发(检测/旋转框/姿态/分割/分类),检测类无 DFL。

6.3 类别名解析

  • 模型类别名从 ONNX 元数据 metadata_props["names"] 读取。
  • ClassIdsResolution 将「业务键 ↔ 模型类名」绑定解析为实际 ClassId;配置 classes 与 metadata 不一致时引擎告警并按模型顺序强制解析。
  • ClassIdAutoMapper 支持类别名自动映射。

7. 通知体系

告警由算法在 DetectionResult 中携带,经 NotificationServiceFactory 分发到配置的渠道:

渠道 实现 载体
Webhook WebhookNotificationService HTTP POST JSON,支持自定义正文模板
企业微信 WeChatNotificationService 固定格式消息(含图片/视频路径)
语音播报 SpeakerNotificationService TTS 或固定音频文件
PLC PlcNotificationService Modbus TCP 写寄存器数字量

正文归属原则:NotificationMessage.Text(自定义模板)由算法自行构造,渠道不硬编码算法文案。当算法未提供 Text 时,Webhook 回退到通用默认格式 【标题】\n时间\n级别\n内容(标题优先级:title_content 参数 → NotificationTitle → AlgorithmType → “检测告警”)。企业微信 / 喇叭 / PLC 各自使用固定格式,不读 Text。


8. 配置系统

  • 存储:JsonConfigurationStore(多文件)或 SingleFileConfigurationStore(单文件 configs.json)。
  • 服务:ConfigurationService 提供 ListAsync / LoadAsync / SaveAsync / ValidateAsync / ImportAsync 等。
  • 序列化:JSON 键统一 camelCase(ConfigurationJsonOptions.ForConfigurationFile + JsonNamingPolicy.CamelCase),代码中禁止使用 JsonPropertyName 特性。
  • 校验:DetectionConfigurationValidator 在启动/保存时校验区域完整性、算法与模型类别匹配等,缺失必要区域抛 MissingAlgorithmRegionsException。
  • 数据模型:DetectionConfiguration(顶层,含 Name/Id/Enabled/VideoSource/Algorithms[])→ AlgorithmConfig(含 AlgorithmType/Inference/Regions/Notification/Args)→ InferenceConfig(模型路径/设备/阈值/类别)。

9. 存储与统计

组件 职责
StorageManager 统一管理截图/录像保存目录与生命周期
RecordingManager + VideoRecorder NG 录像:环形缓冲 + 事件触发导出
FileStorageService 跨平台文件写入(含回退目录)
ProductionStatisticsStore 生产统计:按「日期 + 配置名」分桶,跨程序重启不归零;算法通过实现 IProductionStatisticsProvider 覆写 SetStatisticsCounters 上报 OK/NG
CrossPlatformMediaWriter 跨平台媒体编码(JPEG/视频封装)

10. 三种宿主形态

宿主 启动入口 适用场景
Desktop App.axaml → MainWindow 现场调试、配置编辑、实时画面预览、区域绘制、NG 回放
Web Program.cs(Kestrel,默认端口 5050) 远程监控:REST API(配置/会话/统计/NG 回放)+ MJPEG 视频流
Headless Program.cs(控制台) 服务器/盒子部署:命令行筛选配置、Serilog 日志、优雅停机

三者均通过 AddLuxVideoDetCore() 复用同一套 DI 注册与 Core 引擎,仅前端呈现层不同。


11. 关键设计决策(约定)

  1. JSON 键 camelCase,禁止 JsonPropertyName 特性。
  2. UI 文案本地化:一律 _appLocalizer.GetString(UiKeys.Xxx),禁止 AXAML 硬编码中文。
  3. 增量功能禁止引入新 NuGet 包。
  4. 「其他参数」UI 自动驱动:IAlgorithmDescriptor.DefaultOtherArgs 声明参数即出现在编辑器,无需改 ViewModel/AXAML。
  5. 清单渲染统一缩放:s = frame.Width / 2560.0,新增清单渲染器须带同样缩放。
  6. 通知正文归算法所有:渠道不硬编码算法文案。
  7. NG 录像与推理解耦:录像帧全速喂入环形缓冲,不在 Process 内喂。
  8. 类别名严格一致:模型 metadata 类别名须与代码类名精确匹配(大小写/空格/拼写)。
  9. 测试用 --filter 定向运行:存在预存错误时跳过,避免全量测试被旧错误阻塞。
  10. 模型选型以实测为准:不同训练轮次/窄化重训模型能力差异大,不能仅凭类别名判断。

文档基于代码库 LuxVideoDet.sln 结构梳理,随架构演进持续更新。

comments powered by Disqus
使用 Hugo 构建😊 主题 Stack 由 Jimmy 设计