154 lines
10 KiB
Markdown
154 lines
10 KiB
Markdown
# 架构设计
|
||
|
||
## 系统结构
|
||
|
||
```text
|
||
海康 RTSP 流(凭证仅在本机)
|
||
↓
|
||
RTSP 采集器 / 帧时间戳
|
||
↓
|
||
Pose 推理适配器(person box + 17 keypoints)
|
||
↓
|
||
人员跟踪器(track_id)
|
||
↓
|
||
姿态质量门控 + 倒地证据提取
|
||
↓
|
||
倒地领域规则(突发下移 → 水平姿态)
|
||
↓
|
||
每人摔倒事件状态机
|
||
↓
|
||
确认事件
|
||
├── PyQt 实时画面:红框、骨架、状态
|
||
├── 本地声音与弹窗
|
||
├── 标注截图
|
||
└── JSONL 事件日志
|
||
```
|
||
|
||
V1 的同一数据流既可接 RTSP,也可回放本地录像。V2 复用同一配置、事件字段和录像集,但将 Pose 推理替换为 ONNX 适配器;不得改变事件语义。
|
||
|
||
T-302/T-303 的实现路线为:受控 `ffmpeg.exe` 负责解码为 BGR 原始帧,Go 预处理模块以 114 补边、双线性缩放与 RGB/CHW 生成固定 `1×3×640×640` tensor,`onnxruntime_go` 以显式 DLL 路径执行 Pose ONNX,随后由 NMS、17 点解析、坐标还原、轻量跟踪、质量/几何证据、倒地策略和四态状态机生成不变的 `FallEvent`。Windows Walk UI 只接收已完成渲染的数据。解码、推理和事件计算都不得在 UI 消息线程运行;UI 只显示最新完成帧和事件状态。
|
||
|
||
## 模块职责
|
||
|
||
| 模块 | V1 位置 | 职责 | 不负责 |
|
||
| --- | --- | --- | --- |
|
||
| 应用入口 | `v1/app.py` | 装配配置、窗口、线程和依赖 | 推理细节、事件判定 |
|
||
| 配置 | `v1/config.py` | 解析示例和本地配置,校验非敏感字段 | 保存真实凭证 |
|
||
| 摄像头接入 | `v1/camera.py` | 由 host/port/channel/账号/密码构建 RTSP URL(凭证百分号编码),并对流做一次有界连接测试抓帧 | 事件判定、持久化 |
|
||
| 视频源 | `v1/video_source.py` | 打开、读取、重连 RTSP 或录像;输出帧、单调回放时间戳和显式来源状态 | Pose、报警 |
|
||
| Pose 适配器 | `v1/pose.py` | 校验锁定模型的 SHA-256、pose/person/17×3 契约,统一返回 box、关键点、置信度 | 跟踪、摔倒业务结论 |
|
||
| 跟踪 | `v1/tracking.py` | 以归一化 box 中心距离为连续人员输出稳定 `track_id` | 根据姿态报警 |
|
||
| 质量与证据 | `v1/evidence.py` | 拒绝缺失肩/髋/膝/踝的姿态,计算水平姿态和躯干归一化下移证据 | GUI 状态、确认事件 |
|
||
| 倒地领域规则 | `v1/fall_policy.py` | 将每人连续的 `PoseEvidence` 映射为状态机 `Evidence`;要求快速下移后在 suspect 窗口内转为水平,确认后才接受恢复证据 | GUI、报警副作用、模型推理 |
|
||
| 事件管线 | `v1/pipeline.py` | 按一帧顺序装配 Pose、跟踪、质量/证据、领域规则和状态机;对缺帧、低质量和断流输入拒绝证据 | 读取视频、加载模型、GUI、报警副作用 |
|
||
| 状态机 | `v1/fall_state.py` | 管理每个 ID 的 NORMAL、SUSPECT、CONFIRMED、RECOVERING,并在首次确认时产生带确认延迟和 `config_version` 的事件 | 播放声音或存文件 |
|
||
| 报警工件 | `v1/alerts.py` | 对确认事件去重、播放声音、保存截图、写日志 | 推理或事件计算 |
|
||
| 视图模型 | `v1/view_model.py` | 由 `FrameAnalysis` 构建 Qt-free 监控视图状态(连接文案、状态语义色、骨架段、人员叠加)与设置草稿(运行/已保存/草稿三份隔离,下次启动生效) | Qt 渲染、事件判定、读 RTSP |
|
||
| PyQt UI | `v1/gui.py` | 渲染帧、骨架、状态、设置和弹窗,绑定视图模型 | 直接读 RTSP 或写判定规则 |
|
||
| 应用装配 | `v1/app.py` | 装配配置、Pose、管线线程与窗口;`FrameWorker` 只发出已判定的 `FrameAnalysis` | 事件判定、渲染细节 |
|
||
| 回归工具 | `v1/tests/` 与 `v1/scripts/` | 回放录像、断言事件和延迟 | 生产 UI |
|
||
|
||
V2 对应模块的当前落实与 T-304 目标如下:
|
||
|
||
| 模块 | V2 目标位置 | 职责 | 不负责 |
|
||
| --- | --- | --- | --- |
|
||
| 回放解码器 | `v2/cmd/regression` | 用受控 FFmpeg 顺序读取 BGR 帧,供本机录像回归 | RTSP 重连、UI 绘制 |
|
||
| 运行配置 | `v2/internal/config` | 校验公开 JSON、仅从环境变量解析 RTSP URL、生成非敏感配置版本 | 保存或显示 URL、账号、密码 |
|
||
| 实时视频源 | `v2/internal/source` | 用 FFprobe 获取尺寸/FPS,以 FFmpeg 输出 BGR 帧;有界重连、取消、来源状态和单槽最新帧投递 | ONNX、事件判定、UI 绘制;错误状态不得含 URL |
|
||
| ONNX Pose | `v2/internal/pose` | 114 letterbox、RGB/CHW、NMS、关键点及坐标还原 | 人员 ID、摔倒结论 |
|
||
| 事件引擎 | `v2/internal/fall` | 复现 V1 的跟踪、证据、四态状态机和 `FallEvent` | 视频解码、声音、文件 |
|
||
| 画面与证据 | `v2/internal/render`、`v2/internal/alert` | 叠加人员骨架/状态,红色仅表示 CONFIRMED;按事件 ID 保存一次 PNG 和 JSONL | 读取 RTSP、重跑事件规则、直接操作 Walk 控件 |
|
||
| 实时装配 | `v2/internal/monitor` | 在后台串联帧→Pose→事件→渲染→证据;画面只保留最新完成帧,确认事件经独立队列送 UI | 直接操作 Walk 控件、保存凭证 |
|
||
| Windows UI | `v2/internal/ui` | **Gio**(替代 Walk)浅色顶部“监控/设置”Tab、渲染最新帧和已计算状态;后台更新经 `Invalidate` 上屏、UI 线程只渲染;确认事件播放声音并自绘弹窗 | 直接读 RTSP、执行 ONNX 或事件规则 |
|
||
| 应用装配 | `v2/cmd/silver-pose`(T-304) | 管理 worker 生命周期、取消、最新帧投递和依赖注入 | 重写领域规则 |
|
||
|
||
## UI 导航与配置生效生命周期
|
||
|
||
PyQt 主窗口只包含实时监控和设置两个顶部 Tab。实时监控 Tab 保持视频画面优先;设置 Tab 不能直接调用视频源、Pose 或状态机。
|
||
|
||
设置页面产生的是已校验的草稿配置。用户点击开始监控时,应用创建不可变的运行配置快照与配置版本,并将该快照传给视频源、Pose、证据和状态机。运行期间编辑设置不会修改该快照;保存后的草稿在下一次开始监控时才会成为新的运行配置。`AppConfig.runtime_config_version` 从非敏感来源 ID、锁定模型与事件参数计算,不含 RTSP 地址或凭证;`FallEvent` 继续记录它,使截图和 JSONL 可以追溯到实际阈值。
|
||
|
||
真实 RTSP 凭证仍只由环境变量或未跟踪本地配置提供。UI 只显示环境变量是否就绪,不能回显或记录具体值。
|
||
|
||
## 状态模型
|
||
|
||
每个 `track_id` 独立维护状态:
|
||
|
||
```text
|
||
NORMAL
|
||
└─ 高质量证据显示快速下移,且在 suspect 窗口内转为水平姿态 → SUSPECT
|
||
SUSPECT
|
||
├─ 水平倒地证据在 confirm 时间窗内持续 → CONFIRMED(产生一次 FallEvent)
|
||
└─ 缺失、低质量或非倒地证据 → NORMAL
|
||
CONFIRMED
|
||
└─ 经配置冷却与恢复稳定站立 → RECOVERING
|
||
RECOVERING
|
||
├─ 恢复证据持续 → NORMAL
|
||
└─ 再次倒地证据 → SUSPECT
|
||
```
|
||
|
||
状态机只以秒和单调时间为准,不以固定帧数为准。这样 15 FPS、30 FPS、丢帧或录像回放速度变化不会改变 1–3 秒业务目标。
|
||
|
||
录像源和实时流使用不同的计时策略:回放优先容器 PTS、再回退到帧序号/FPS;实时流以成功读帧时的 `time.monotonic()` 计时。任意非连接帧、人员缺帧或低质量姿态都会向该人员输入拒绝证据,不能被计入连续倒地确认时间。
|
||
|
||
## 数据和文件
|
||
|
||
| 数据 | 位置 | 规则 |
|
||
| --- | --- | --- |
|
||
| 公共配置示例 | `v1/config.example.json` | 可提交;只含 `rtsp_url_env`,不含 URL 或密码。 |
|
||
| 本地配置 | `v1/config.local.json` | 忽略提交;可引用环境变量。 |
|
||
| V1 模型 | `v1/models/best.pt` 或受控相对路径 | 记录 SHA-256、来源与验证日期。 |
|
||
| V2 模型 | `v2/assets/best.onnx` | 从锁定 V1 权重导出,记录导出命令、输入尺寸和 SHA-256。 |
|
||
| 事件截图 | `artifacts/events/YYYYMMDD/` | 文件名含事件 ID,不含客户姓名或 RTSP 地址。 |
|
||
| 事件日志 | `artifacts/events/YYYYMMDD/events.jsonl` | 一行一个 `FallEvent`。 |
|
||
| 回归录像 | `testdata/videos/` | 只保存经同意的演示素材;外部客户视频不提交。 |
|
||
| 回归标签 | `testdata/expected_events.json` | 每段录像的期望事件、非事件和最大延迟。 |
|
||
|
||
## 关键风险与应对
|
||
|
||
| 风险 | 原因 | 应对 |
|
||
| --- | --- | --- |
|
||
| 单帧误报 | 当前 `demo/` 任一规则命中即报警 | V1 用质量门控、跟踪和时序状态机;反例录像必测。 |
|
||
| 俯视关键点不稳 | 1.6 米俯视、遮挡或远距离会影响膝踝 | 全身可见前提、ROI、质量拒绝和现场回归;必要时再采集数据。 |
|
||
| RTSP 断流 | 网络抖动或摄像头重连 | 视频源显式状态、指数退避重连、断流不报警。 |
|
||
| 多人交叉换 ID | 当前 V1 使用贪心中心点匹配,未做全局最优匹配 | 固定机位、稀疏人员演示中记录为已知限制;多人密集场景在有回归素材后再评估升级。 |
|
||
| 域外倒地漏检 | Pose 模型可能在室外斜视、字幕遮挡或与部署机位差异很大的倒地画面中失去人体/关键点 | `demo/1.mp4` 已出现该现象;不以降低事件阈值伪造修复。仅用符合固定俯视大厅/走廊、全身大部分可见边界的经同意录像做验收;若业务要覆盖域外画面,另立模型数据适配任务。 |
|
||
| 同一事件重复报警 | CONFIRMED 状态持续多帧 | 每个事件 ID 仅执行一次报警副作用,恢复后才允许新事件。 |
|
||
| Go 行为漂移 | ONNX 预后处理与 Python 不同 | 导出后跑同一录像,比较关键点、事件数量、确认时间和截图。 |
|
||
| 模型误解 | Pose 指标被误当摔倒指标 | 文案仅说明姿态模型;事件级指标单独记录。 |
|
||
|
||
## 开发顺序
|
||
|
||
1. 冻结 `demo/`、创建 V1 配置和可验证骨架。
|
||
2. 用本地录像打通 Pose、质量门控、跟踪和状态机。
|
||
3. 加入 PyQt 实时画面、RTSP 重连、报警和截图。
|
||
4. 用正反例录像和现场流完成 V1 事件级验收。
|
||
5. 锁定模型并导出 ONNX,完成 Python/ONNX 一致性。
|
||
6. 由 Go V2 重复相同行为后,再作为客户演示部署版。
|
||
|
||
## 目标目录
|
||
|
||
```text
|
||
v1/
|
||
├── app.py
|
||
├── config.py
|
||
├── config.example.json
|
||
├── gui.py
|
||
├── video_source.py
|
||
├── pose.py
|
||
├── tracking.py
|
||
├── evidence.py
|
||
├── fall_policy.py
|
||
├── fall_state.py
|
||
├── pipeline.py
|
||
├── alerts.py
|
||
├── models/
|
||
├── scripts/
|
||
└── tests/
|
||
v2/
|
||
├── cmd/silver-pose/
|
||
├── internal/
|
||
├── assets/
|
||
└── testdata/
|
||
```
|