feat(v1): add replayable video source
This commit is contained in:
@@ -30,7 +30,7 @@ V1 的同一数据流既可接 RTSP,也可回放本地录像。V2 复用同一
|
||||
| --- | --- | --- | --- |
|
||||
| 应用入口 | `v1/app.py` | 装配配置、窗口、线程和依赖 | 推理细节、事件判定 |
|
||||
| 配置 | `v1/config.py` | 解析示例和本地配置,校验非敏感字段 | 保存真实凭证 |
|
||||
| 视频源 | `v1/video_source.py` | 打开、读取、重连 RTSP 或录像,附带时间戳 | Pose、报警 |
|
||||
| 视频源 | `v1/video_source.py` | 打开、读取、重连 RTSP 或录像;输出帧、单调回放时间戳和显式来源状态 | Pose、报警 |
|
||||
| Pose 适配器 | `v1/pose.py` | 统一返回 box、关键点、置信度 | 跟踪、摔倒业务结论 |
|
||||
| 跟踪 | `v1/tracking.py` | 为连续人员输出 `track_id` | 根据姿态报警 |
|
||||
| 质量与证据 | `v1/evidence.py` | 过滤低质量点,计算水平姿态、下移和持续性证据 | GUI 状态 |
|
||||
@@ -85,7 +85,7 @@ RECOVERING
|
||||
| --- | --- | --- |
|
||||
| 单帧误报 | 当前 `demo/` 任一规则命中即报警 | V1 用质量门控、跟踪和时序状态机;反例录像必测。 |
|
||||
| 俯视关键点不稳 | 1.6 米俯视、遮挡或远距离会影响膝踝 | 全身可见前提、ROI、质量拒绝和现场回归;必要时再采集数据。 |
|
||||
| RTSP 断流 | 网络抖动或摄像头重连 | 视频源显式状态、退避重连、断流不报警。 |
|
||||
| RTSP 断流 | 网络抖动或摄像头重连 | 视频源显式状态、指数退避重连、断流不报警。 |
|
||||
| 同一事件重复报警 | CONFIRMED 状态持续多帧 | 每个事件 ID 仅执行一次报警副作用,恢复后才允许新事件。 |
|
||||
| Go 行为漂移 | ONNX 预后处理与 Python 不同 | 导出后跑同一录像,比较关键点、事件数量、确认时间和截图。 |
|
||||
| 模型误解 | Pose 指标被误当摔倒指标 | 文案仅说明姿态模型;事件级指标单独记录。 |
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
| ID | 任务 | 依赖 | 验收要点 | 状态 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| T-101 | 创建 V1 包、依赖清单、示例配置和忽略规则 | T-000 | `v1/` 可导入;真实 RTSP 凭证被拒绝提交;`pytest` 能运行。 | DONE |
|
||||
| T-102 | 实现可重连的视频源与录像回放适配器 | T-101 | 有效本地录像可按时间戳产帧;无效源进入连接错误状态且不崩溃。 | DOING |
|
||||
| T-102 | 实现可重连的视频源与录像回放适配器 | T-101 | 有效本地录像可按时间戳产帧;无效源进入连接错误状态且不崩溃。 | DONE |
|
||||
| T-103 | 实现 Pose 适配器与模型来源校验 | T-102 | 输出 person box、17 点和置信度;错误模型或哈希不符时给出明确错误。 | TODO |
|
||||
| T-104 | 实现人员跟踪与姿态质量门控 | T-103 | 连续人员维持 ID;低质量、缺失膝踝或空帧不会产生倒地候选。 | TODO |
|
||||
| T-105 | 实现按 ID 的时序摔倒状态机 | T-104 | 正例在配置秒数内确认;坐下、弯腰、短时低姿态回到 NORMAL;事件副作用只触发一次。 | TODO |
|
||||
|
||||
@@ -132,7 +132,7 @@ git commit -m "feat(v1): add secure configuration baseline"
|
||||
- Create: `v1/video_source.py`
|
||||
- Create: `v1/tests/test_video_source.py`
|
||||
|
||||
- [ ] **Step 1: Write replay and broken-source tests**
|
||||
- [x] **Step 1: Write replay and broken-source tests**
|
||||
|
||||
```python
|
||||
def test_file_source_emits_monotonic_timestamps(sample_video):
|
||||
@@ -146,12 +146,12 @@ def test_missing_source_returns_error_state(tmp_path):
|
||||
assert source.read().status == SourceStatus.ERROR
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Run tests to verify they fail**
|
||||
- [x] **Step 2: Run tests to verify they fail**
|
||||
|
||||
Run: `python -m pytest v1/tests/test_video_source.py -v`
|
||||
Expected: FAIL because `VideoSource` and `SourceStatus` do not exist.
|
||||
|
||||
- [ ] **Step 3: Implement the source contract**
|
||||
- [x] **Step 3: Implement the source contract**
|
||||
|
||||
```python
|
||||
from typing import Optional
|
||||
@@ -172,12 +172,12 @@ class FramePacket:
|
||||
|
||||
`read()` returns an error packet for failures; it never emits a synthetic person or fall event. For RTSP, reconnect with bounded backoff from configuration.
|
||||
|
||||
- [ ] **Step 4: Run tests**
|
||||
- [x] **Step 4: Run tests**
|
||||
|
||||
Run: `python -m pytest v1/tests/test_video_source.py -v`
|
||||
Expected: PASS.
|
||||
|
||||
- [ ] **Step 5: Commit**
|
||||
- [x] **Step 5: Commit**
|
||||
|
||||
```powershell
|
||||
git add v1/video_source.py v1/tests/test_video_source.py docs progress.md
|
||||
|
||||
+15
@@ -71,6 +71,21 @@ FallEvent = {
|
||||
|
||||
`FallEvent` 只在状态首次进入 `CONFIRMED` 时创建一次。连续帧更新 UI 状态,但不重复创建事件。
|
||||
|
||||
## 视频来源帧合约
|
||||
|
||||
```text
|
||||
FramePacket = {
|
||||
image: ndarray | null,
|
||||
timestamp_monotonic: float,
|
||||
status: "connected" | "retrying" | "error" | "eof" | "closed",
|
||||
error: string | null
|
||||
}
|
||||
```
|
||||
|
||||
- 录像优先使用容器时间戳;首帧时间戳无效或倒退时,回退为帧序号/FPS,保证回放时间单调。
|
||||
- `retrying`、`error`、`eof` 和 `closed` 都没有图像,且绝不伪造人员、姿态或摔倒事件。
|
||||
- 可重连来源以有界指数退避重新打开;断流不推进状态机的证据时间。
|
||||
|
||||
## 事件合约
|
||||
|
||||
| 事件 | 触发者 | 负载 | 结果 |
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
## 当前快照
|
||||
|
||||
- 日期:2026-07-21
|
||||
- 阶段:V1 工程化起步;T-102 进行中。
|
||||
- 阶段:V1 工程化起步;T-102 已验收,等待 T-103。
|
||||
- 已验证环境: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 代码:已建立 `v1/__init__.py`、`v1/config.py`、安全的 `config.example.json`、固定依赖清单和配置单元测试;视频源、Pose、跟踪、证据、状态机和 GUI 尚未实现。
|
||||
- V1 代码:已建立安全配置基线,以及 `v1/video_source.py` 的 OpenCV 回放/重连适配器;它输出显式状态和单调时间戳。Pose、跟踪、证据、状态机和 GUI 尚未实现。
|
||||
- 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` 当前有 2 个配置测试并已通过。`init.ps1` 会检查运行时依赖、编译旧基线并运行 V1 测试,但不会安装软件包。
|
||||
- 测试:`python -m compileall -q demo` 已通过;`python -m pytest v1/tests -v` 当前有 6 项配置/视频源测试并已通过。`demo/1.mp4` 的首两帧回放时间戳已验证为 0.000000 与 0.033333 秒。`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`。
|
||||
@@ -32,9 +32,9 @@
|
||||
|
||||
## 任务状态
|
||||
|
||||
- 已完成:T-000(Harness 文档与旧基线快照)、T-101(V1 安全配置基线)。
|
||||
- 正在进行:T-102(实现可重连的视频源与录像回放适配器)。
|
||||
- 下一个可领取:完成 T-102 后为 T-103。
|
||||
- 已完成:T-000(Harness 文档与旧基线快照)、T-101(V1 安全配置基线)、T-102(视频源与录像回放)。
|
||||
- 正在进行:无。
|
||||
- 下一个可领取:T-103。
|
||||
|
||||
## 当前可运行内容
|
||||
|
||||
|
||||
Reference in New Issue
Block a user