feat(v1): compose temporal fall event pipeline
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
| 桌面 UI | PyQt5 | 已验证 | 现有 GUI 已使用,适合实时画面、弹窗和信号线程。 |
|
||||
| 视频与图像 | OpenCV(含 FFmpeg) | 已验证 | 读取 RTSP、绘制叠加层和保存截图。 |
|
||||
| Pose 推理 | Ultralytics 8.3.205 + YOLOv8 Pose | 已验证 | 当前 `best.pt` 能加载为 17 点 person Pose 模型。 |
|
||||
| 跟踪 | Ultralytics ByteTrack | 已定 | 为时序事件提供人员 ID;实现前需用现场录像验证 ID 稳定性。 |
|
||||
| 跟踪 | 轻量归一化框中心最近邻 | 已实现基线 | 为时序事件提供人员 ID;固定机位、稀疏人员适用;多人交叉可能换 ID,待有回归素材后再评估 ByteTrack 或全局匹配。 |
|
||||
| 事件逻辑 | 纯 Python 模块 + pytest | 已定 | 与 GUI 解耦,便于正反例录像回归。 |
|
||||
| 本地配置 | JSON 示例文件 + 未跟踪的 `config.local.json` | 已定 | 不把 RTSP 凭证提交仓库。 |
|
||||
| 日志与截图 | JSONL + PNG/JPG 文件 | 已定 | 无数据库的可审计演示证据。 |
|
||||
|
||||
+14
-5
@@ -13,6 +13,8 @@ Pose 推理适配器(person box + 17 keypoints)
|
||||
↓
|
||||
姿态质量门控 + 倒地证据提取
|
||||
↓
|
||||
倒地领域规则(突发下移 → 水平姿态)
|
||||
↓
|
||||
每人摔倒事件状态机
|
||||
↓
|
||||
确认事件
|
||||
@@ -34,7 +36,9 @@ V1 的同一数据流既可接 RTSP,也可回放本地录像。V2 复用同一
|
||||
| Pose 适配器 | `v1/pose.py` | 校验锁定模型的 SHA-256、pose/person/17×3 契约,统一返回 box、关键点、置信度 | 跟踪、摔倒业务结论 |
|
||||
| 跟踪 | `v1/tracking.py` | 以归一化 box 中心距离为连续人员输出稳定 `track_id` | 根据姿态报警 |
|
||||
| 质量与证据 | `v1/evidence.py` | 拒绝缺失肩/髋/膝/踝的姿态,计算水平姿态和躯干归一化下移证据 | GUI 状态、确认事件 |
|
||||
| 状态机 | `v1/fall_state.py` | 管理每个 ID 的 NORMAL、SUSPECT、CONFIRMED、RECOVERING,并在首次确认时产生一个带确认延迟的事件 | 播放声音或存文件 |
|
||||
| 倒地领域规则 | `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` | 对确认事件去重、播放声音、保存截图、写日志 | 推理或事件计算 |
|
||||
| PyQt UI | `v1/gui.py` | 渲染帧、骨架、状态、设置和弹窗 | 直接读 RTSP 或写判定规则 |
|
||||
| 回归工具 | `v1/tests/` 与 `v1/scripts/` | 回放录像、断言事件和延迟 | 生产 UI |
|
||||
@@ -43,7 +47,7 @@ V1 的同一数据流既可接 RTSP,也可回放本地录像。V2 复用同一
|
||||
|
||||
PyQt 主窗口只包含实时监控和设置两个顶部 Tab。实时监控 Tab 保持视频画面优先;设置 Tab 不能直接调用视频源、Pose 或状态机。
|
||||
|
||||
设置页面产生的是已校验的草稿配置。用户点击开始监控时,应用创建不可变的运行配置快照与配置版本,并将该快照传给视频源、Pose、证据和状态机。运行期间编辑设置不会修改该快照;保存后的草稿在下一次开始监控时才会成为新的运行配置。FallEvent 继续记录 config_version,使截图和 JSONL 可以追溯到实际阈值。
|
||||
设置页面产生的是已校验的草稿配置。用户点击开始监控时,应用创建不可变的运行配置快照与配置版本,并将该快照传给视频源、Pose、证据和状态机。运行期间编辑设置不会修改该快照;保存后的草稿在下一次开始监控时才会成为新的运行配置。`AppConfig.runtime_config_version` 从非敏感来源 ID、锁定模型与事件参数计算,不含 RTSP 地址或凭证;`FallEvent` 继续记录它,使截图和 JSONL 可以追溯到实际阈值。
|
||||
|
||||
真实 RTSP 凭证仍只由环境变量或未跟踪本地配置提供。UI 只显示环境变量是否就绪,不能回显或记录具体值。
|
||||
|
||||
@@ -53,10 +57,10 @@ PyQt 主窗口只包含实时监控和设置两个顶部 Tab。实时监控 Tab
|
||||
|
||||
```text
|
||||
NORMAL
|
||||
└─ 高质量证据显示快速下移或倒地姿态 → SUSPECT
|
||||
└─ 高质量证据显示快速下移,且在 suspect 窗口内转为水平姿态 → SUSPECT
|
||||
SUSPECT
|
||||
├─ 倒地证据在配置时间窗内持续 → CONFIRMED(产生一次 FallEvent)
|
||||
└─ 证据消失 → NORMAL
|
||||
├─ 水平倒地证据在 confirm 时间窗内持续 → CONFIRMED(产生一次 FallEvent)
|
||||
└─ 缺失、低质量或非倒地证据 → NORMAL
|
||||
CONFIRMED
|
||||
└─ 经配置冷却与恢复稳定站立 → RECOVERING
|
||||
RECOVERING
|
||||
@@ -66,6 +70,8 @@ RECOVERING
|
||||
|
||||
状态机只以秒和单调时间为准,不以固定帧数为准。这样 15 FPS、30 FPS、丢帧或录像回放速度变化不会改变 1–3 秒业务目标。
|
||||
|
||||
录像源和实时流使用不同的计时策略:回放优先容器 PTS、再回退到帧序号/FPS;实时流以成功读帧时的 `time.monotonic()` 计时。任意非连接帧、人员缺帧或低质量姿态都会向该人员输入拒绝证据,不能被计入连续倒地确认时间。
|
||||
|
||||
## 数据和文件
|
||||
|
||||
| 数据 | 位置 | 规则 |
|
||||
@@ -86,6 +92,7 @@ RECOVERING
|
||||
| 单帧误报 | 当前 `demo/` 任一规则命中即报警 | V1 用质量门控、跟踪和时序状态机;反例录像必测。 |
|
||||
| 俯视关键点不稳 | 1.6 米俯视、遮挡或远距离会影响膝踝 | 全身可见前提、ROI、质量拒绝和现场回归;必要时再采集数据。 |
|
||||
| RTSP 断流 | 网络抖动或摄像头重连 | 视频源显式状态、指数退避重连、断流不报警。 |
|
||||
| 多人交叉换 ID | 当前 V1 使用贪心中心点匹配,未做全局最优匹配 | 固定机位、稀疏人员演示中记录为已知限制;多人密集场景在有回归素材后再评估升级。 |
|
||||
| 同一事件重复报警 | CONFIRMED 状态持续多帧 | 每个事件 ID 仅执行一次报警副作用,恢复后才允许新事件。 |
|
||||
| Go 行为漂移 | ONNX 预后处理与 Python 不同 | 导出后跑同一录像,比较关键点、事件数量、确认时间和截图。 |
|
||||
| 模型误解 | Pose 指标被误当摔倒指标 | 文案仅说明姿态模型;事件级指标单独记录。 |
|
||||
@@ -111,7 +118,9 @@ v1/
|
||||
├── pose.py
|
||||
├── tracking.py
|
||||
├── evidence.py
|
||||
├── fall_policy.py
|
||||
├── fall_state.py
|
||||
├── pipeline.py
|
||||
├── alerts.py
|
||||
├── models/
|
||||
├── scripts/
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
| T-103 | 实现 Pose 适配器与模型来源校验 | T-102 | 输出 person box、17 点和置信度;错误模型或哈希不符时给出明确错误。 | DONE |
|
||||
| T-104 | 实现人员跟踪与姿态质量门控 | T-103 | 连续人员维持 ID;低质量、缺失膝踝或空帧不会产生倒地候选。 | DONE |
|
||||
| T-105 | 实现按 ID 的时序摔倒状态机 | T-104 | 正例在配置秒数内确认;坐下、弯腰、短时低姿态回到 NORMAL;事件副作用只触发一次。 | DONE |
|
||||
| T-106 | 装配事件管线与固化事件契约 | T-105 | Pose → 跟踪 → 质量/几何证据 → 领域规则 → 按 ID 状态机可回放运行;缺失/低质量证据会中断确认;全部公开事件参数生效;事件可追溯运行配置版本;录像 EOF 不会重放。 | DOING |
|
||||
| T-106 | 装配事件管线与固化事件契约 | T-105 | Pose → 跟踪 → 质量/几何证据 → 领域规则 → 按 ID 状态机可回放运行;缺失/低质量证据会中断确认;全部公开事件参数生效;事件可追溯运行配置版本;录像 EOF 不会重放。 | DONE |
|
||||
|
||||
## Phase 2 · V1 演示闭环
|
||||
|
||||
|
||||
+5
-3
@@ -32,7 +32,7 @@
|
||||
```
|
||||
|
||||
- `rtsp_url_env` 必填;应用从同名环境变量读取真实 URL。
|
||||
- 数值是待现场录像校准的默认值;每个值必须真正进入事件逻辑。示例中的全零 SHA-256 只占位配置形状,T-103 必须以受控模型的真实哈希替换并验证后才能启动推理。
|
||||
- 数值是待现场录像校准的默认值;每个值必须真正进入事件逻辑:`keypoint_confidence_threshold` 决定姿态质量门槛;`suspect_window_seconds` 限制快速下移到水平姿态的最大间隔;`confirm_window_seconds` 是水平倒地候选需持续的确认时间;`recovery_window_seconds` 是恢复姿态需持续的时间;`cooldown_seconds` 是确认事件后允许开始恢复判断前的最短等待时间。示例中的全零 SHA-256 只占位配置形状,T-103 必须以受控模型的真实哈希替换并验证后才能启动推理。
|
||||
- 缺少环境变量、模型不存在或哈希不符时,应用显示配置错误,不启动监控。
|
||||
|
||||
## 核心数据
|
||||
@@ -66,6 +66,7 @@ PoseEvidence = {
|
||||
FallEvent = {
|
||||
event_id: string,
|
||||
track_id: string,
|
||||
config_version: string,
|
||||
suspected_at_monotonic: float,
|
||||
confirmed_at_monotonic: float,
|
||||
latency_seconds: float,
|
||||
@@ -73,7 +74,7 @@ FallEvent = {
|
||||
}
|
||||
```
|
||||
|
||||
`FallEvent` 是 T-105 状态机的纯内存确认事件,只在状态首次进入 `CONFIRMED` 时创建一次。连续帧更新 UI 状态,但不重复创建事件。T-202 的 `alerts` 会在不改变事件幂等语义的前提下,为截图/JSONL 记录补充来源、UTC 时间、证据和配置版本。
|
||||
`FallEvent` 是状态机的纯内存确认事件,只在状态首次进入 `CONFIRMED` 时创建一次。连续帧更新 UI 状态,但不重复创建事件。`config_version` 是由运行配置快照计算的非敏感版本标识;T-202 的 `alerts` 会在不改变事件幂等语义的前提下,为截图/JSONL 记录补充来源、UTC 时间和证据。
|
||||
|
||||
`PersonPose` 是 T-103 的纯模型输出,不带人员 ID;T-104 的跟踪模块产生 `TrackedPersonPose` 后,才允许事件证据按人员连续积累。
|
||||
|
||||
@@ -88,7 +89,8 @@ FramePacket = {
|
||||
}
|
||||
```
|
||||
|
||||
- 录像优先使用容器时间戳;首帧时间戳无效或倒退时,回退为帧序号/FPS,保证回放时间单调。
|
||||
- `SourceMode.REPLAY` 的录像优先使用容器时间戳;首帧时间戳无效或倒退时,回退为帧序号/FPS,保证回放时间单调;到达 EOF 后保持 EOF,不重放。
|
||||
- `SourceMode.STREAM` 的实时流以成功读帧时的单调时钟计时;读取失败进入有界指数退避重连,不使用 `CAP_PROP_POS_MSEC` 作为事件时间。
|
||||
- `retrying`、`error`、`eof` 和 `closed` 都没有图像,且绝不伪造人员、姿态或摔倒事件。
|
||||
- 可重连来源以有界指数退避重新打开;断流不推进状态机的证据时间。
|
||||
|
||||
|
||||
@@ -5,17 +5,17 @@
|
||||
## 当前快照
|
||||
|
||||
- 日期:2026-07-21
|
||||
- 阶段:V1 事件引擎基线已建立;T-106(事件管线与事件契约)进行中。
|
||||
- 阶段:V1 事件管线与事件契约已建立;T-106 已验收,等待 T-201。
|
||||
- 已验证环境:Windows PowerShell;Python 3.8.10;Ultralytics 8.3.205;PyQt5 可导入。
|
||||
- 旧生产基线:`demo/main.py`、`demo/fall_detection_gui.py`、`demo/detect_fall.py`、`demo/best.pt`。
|
||||
- V1 代码:已建立安全配置、视频源、Pose、跟踪、质量/几何证据,以及 `v1/fall_state.py` 的按 ID 四态事件机;Pose/跟踪/证据到状态机的事件管线与事件契约正在由 T-106 装配。PyQt GUI、声音、弹窗、截图、JSONL 和真实 RTSP 接入尚未实现。
|
||||
- V1 代码:已建立安全配置、显式 Replay/Stream 视频源、Pose、轻量跟踪、质量/几何证据、倒地领域规则、按 ID 四态事件机及 `v1/pipeline.py` 事件管线;运行事件带非敏感 `config_version`,缺帧/低质量/断流会中断证据确认。PyQt GUI、声音、弹窗、截图、JSONL 和真实 RTSP 接入尚未实现。
|
||||
- V2 代码:`v2/` 目录存在但尚无实现。
|
||||
- 非代码设计工件:docs/ui/silver-pose-ui-ux-spec.md、docs/ui/2026-07-20-html-prototype-plan.md、docs/ui/silver-pose-v1-prototype.html 与 docs/ui/silver-pose-v2-prototype.html 已建立。v2 HTML 是符合正式浅色 Windows 规范的当前视觉参考:浅灰蓝底、白色卡片,红色只表示确认摔倒、其弹窗和事件证据;文件名中的 v2 只表示原型设计修订,不能理解为 Go V2 实现已开始。v1 HTML 保留为历史深色对照。两者均使用顶部双 Tab、设置草稿与状态交互,且画面、事件和时间都是模拟数据,不连接真实摄像头、模型或网络,也不改变 Phase 1 任务顺序。
|
||||
- 测试:`python -m compileall -q demo` 已通过;`python -m pytest v1/tests -v` 当前有 20 项配置/视频源/Pose/跟踪/证据/状态机测试并已通过。`demo/1.mp4` 的首两帧回放时间戳已验证为 0.000000 与 0.033333 秒,首帧 Pose smoke 得到 2 名人员、每人 17 点。`init.ps1` 会检查运行时依赖、编译旧基线并运行 V1 测试,但不会安装软件包。
|
||||
- 测试:`python -m compileall -q demo` 已通过;`python -m pytest v1/tests -v` 当前有 30 项配置、视频源、Pose、跟踪、证据、领域规则、状态机和管线测试并已通过。`demo/1.mp4` 的首两帧回放时间戳已验证为 0.000000 与 0.033333 秒;T-106 的真实模型/录像 smoke 在首帧得到 2 名已分析人员、第二帧得到 0 名人员且未创建事件,这只验证管线可运行,不表示摔倒识别准确率。`init.ps1` 会检查运行时依赖、编译旧基线并运行 V1 测试,但不会安装软件包。
|
||||
- 模型:`demo/best.pt` 可加载为 YOLO Pose,类别 `person`,`kpt_shape=[17, 3]`;与 `D:\PythonP\fall_detection\best.pt` 哈希一致。
|
||||
- 当前标准启动:`./init.ps1`。
|
||||
- 当前标准验证:`python -m compileall -q demo`。
|
||||
- 当前 blocker:T-106 尚未完成 Pose/跟踪/证据到状态机的事件管线、缺失证据中断语义与运行配置版本契约;回归录像及事件标签尚未创建;真实海康 RTSP 流尚未接入。
|
||||
- 当前 blocker:尚无带标签的正反例回归录像及事件标签;真实海康 RTSP 流尚未接入,实时流单调计时策略尚待 T-203 在现场验证;PyQt 与本地报警闭环尚未实现。
|
||||
|
||||
全局环境的 `pip check` 存在其他项目的包冲突,因此它不是 Silver Pose 的验收命令。`init.ps1` 只检查本项目实际导入的 OpenCV、NumPy、Ultralytics 与 PyQt5,并在命令非零退出时失败。
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
## 任务状态
|
||||
|
||||
- 已完成:T-000(Harness 文档与旧基线快照)、T-101(V1 安全配置基线)、T-102(视频源与录像回放)、T-103(Pose 适配器与模型校验)、T-104(跟踪与姿态质量证据)、T-105(按 ID 时序状态机)。
|
||||
- 正在进行:T-106(装配事件管线与固化事件契约)。
|
||||
- 下一个可领取:无;完成 T-106 后为 T-201。
|
||||
- 正在进行:无。
|
||||
- 下一个可领取:T-201(顶部双 Tab 的 PyQt 监控与设置界面)。
|
||||
|
||||
## 当前可运行内容
|
||||
|
||||
|
||||
Reference in New Issue
Block a user