feat(v2): complete Go inference and UI spike
This commit is contained in:
@@ -23,9 +23,10 @@
|
||||
| --- | --- | --- | --- |
|
||||
| 语言 | Go | 已定 | 面向长时间 RTSP 运行、并发控制和单一交付物。 |
|
||||
| 模型工件 | 固定输入尺寸的 ONNX Pose 模型 | 已定 | Go 不直接加载 `.pt`;模型由已验收 V1 权重导出并记录哈希。 |
|
||||
| 推理运行时 | ONNX Runtime 或经 Spike 验证的等价 Go 运行时 | 待 T-302 决定 | 选择标准是 Windows 打包、Pose 输出、CPU/GPU 与持续运行稳定性。 |
|
||||
| 视频输入与绘制 | Go 方案待 T-302 Spike 决定 | 待定 | 必须读取 RTSP、保留 BGR/RGB 与 letterbox 一致性,并满足现场显示。 |
|
||||
| 演示 UI | 本地网页壳或轻量桌面壳待 T-302 Spike 决定 | 待定 | 不在未验证视频帧展示能力前锁定 UI 框架。 |
|
||||
| 推理运行时 | `github.com/yalue/onnxruntime_go` v1.31.0 + ONNX Runtime CPU DLL | Spike 已验证 | Windows 上以显式 DLL 路径加载锁定的 1×3×640×640 Pose ONNX,已完成一次真实录像首帧推理;该包装器的 C API 为 26,V2 构建必须启用 CGO/MinGW,并在发布包锁定匹配 DLL 的来源与 SHA-256。 |
|
||||
| 视频输入 | 受控的 `ffmpeg.exe` 子进程输出 `bgr24` 原始帧 | Spike 已验证 | 已读取 848×480 本地录像首帧;避免未配置的 GoCV/OpenCV 开发绑定。T-304 必须随应用锁定 FFmpeg/FFprobe 的版本、哈希与 RTSP 重连行为。 |
|
||||
| 图像预处理 | Go 实现的 BGR→RGB、CHW、640 letterbox | Spike 已验证,待一致性回归 | 可生成 ONNX 所需 1,228,800 个 float;当前是最小 nearest-neighbour Spike,不得直接当作生产预处理,T-303 必须与 V1 缩放、补边、NMS 和坐标还原逐项对齐。 |
|
||||
| 演示 UI | `github.com/lxn/walk`(Windows 原生控件) | Spike 已验证 | 双 Tab 骨架可在 `CGO_ENABLED=0` 编译,避免 Fyne/OpenGL 首次编译的高复杂度;正式版仍须实现浅灰蓝底、白色卡片,红色仅表示确认摔倒。 |
|
||||
| 测试 | `go test ./...` + V1 回归录像 | 已定 | V2 行为必须与 V1 基线对照。 |
|
||||
|
||||
## 关键选型纪律
|
||||
@@ -33,6 +34,8 @@
|
||||
- V1 不引入新模型、数据库、云服务或重量级告警依赖。
|
||||
- RTSP 凭证仅来自环境变量或未跟踪本地文件;示例配置只含变量名。
|
||||
- V2 的 ONNX 预处理、NMS、关键点解析、坐标还原和阈值必须与 V1 录像基线一致。
|
||||
- `onnxruntime.dll`、`ffmpeg.exe` 与 `ffprobe.exe` 是 V2 发布依赖,必须以明确版本、来源和 SHA-256 随发布清单锁定;不得把开发机 Python 包、Go 模块缓存或系统 PATH 当成交付依赖。
|
||||
- V2 的 ONNX Runtime 包装器依赖 CGO;构建机必须固定 Go、MinGW 和 CGO 环境,运行端只加载已锁定的 DLL。CPU 是当前唯一已验证执行路径。
|
||||
- 如果 V2 需要 GPU 专用引擎,必须记录显卡、驱动、运行时版本和回退 CPU 路径;不能将硬件绑定伪装成通用稳定性。
|
||||
|
||||
## 当前可运行命令
|
||||
@@ -44,7 +47,9 @@
|
||||
| 旧 GUI 启动 | `Set-Location demo; python main.py` |
|
||||
| V1 依赖安装 | `python -m pip install -r v1/requirements.txt`(显式执行;`init.ps1` 不自动安装) |
|
||||
| V1 单元测试 | `python -m pytest v1/tests -v` |
|
||||
| V2 测试 | T-302 创建 Go 模块后使用 `go test ./...` |
|
||||
| V2 单元测试 | `Set-Location v2; $env:CGO_ENABLED='1'; go test ./...` |
|
||||
| V2 ONNX/视频 Spike | `Set-Location v2; $env:CGO_ENABLED='1'; go run ./cmd/spike --ffmpeg <ffmpeg.exe> --video <local-video> --width <w> --height <h> --onnx assets\best.onnx --ort-dll <onnxruntime.dll>` |
|
||||
| V2 Walk UI 编译 Spike | `Set-Location v2; $env:CGO_ENABLED='0'; go build ./cmd/ui-spike` |
|
||||
|
||||
## 演进决策
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@ Pose 推理适配器(person box + 17 keypoints)
|
||||
|
||||
V1 的同一数据流既可接 RTSP,也可回放本地录像。V2 复用同一配置、事件字段和录像集,但将 Pose 推理替换为 ONNX 适配器;不得改变事件语义。
|
||||
|
||||
T-302 的实现路线为:受控 `ffmpeg.exe` 负责解码为 BGR 原始帧,Go 预处理模块生成固定 `1×3×640×640` RGB/CHW tensor,`onnxruntime_go` 以显式 DLL 路径执行 Pose ONNX,Windows Walk UI 只接收已完成渲染的数据。解码、推理和事件计算都不得在 UI 消息线程运行;UI 只显示最新完成帧和事件状态。T-303 必须先补齐与 V1 一致的 letterbox、NMS、17 点解析、坐标还原、跟踪和状态机,才可以接入实时 UI。
|
||||
|
||||
## 模块职责
|
||||
|
||||
| 模块 | V1 位置 | 职责 | 不负责 |
|
||||
@@ -46,6 +48,16 @@ V1 的同一数据流既可接 RTSP,也可回放本地录像。V2 复用同一
|
||||
| 应用装配 | `v1/app.py` | 装配配置、Pose、管线线程与窗口;`FrameWorker` 只发出已判定的 `FrameAnalysis` | 事件判定、渲染细节 |
|
||||
| 回归工具 | `v1/tests/` 与 `v1/scripts/` | 回放录像、断言事件和延迟 | 生产 UI |
|
||||
|
||||
V2 对应模块将在 T-303/T-304 建立,职责预先固定如下:
|
||||
|
||||
| 模块 | V2 目标位置 | 职责 | 不负责 |
|
||||
| --- | --- | --- | --- |
|
||||
| 解码器 | `v2/internal/video` | 启动受控 FFmpeg、提供最新 BGR 帧与显式来源状态 | Pose、事件判定、UI 绘制 |
|
||||
| ONNX Pose | `v2/internal/pose` | 校验模型/DLL 清单,完成精确预处理、推理、NMS、关键点及坐标还原 | 人员 ID、摔倒结论 |
|
||||
| 事件引擎 | `v2/internal/fall` | 复现 V1 的跟踪、证据、四态状态机和 `FallEvent` | 视频解码、声音、文件 |
|
||||
| Windows UI | `v2/internal/ui` | Walk 顶部“监控/设置”Tab、渲染最新帧和已计算状态 | 直接读 RTSP、执行 ONNX 或事件规则 |
|
||||
| 应用装配 | `v2/cmd/silver-pose` | 管理 worker 生命周期、取消、最新帧投递和依赖注入 | 重写领域规则 |
|
||||
|
||||
## UI 导航与配置生效生命周期
|
||||
|
||||
PyQt 主窗口只包含实时监控和设置两个顶部 Tab。实时监控 Tab 保持视频画面优先;设置 Tab 不能直接调用视频源、Pose 或状态机。
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@
|
||||
| ID | 任务 | 依赖 | 验收要点 | 状态 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| T-301 | 锁定 V1 模型并导出 ONNX 一致性工件 | T-205 | 记录 `.pt` 与 ONNX 哈希、输入尺寸、导出命令;同一帧关键点与 Python 在约定容差内。 | DONE |
|
||||
| T-302 | 完成 Go 推理与视频/UI 技术 Spike | T-301 | Windows 上可读取录像和 ONNX Pose;选定运行时与 UI 方案并记录取舍。 | DOING |
|
||||
| T-302 | 完成 Go 推理与视频/UI 技术 Spike | T-301 | Windows 上可读取录像和 ONNX Pose;选定运行时与 UI 方案并记录取舍。 | DONE |
|
||||
| T-303 | 实现 Go 的事件引擎与 V1 回归对比 | T-302 | 同一录像的确认事件、无报警案例和延迟满足 V1 基线。 | TODO |
|
||||
| T-304 | 完成 Go 实时演示、报警和打包 | T-303 | 实时 RTSP、红色画面、声音、弹窗和截图可运行;新环境按文档启动。 | TODO |
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
# T-302 · Go 推理、视频与 Windows UI Spike 决策
|
||||
|
||||
- 状态:已接受,作为 T-303/T-304 的实施前提
|
||||
- 日期:2026-07-22
|
||||
- 范围:仅验证 Windows 开发环境的单帧推理、录像解码和 UI 技术路线;不等于 V2 行为验收或客户演示验收。
|
||||
|
||||
## 结论
|
||||
|
||||
1. Pose 运行时采用 `github.com/yalue/onnxruntime_go` v1.31.0,CPU 路径,且启动时必须显式指定 `onnxruntime.dll`。包装器当前使用 ONNX Runtime C API 26,构建机须固定 Go、`CGO_ENABLED=1` 和 MinGW;运行端不依赖 Python,但必须随发布物携带版本、来源和 SHA-256 都已锁定的匹配 DLL。
|
||||
2. 视频接入采用受控 `ffmpeg.exe` 子进程。它解码录像或 RTSP 为 `bgr24` 原始帧;T-304 将锁定 `ffmpeg.exe`/`ffprobe.exe` 的版本和哈希,并实现来源状态、超时、取消与重连。当前不采用 GoCV,因为此机没有可用的 OpenCV/GoCV 开发绑定。
|
||||
3. Windows UI 采用 `github.com/lxn/walk`。它提供原生窗口、顶部 Tab 和控件,UI Spike 在 `CGO_ENABLED=0` 下可编译。正式 UI 继续使用文档中的浅灰蓝底、白色卡片和“红色只表示 CONFIRMED”的语义;Walk 只在 UI 线程渲染,不能调用解码、ONNX 或状态机。
|
||||
|
||||
## 验证证据
|
||||
|
||||
命令行 Spike 使用 `demo/1.mp4` 的第一帧(848×480),从 FFmpeg 获取准确的 1,221,120 字节 BGR 帧,转为 1×3×640×640 的 1,228,800 个 `float32` 输入;锁定 `v2/assets/best.onnx` 输出为 1×56×8400 的 470,400 个值。实际运行输出:
|
||||
|
||||
```text
|
||||
SPIKE_OK frame=848x480 input=1228800 output=470400 max=685.7795
|
||||
```
|
||||
|
||||
`go test ./...` 在 `CGO_ENABLED=1` 下通过,且 `go build ./cmd/ui-spike` 在 `CGO_ENABLED=0` 下通过。最小测试覆盖 BGR 尺寸拒绝、letterbox 后 RGB/CHW 布局、Pose 输入长度拒绝和 UI 视觉令牌。
|
||||
|
||||
开发机的 ONNX Spike 暂时使用 Go 模块缓存内的 `test_data/onnxruntime.dll`,仅用于证明接口可执行;它不是允许交付的 DLL 来源,也未被拷入仓库。
|
||||
|
||||
## 拒绝的路线
|
||||
|
||||
- **GoCV/OpenCV**:未配置 Windows 开发库、`pkg-config` 或 CGO 绑定,无法据实声称可用于 V2。
|
||||
- **Fyne**:初次 Windows 构建进入 OpenGL/CGO 编译并在 120 秒内未完成,且遗留编译进程;对于当前“稳定现场演示”的目标,引入的 UI 图形链复杂度不合适。随后已停止这些精确的临时进程,没有修改用户文件。
|
||||
|
||||
## 不在本任务中的内容
|
||||
|
||||
当前 Go letterbox 是最小 Spike(nearest-neighbour)。它尚未完成或证明与 V1 等价的缩放/补边、NMS、关键点解析、坐标还原、人员跟踪、事件状态机、RTSP 断流、声音、弹窗、截图和打包。T-303 必须以同一录像的关键点、事件数量、非报警案例和确认延迟证明 V1/V2 等价;T-304 才可形成部署与现场演示闭环。
|
||||
@@ -5,17 +5,17 @@
|
||||
## 当前快照
|
||||
|
||||
- 日期:2026-07-22
|
||||
- 阶段:V1 客户演示闭环和 T-301 模型导出一致性已验收;T-302 Go 推理/UI 技术 Spike 进行中。判定灵敏度默认已放宽(低位俯视:持续水平即可疑,膝踝可缺,水平阈值 45°),确认窗为主防误报闸。
|
||||
- 阶段:V1 客户演示闭环、T-301 模型导出一致性与 T-302 Go 技术 Spike 已验收;下一个任务是 T-303(复现 V1 事件引擎并做录像回归)。判定灵敏度默认已放宽(低位俯视:持续水平即可疑,膝踝可缺,水平阈值 45°),确认窗为主防误报闸。
|
||||
- 已验证环境:Windows PowerShell;Python 3.8.10;Ultralytics 8.3.205;PyQt5 可导入。注意:当前 WSL/Linux 环境未安装 PyQt5,且其 ultralytics/torch 版本与该基线不兼容(模型前向不可用),故 GUI 可视化与真实模型端到端渲染只在 Windows 验证;本环境用 Qt-free 的 `view_model.py` 单元测试与假适配器管线冒烟覆盖视图逻辑。
|
||||
- 旧生产基线:`demo/main.py`、`demo/fall_detection_gui.py`、`demo/detect_fall.py`、`demo/best.pt`。
|
||||
- V1 代码:已建立安全配置、显式 Replay/Stream 视频源、Pose、轻量跟踪、质量/几何证据、倒地领域规则、按 ID 四态事件机及 `v1/pipeline.py` 事件管线;运行事件带非敏感 `config_version`,缺帧/低质量/断流会中断证据确认。新增 `v1/view_model.py`(Qt-free 监控视图状态与设置草稿三份隔离)、`v1/gui.py` 薄 PyQt5 双 Tab 外壳与 `v1/app.py` 装配(`FrameWorker` 只发出已判定的 `FrameAnalysis`,窗口只渲染)。新增 `v1/alerts.py`:按 `event_id` 去重,对首次 CONFIRMED 保存带标注截图、追加 JSONL 事件行,并经可注入 `AlertSink`(Windows 侧 `QtAlertSink` 提供声音与一次性弹窗)触发一次声音/弹窗。新增 `v1/camera.py`(RTSP URL 构建 + 有界连接测试抓帧)与 `config.py` 的结构化来源(host/端口/通道/账号/密码,凭证百分号编码)、`write_local_camera_source`;设置页新增摄像头连接分组、测试连接与预览,以及传输协议/连接超时/低延迟三项抓流调优(由 `config` 存值、`app` 开流前写入 `OPENCV_FFMPEG_CAPTURE_OPTIONS`)。真实海康流已用 `VideoSource(STREAM)` 连通(1920×1080)。
|
||||
- V2 代码:`v2/` 目录存在但尚无实现。
|
||||
- V2 代码:已创建 Go 模块和受控 Spike。`cmd/spike` 用 FFmpeg 读取本地 BGR 帧、将其预处理为 640 tensor,并用 `onnxruntime_go` 对锁定 ONNX 执行一次推理;`cmd/ui-spike` 是可编译的 Windows Walk 双 Tab 外壳。它们不含 NMS/关键点解析、跟踪、状态机、RTSP、报警或发布打包,不能作为客户演示版。
|
||||
- 非代码设计工件: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 v1 demo` 已通过(含 `gui.py`、`app.py`、`alerts.py`、`camera.py` 语法);`python -m pytest v1/tests -v` 当前有 86 项配置、视频源、Pose、跟踪、证据、领域规则、状态机、管线、视图模型、报警工件、摄像头/URL 构建、抓流参数拼串、每帧诊断、灵敏度放宽、截图 ASCII 标注、断流重连、事件汇总、灵敏度写回、最新帧丢弃和截图中文标注测试并已通过(含来源模式显式声明、模型置信度经适配器生效、事件号跨轮唯一、结构化凭证不入 config_version 且公开示例无凭证的守卫)。`demo/1.mp4` 的首两帧回放时间戳已验证为 0.000000 与 0.033333 秒;T-106 的真实模型/录像 smoke 在首帧得到 2 名已分析人员、第二帧得到 0 名人员且未创建事件;T-201 的视图冒烟以真实录像解码 + 真实管线 + 确定性假 Pose 适配器驱动 `build_monitor_view`,得到稳定 ID、box、14 段骨架、17/17 关键点与 NORMAL/success,断流帧 0 人且不显示摔倒标签;T-202 的报警冒烟用 `demo/1.mp4` 首帧(848×480)落盘一张可被 `cv2.imread` 读回的标注截图(480×848×3,约 330 KB)与一行 JSONL(相对截图路径、含 config_version/source_id、无 rtsp),重复派发返回 0。这些只验证管线、视图与报警工件可运行,不表示摔倒识别准确率。`init.ps1` 会检查运行时依赖、编译旧基线并运行 V1 测试,但不会安装软件包。
|
||||
- 测试:`python -m compileall -q v1 demo` 已通过(含 `gui.py`、`app.py`、`alerts.py`、`camera.py` 语法);`./init.ps1` 当前运行 V1 测试为 88 passed、1 skipped,覆盖配置、视频源、Pose、跟踪、证据、领域规则、状态机、管线、视图模型、报警工件、摄像头/URL 构建、抓流参数拼串、每帧诊断、灵敏度放宽、截图标注、断流重连、事件汇总、灵敏度写回和最新帧丢弃。T-302 的 `CGO_ENABLED=1 go test ./...` 通过;Go Spike 对 848×480 本地录像首帧生成 1,228,800 元素输入并获得 470,400 元素 ONNX 输出;Walk UI Spike 以 `CGO_ENABLED=0 go build ./cmd/ui-spike` 编译通过。这些只验证管线、视图与报警工件可运行,不表示摔倒识别准确率或 Go 行为等价。`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-301 尚未锁定 ONNX 工件并完成 Python/ONNX 关键点一致性记录;现场录像和事件工件保留本机,不提交仓库。GUI 可视化、声音、弹窗与设置页测试连接的像素级观感仍应在 Windows 目视复核。
|
||||
- 当前 blocker:没有 T-303 的代码阻塞;但 Go 尚未验证与 V1 的预后处理、NMS、关键点、跟踪、状态机和事件延迟一致,不能把 T-302 的单帧推理表述为可演示的 V2。ONNX Runtime DLL、FFmpeg/FFprobe 仍须在 T-304 以版本、来源和哈希纳入发布包;现场录像和事件工件保持本机不提交。
|
||||
|
||||
全局环境的 `pip check` 存在其他项目的包冲突,因此它不是 Silver Pose 的验收命令。`init.ps1` 只检查本项目实际导入的 OpenCV、NumPy、Ultralytics 与 PyQt5,并在命令非零退出时失败。
|
||||
|
||||
@@ -24,17 +24,17 @@
|
||||
| 路径 | 状态 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `demo/` | 已有 | 旧 Python GUI、Pose 模型与样例视频;当前单帧规则不适合作为正式事件逻辑。 |
|
||||
| `v1/` | 待开发 | 新 Python V1 的正式实现目录。 |
|
||||
| `v2/` | 待开发 | Go V2 目录;V1 验收前不实现功能。 |
|
||||
| `v1/` | 已验收 | Python V1 正式实现、现场验收记录与发布工具。 |
|
||||
| `v2/` | Spike 已完成 | Go 模块、ONNX/视频命令行 Spike 与 Windows Walk UI 外壳;尚不是完整 V2。 |
|
||||
| `docs/` | 已有 | Harness Coding 文档、任务和计划。 |
|
||||
| `tests/` | 不适用 | V1 测试将在 `v1/tests/` 下创建。 |
|
||||
| `artifacts/` | 待创建 | 本地事件截图和 JSONL,不提交。 |
|
||||
|
||||
## 任务状态
|
||||
|
||||
- 已完成:T-000、T-101~T-106(V1 地基与事件管线)、T-201(PyQt 双 Tab)、T-202(本地报警/截图/JSONL)、T-203(海康 RTSP 与断流恢复)、T-204(正反例录像与现场验收)、T-206(结构化摄像头配置与连接测试)、T-207(抓流低延迟参数)、T-208(每帧诊断叠加)、T-209(放宽俯视灵敏度)、T-210(截图 ASCII 标注)、T-211(灵敏度设置页)、T-212(实时流最新帧)、T-213(截图中文标注)。
|
||||
- 已完成:T-000、T-101~T-106(V1 地基与事件管线)、T-201(PyQt 双 Tab)、T-202(本地报警/截图/JSONL)、T-203(海康 RTSP 与断流恢复)、T-204(正反例录像与现场验收)、T-205(客户演示脚本与发布包)、T-206(结构化摄像头配置与连接测试)、T-207(抓流低延迟参数)、T-208(每帧诊断叠加)、T-209(放宽俯视灵敏度)、T-210(截图 ASCII 标注)、T-211(灵敏度设置页)、T-212(实时流最新帧)、T-213(截图中文标注)、T-301(ONNX 一致性)、T-302(Go 推理、视频/UI Spike)。
|
||||
- 正在进行:无。
|
||||
- 下一个可领取:T-301(锁定 V1 模型并导出 ONNX 一致性工件)。
|
||||
- 下一个可领取:T-303(实现 Go 事件引擎与 V1 回归对比)。
|
||||
|
||||
## 当前可运行内容
|
||||
|
||||
|
||||
Reference in New Issue
Block a user