将场加权标定模型接入回放分析

回放按声明的 30 帧加权空载窗口取基线并逐帧保存外推质量,field 模型单独进缓存键,实时入口拒绝。
新增测试覆盖窗口、质量与拒绝路径。全量门禁的 scene3d 两项失败与 studio 访问冲突为既有问题,
已归因并另立 studio-gate-hang。
This commit is contained in:
ykcheungab
2026-10-19 19:49:36 +08:00
parent 81063213f9
commit c1e6d21030
14 changed files with 1462 additions and 23 deletions
+5 -5
View File
@@ -38,10 +38,9 @@ zlib level 6。
`(max − min) / 510`,实测 6.6e-5(该帧峰值 0.034)。这不到深度视图所用 256 级色标的一步,所以
重建出来的帧**不可能被染成与原帧不同的颜色**。
稀疏存储实测过并否决:每像素 4 B 索引在最坏帧上要 910 B,而整幅量化平面只要 486 B —— 一片几乎
全零的字节平面在 zlib 下几乎免费,像素索引不是。限制在岛内也实测过并否决:418 B 对 486 B,
在 4,048 B 的记录里省 5.2 B/帧,代价是重建要依赖有效性掩码 keyframe(box 链路根本没有),
而且一旦有深度值落在岛外就会**静默丢掉一个测量**。
稀疏存储实测后否决:最坏帧每像素 4 B 索引要 910 B,整幅量化平面只要 486 B —— 几乎全零的
字节平面在 zlib 下几乎免费。限制在岛内也否决:418 B 对 486 B,每帧省 5.2 B,却要依赖有效性
掩码 keyframe(box 链路没有),且岛外深度值会静默丢测量。
`provenance` 随结果存:算法版本、传感器配置及其内容哈希、标定 id、单位、参考帧 id、首个输出
帧 id、解码偏移、逐通道的"重算/记录"标记(`flow`、`depth` 重算;`forces` 见第 1.1 节)、
@@ -90,7 +89,8 @@ box 链路没有 `valid_mask`,`max_arrows=400` 的上限因此按幅值排序
`magnitude` 重新推导 `active`,不需要重建结果;只有采样**网格**(`flow_grid_spacing`、
`flow_edge_margin`、`max_arrows`)变化才会移动候选位置,那份策略记在 provenance 里供比对而
不塞进键里。SDK 版本同样不在键里(补丁版本不该让键变化),它记在 provenance 的 `versions`,
由 `AnalysisReader.stale_reasons()` 报出。
由 `AnalysisReader.stale_reasons()` 报出。场加权实验模型的键分量与逐帧质量见
[replay-field-experiment.zh.md](replay-field-experiment.zh.md)。
## 4. 参考帧规则
@@ -0,0 +1,62 @@
# Studio 回放:场加权实验模型
用途:reference。范围:Studio 回放分析对 SDK `field_gain/1`(输入 profile
`hhd_normal_l1_field/1`)的接线、缓存身份、逐帧质量诊断与实时拒绝边界。
格式、完整性、失效键与播放语义分别由[replay-analysis.md](replay-analysis.md)与
[replay-analysis-part-b.md](replay-analysis-part-b.md)负责;模型语义见
[场模型契约](../../../orisys-sdk/docs/field-gain-model.zh.md),任务范围见
[实施计划](../../../docs/workflow/field-weighted-calibration-plan.zh.md)。
## 缓存身份
场加权模型是新的分析行为,但不是新的二进制格式。`result_key` 的 `sensor_config` 分量在
标定文件实际为 `field_gain/1` 时追加 `;field-weighted=1`;spatial/global 模型与旧结果的键
不变,因此旧回放结果仍能命中。标定内容身份仍来自 schema 3 指纹(含 `pipeline.field`、
几何与坐标附件),算法版本不因本功能整体升级。
provenance 另存 `field` 块:`profile`、`strategy`、实验来源、`baseline_N`、
`reference_id`、参与统计帧数、`extrapolated_mean/max` 与**运行时实际**的
`hhd.downsample`、`hhd.grid_shape`。缓存键只用标定指纹与配置内容哈希,不用声明值假装实际值;
实际网格只进 provenance。
## 回放 pass
- 打开链后读 `sensor.calibration.input_profile` 判定模型;field 模型只在显式 `cal_path`
下使用,profile 默认文件不假定为实验模型。
- 新模型要求**单 segment 录像**:加权基线无法在段边界重建,多 segment 直接 `ValueError`
并留下原因,不静默丢基线。
- 空载窗口仍需操作员在分析设置里声明(30 帧);每个 pass 在参考帧 `reset` 之后、该帧
`process_chain` 之前调用一次 `declare_unloaded_reference(reference_id="video-unloaded-<id>")`。
SDK 累计连续 30 个有效加权 `P` 并取中位数;前 30 帧状态 `zero_unavailable`,
没有牛顿值但保留 raw 读数。不得调用 `set_calibration_reference` 传旧 raw 标量零点,
也不得把 `centroid_found` 当门槛。
- 第 30 个有效帧后确认 `baseline_N` 已就绪;视频结束仍未就绪沿用现有 `ValueError` 语义。
- 逐帧质量取自 `sensor.calibration_result.diagnostics`:`extrapolated_fraction`、
`coverage_fraction`、`pending_reference_frames`、`baseline_N`、`reference_id`、
`model_fingerprint`。质量是估计证据,不参与 `calibration_status`,不得因此丢弃牛顿值。
## 逐帧存储与读取
场加权质量追加在帧记录最后:`FRAME_FLAG_FIELD` 后接 `extrapolated_fraction` 与
`coverage_fraction` 两个 float32,沿用 `FRAME_FLAG_FORCE` 的追加先例,格式版本不变。
`AnalysisReader.frame().field_quality` 返回二元组;旧结果没有该 flag 时返回 `None`,
上层显示“未知”,不得补零或拒绝结果。`counts.field_quality_frames` 记录带质量帧数。
`ForceSample.from_reading` 继续只凭 raw 有限性判断 `valid`;质量缺失或外推比例高低都不改变
有效性。`out_of_range` 与负的基线差保留数值。
## 显示与实时拒绝
- `replay_controller` 在曲线来源与提示中使用 provenance 的 `field` 块:实验模型标签、
加权基线、平均外推比例;缺字段显示未知。中英 locales 成对新增键。
- 实时入口未接入该模型:`SdkAcquisitionWorker.start()`/`FingerAcquisitionWorker.start()`
与热切换 `_consume_pending_calibration()` 在打开设备前检查显式 `cal_path`,遇
schema 3 `field_gain/1` 抛可诊断的 `RuntimeError`;由现有运行错误处理显示。
`calibration_service`/实时 UI 若继续重构,保留同一检查函数供调用。
## 验收与限制
回归见 `shared/tests/test_field_calibration_app.py`、`apps/studio/tests/test_field_experiment_display.py`
及扩展现有四件套:窗口只声明一次、前 30 帧无牛顿值、第 30 帧后就绪、无接触仍有效、
多 segment 拒绝、质量 round-trip 与旧结果未知、field 键与 spatial 键不同、实时入口拒绝。
本次不宣称物理精度或在先模型的精度改善;基线窗口是否平稳、外推比例大小都必须随结果如实报告。