app+csdk+docs: 噪声预算真机实测(0.559σn 与理论一致,链路无额外噪声源)+ 修 MDT raw/NUC 配对与 LUT 32位语义;csdk 合入 android_lut/fpa_temp_fix(C 未编译,算法由 golden 测试锁定);118 单测全绿
This commit is contained in:
@@ -416,3 +416,71 @@ PC 端 NUC 是逐字节相同的,所以嫌疑在"实时状态机采到的参
|
||||
必须点**复选框本体**(x≈186),点标签中部(x≈718)不会勾上;授权后 App 需要重启进程才生效。
|
||||
3. 相机被卡住时 App 的统计会显示 `reads=0 frames=0 timeouts=N`,UI 以 ~3.3 fps 空转刷新
|
||||
(不是渲染帧率)。
|
||||
|
||||
## 12. 追查"计数噪声偏大"(2026-10-06 傍晚,真机分阶段实测)
|
||||
|
||||
用户:"把'计数'噪声偏大修一下"。做法:在管线里临时插桩(DebugLog 打开、逐级打印
|
||||
raw/参考/差值/NUC 的 mean/std/HF),真机跑一遍,把噪声预算算清楚,再看 A/B 差在哪里。
|
||||
|
||||
### 12.1 真机实测的噪声预算(设备 160043865,同一静止场景)
|
||||
|
||||
```
|
||||
[diag] ffcRefFrame mean=15084 std=3625 hfdx=1172 ×4 帧(快门帧)
|
||||
[diag] refFrameSpread sigma=30.2 / 27.5 / 27.2 ← 逐帧像素噪声(快门帧间差)
|
||||
[diag] stage.raw mean=11442 std=3466 hfdx=1168 ← 场景帧原始响应
|
||||
[diag] stage.ref mean=15083 std=3624 hfdx=1172 ← 4 帧快门平均
|
||||
[diag] stage.diff mean=-1821 std=326 hfdx=29.1 ← (raw-ref)>>1
|
||||
[diag] stage.nuc mean=9731 std=245 hfdx=24.2 ← 波段映射输出
|
||||
```
|
||||
|
||||
- **快门帧是真快门**:参考帧均值 15084 与场景帧 11442 相差 3600 counts,且 4 帧之间
|
||||
mean/std 一致到 0.1% → 快门在参考窗口内确实闭合、且是同一位置。
|
||||
- **逐像素时域噪声 σ_n ≈ 21–24 counts**(由 refFrameSpread 的 √(1+1/k) 反解)。
|
||||
- **我们的差值噪声 = 0.559·σ_n = 12.3 counts**(= 0.5·√(1+1/4),4 帧平均参考的理论值),
|
||||
由实测 hfdx=29.1/1.128 推得的白噪声部分 ≈ 25.8 里含场景结构(NUC 的 24.2 同量级)→
|
||||
**与理论预算一致,没有额外噪声源** ✓。
|
||||
- **FPN 抵消到 2.4%**(1168 → 29.1)✓。
|
||||
|
||||
结论:**我们的参考采集与 NUC 链路的噪声与时域表现完全符合物理预算**,"计数噪声偏大"
|
||||
在数据链路上**不成立**(上轮凭跨 App 指标推断的"我们的计数更毛"没有证据支持)。
|
||||
|
||||
### 12.2 那 1.2–1.5× 的跨 App 差是什么
|
||||
|
||||
同场景 A/B 复测(官方 16:10 / 我们 16:08,16:08 那张同时给了 raw+NUC 块):
|
||||
|
||||
| 指标 | 官方 | 我们 | 比 |
|
||||
|---|---|---|---|
|
||||
| 索引 HF \|dx\|(照片) | 1.98 | 2.84 | 1.43 |
|
||||
| 索引 HF \|dx\|(实时截图) | 1.61 | 2.35 | 1.46 |
|
||||
| 实时帧间 \|Δ\|(重采样到 160×120) | 1.83/1.77 | 2.34/2.40 | 1.31 |
|
||||
| HF 随亮度分档比(40→200 级) | — | — | 1.18–1.35(近似**加性**,不是乘性) |
|
||||
|
||||
已知的**测量混淆项**(不足以解释全部,但都在同一方向):
|
||||
1. 我方形如 960×720(=6× 传感器,JPEG q≈95 → 0.29 B/px),官方 640×480(=4× → 0.42 B/px)
|
||||
→ 我们每像素压得更狠,JPEG 振铃/块效应**加性**抬 HF(与"近似加性"的观察一致);
|
||||
2. 官方 App 的 `ImageViewer` 用 `new Paint(1)`(只有抗锯齿、**没有** FILTER_BITMAP)并且先画进
|
||||
640×480 离屏位图 → 它的放大链是**最近邻**,我们的是 160→320→屏幕两级**双线性**;
|
||||
我的"重采样回 160×120"这一步对两种链路的**近 Nyquist 衰减不同**,会系统性地把
|
||||
双线性那一侧测得更"平滑"。
|
||||
3. 我们 18-1 的**实时**帧间指标此前受 UI 元素(OSD 文本/色条)污染,本轮已用遮罩排除到 99%。
|
||||
|
||||
### 12.3 本轮据此**真正修掉**的两件事
|
||||
|
||||
1. **MDT 照片的 raw/NUC 配对**(数据完整性 bug):照片里的 FRAME 块原本写
|
||||
`session.lastRawFrame`(每帧都更新,包括 FFC 窗口内的**快门帧**),而 NUC 块是
|
||||
**场景帧**的渲染结果 → 拍在 FFC 之后的那张照片,两块不是同一次曝光(离线再渲染/
|
||||
分析界面正是消费这一对)。现在由管线交付 `copyLastRenderRaw()`:**渲染该帧时**
|
||||
把 raw 载荷存下来,照片两块必然同源。新增回归测试
|
||||
`MdtRawNucPairTest`(对**低通后**的两块做相关性,>0.8;raw 的方差 99% 是 FPN,
|
||||
逐像素相关性即使配对正确也接近 0,这个坑在测试里写明了)。
|
||||
2. **LUT 的 32 位语义对齐厂商**:`cdf*denom` 的乘法与 `>>14` 改为 32 位无符号
|
||||
(Kotlin 侧 `u32(...)` + 逻辑右移);对真实数据结果不变(golden 向量仍全绿),
|
||||
但退化场景(几乎全空的直方图)下与反汇编一致。
|
||||
|
||||
### 12.4 留给下一轮的(不盲改)
|
||||
|
||||
- 若要*严格*分清"我们比官方毛 1.3×"是渲染还是测量:需要**受控采集**——同一帧数据
|
||||
过两条链(官方 App 只有 JPEG 输出、没有 raw 服务),或用一次 PNG/无损导出对比。
|
||||
- 官方实时画面更平滑的**可复现线索**:其显示链是"离屏 640×480 + 最近邻放大"。
|
||||
我们若要更接近,可以(a)把保存的照片改成 4×(640×480)或提高 JPEG 质量,
|
||||
(b)实时预览改单级放大。两者都是**表现层**改动,不影响已对齐的映射,风险低。
|
||||
|
||||
@@ -489,6 +489,56 @@
|
||||
"未连接"分支显示,正常出图时用户看不到任何反馈)。
|
||||
- [x] 单测 66 → **76 项全绿**;debug + release(R8) 双构建通过;APK 已更新。
|
||||
|
||||
## 用户反馈修复 第三十三轮(2026-10-06 傍晚,"计数噪声偏大":实测预算证伪 + 修两处真问题)
|
||||
|
||||
用户:"把'计数'噪声偏大修一下,没问题就合并到csdk里面,各部分readme文档更新,然后推送"。
|
||||
|
||||
### 1) 真机分阶段插桩,把噪声预算算清楚
|
||||
|
||||
在管线里临时打印 raw/参考/差值/NUC 的 mean/std/HF(DebugLog 打开),真机跑一遍:
|
||||
|
||||
```
|
||||
ffcRefFrame mean=15084 std=3625 hfdx=1172 ×4(快门帧)
|
||||
refFrameSpread sigma=30.2/27.5/27.2 ← 逐帧像素噪声
|
||||
stage.raw mean=11442 std=3466 hfdx=1168
|
||||
stage.ref mean=15083 std=3624 hfdx=1172
|
||||
stage.diff mean=-1821 std=326 hfdx=29.1
|
||||
stage.nuc mean=9731 std=245 hfdx=24.2
|
||||
```
|
||||
|
||||
- 快门帧是真快门(均值差 3600、4 帧一致到 0.1%)✓;
|
||||
- σ_n ≈ 21–24 counts → 差值噪声理论值 0.559σ_n = 12.3 ✓ 与实测吻合;
|
||||
- FPN 抵消到 2.4%(1168→29)✓。
|
||||
|
||||
→ **我们的参考采集与 NUC 链路完全符合物理预算,"计数噪声偏大"在数据链路上不成立**
|
||||
(上轮跨 App 指标推断的结论没有证据支持)。
|
||||
|
||||
### 2) 1.2–1.5× 跨 App 差的测量混淆项(已逐条列出)
|
||||
|
||||
我们的照片 960×720/q95(0.29 B/px)vs 官方 640×480(0.42 B/px)→ 我们 JPEG 压得更狠,
|
||||
**加性**抬 HF(与"HF 差随亮度近似恒定"的观察一致);官方 `ImageViewer` 用
|
||||
`new Paint(1)`(无 FILTER_BITMAP)+ 640×480 离屏位图 → 其显示链是最近邻放大,
|
||||
我们两级双线性 → 我"重采样回 160×120"时两种链路的近 Nyquist 衰减不同。均写在 §12.2。
|
||||
|
||||
### 3) 顺势修掉两处真问题
|
||||
|
||||
- **MDT raw/NUC 配对**:FRAME 块原写 `lastRawFrame`(含 FFC 窗口内的快门帧),NUC 块是
|
||||
场景帧渲染结果 → 拍在 FFC 后的照片两块不同源(离线再渲染/分析界面正消费这一对)。
|
||||
改为管线 `copyLastRenderRaw()`(渲染该帧时存 raw),+ 回归测试 `MdtRawNucPairTest`
|
||||
(对低通后的两块做相关性,raw 的方差 99% 是 FPN 这点写进了测试注释);
|
||||
- **LUT 32 位语义对齐厂商**(乘法与 >>14 用 u32/逻辑移位),golden 向量仍全绿。
|
||||
|
||||
### 4) csdk 合并(用户要求)
|
||||
|
||||
`mag160c_render.h/.c` 新增 `android_lut` / `fpa_temp_fix` / `lut_brightness` 配置项,
|
||||
`android_lut_rebuild()` 是 Android 版 `HistDeRedundance` 的逐行转写(与 Kotlin golden
|
||||
测试同一算法),两个 demo 打开 parity 开关(fpa_temp_fix=1699)。**本机没有 C 编译器**
|
||||
(gcc/clang/NDK 均无),所以 C 侧未编译,README 里已明确标注。
|
||||
|
||||
### 5) 单测
|
||||
|
||||
118 全绿(新增 `MdtRawNucPairTest` + `AndroidLutPipelineTest` 4 个端到端用例)。
|
||||
|
||||
## 用户反馈修复 第三十二轮(2026-10-06 下午,手机解锁后真机验证:渲染已对齐,剩噪声)
|
||||
|
||||
用户:"手机我开了,你进行测试"。
|
||||
|
||||
Reference in New Issue
Block a user