android: 修正 7x7 细节增强的混叠系数(原实现把增益乘了两遍,画面满噪点)

官方 FilterDetailEnhancement_Simple 把「增益缩放后」的 k = strength*gain*2>>8 只
传给 map(决定阈值与 divisor 下限),混叠系数用的是**原始 strength**。本移植最初
两处都用 k,等于把细节再乘一遍增益:真机 level 2 满屏噪点。改为原始 strength 后
HF 能量与关闭档基本相同(0.47-0.51 vs 0.46-0.47),边缘仍被增强。

细节校正:
- 一个有用的推论:每档的边缘强度其实与档位无关(化简为 128/gain),档位只决定
  哪些窗口通过对比度阈值——所以调高档位是"纳入更多弱对比区域",不是"推得更狠"。
  据此把档位从 0-4 扩到 0/1/2/3/4/6/8(官方 MAG_SetDetailEnhancement 钳 0..32)。
- 官方 App 自身不调用 SetDetailEnhancement(jadx 全量搜索无此符号),SetEX 是数码
  变焦 ROI 与增强无关;故无法据此对齐官方默认档,保持用户可见设置、默认关闭。

测试:
- 新增 blendUsesTheRawStrengthNotTheGainScaledOne 黄金值用例(推导写在注释里),
  把 bug 改回去会立刻失败(已实测验证)。
- 原 gainScalesTheEffect 改为 gainDoesNotAmplifyNoiseOnAFlatField + gainBelowOneIsANoOp,
  因为修正后增益不再缩放混叠幅度。98 项测试全绿。

顺带修复(同一轮真机复现):
- no_device 死锁:首次 connect 撞上相机重枚举时停在「无相机」,且紧随其后的
  ATTACHED 广播被 800ms 防抖丢弃 → 永久无画面。防抖/退避改为延后重试,no_device
  也安排 1.5s 重试(scheduleRetry 单槽位、最新优先)。
- 手机平放时加速度计 x/y≈0,迟滞逻辑保留旧姿态角导致 OSD 文字整体转 90°;
  改为 tilt<4m/s² 判定平放、姿态归零。
- 录像帧缺 max/min 标记:probesAsMarks() 现在一并返回,录像与实时画面一致。

真机(小米 22041211AC/Android12/MIUI):15.1fps 稳定、单帧 6-9ms(开增强 11ms)、
拍照与分析页标记一致且各只有一个 min/max、设置跨冷启动持久化、
屏幕熄灭时渲染停止无空转(CPU 3.7%)。
This commit is contained in:
ZXCLI
2026-09-12 05:04:50 +08:00
parent 4ebdca109a
commit f41668d5d1
8 changed files with 180 additions and 35 deletions
+37 -9
View File
@@ -562,17 +562,43 @@ extremes **合并成一次 draw**(原来分两次调用,彼此看不见)
按反编译的 `CFunctions::FilterDetailEnhancement_Simple` + `LocalMap7x7_Simple`
移植(`core/DetailEnhance.kt`):7×7 窗口按 4×4 抽样(x/y 步长 2),
`mean = sum >> 4``if (strength <= (max-min)*32)`
`detail = (0x8000/divisor)*(center-mean)`,最后 `gray += (k*detail) >> 15`
`detail = (0x8000/divisor)*(center-mean)`,最后 `gray += (strength*detail) >> 15`
管线位置与官方一致:`grayMap → 细节增强 → upscale2x → 调色板`
强度换算经官方 SDK 核对:`MAG_SetDetailEnhancement` 把等级钳到 0..32
调用方传 `level << 3`——**与本实现 `level shl 3` 完全一致**。
设置页新增"图像增强"(关闭/1–4 级),**默认关闭**(无官方参考输出可逐位比对,
故 opt-in)。默认关闭时 `RenderPipelineTest` 的逐位基线不受影响(96 项测试全绿)。
实机实测:级别 2 下仍 15.1fps,单帧绘制 11.3ms(滤波器约 +5ms,帧预算 66ms 内),
细节增强清晰可见。
**两个 strength 不可互换(本轮抓到的实现 bug)**:官方把**增益缩放后**的
`k = strength * gain * 2 >> 8` 传给 map(决定阈值与 divisor 下限),
但**混叠系数用的是原始 strength**。本移植最初两处都用 `k`,等于把细节
再乘一遍增益——真机 level 2 画面满屏噪点。修正后 HF 能量与关闭档几乎相同
0.47~0.51 对 0.46~0.47),边缘仍被增强。
数值由 `blendUsesTheRawStrengthNotTheGainScaledOne` 黄金值测试锁定
(推导写在测试注释里;把 bug 改回去该测试立刻失败,已验证)。
**本轮真机验证(小米 22041211AL / Android 12 / MIUI,无线 adb 192.168.88.137:44323**
**档位换算经官方 SDK 核对**`MAG_SetDetailEnhancement` 把档位钳到 **0..32**
`SetEX` 与之无关(那是数码变焦 ROI)。**官方 App 本身不调用
SetDetailEnhancement**jadx 全量搜索无此符号),所以官方实时画面用的是
SDK 内部默认档——无法据此对齐具体档位,故本应用把它做成用户可见设置
0/1/2/3/4/6/8 档),默认**关闭**(关闭时 `RenderPipelineTest` 逐位基线不受影响)。
一个有用的推论:每档的边缘强度其实与档位无关(化简为 `128/gain`),
档位只决定哪些窗口通过对比度阈值——所以调高档位是"纳入更多弱对比区域",
而不是"把边缘推得更狠"。
实机实测:级别 2 下仍 15.1fps,单帧绘制 11.3ms(滤波器约 +5ms,帧预算 66ms 内)。
### 8) 其他顺带修复(本轮真机复现)
- **`no_device` 死锁**:首次 connect 若赶上相机正在重枚举(`findDevice()` 返回
null)就停在"无相机",而 200ms 后到达的 ATTACHED 广播又落在 800ms 防抖窗口里
被丢弃 → 永久无画面,必须手动重启 App。现在防抖与退避都改为**延后重试而非丢弃**,
`no_device` 本身也会安排一次 1.5s 重试(`scheduleRetry` 单槽位、最新请求优先)。
- **平放时 OSD 文字整体转 90°**:手机平放在桌面时加速度计 x/y 都接近 0,
迟滞逻辑保留了上一次的姿态角。现在 tilt < 4 m/s²(约 24°)判定为"平放"
姿态角归零。
- **视频录制缺少 max/min 标记**:实时画面显示的两个极值没有烧进录像帧,
现在 `probesAsMarks()` 一并返回(录像因此与实时画面一致)。
- **屏幕熄灭时的行为(实测)**:渲染线程随 SurfaceView 停止绘制(无空转),
USB 读取继续,整机 CPU 占用 3.7%——后台不烧电、不崩溃。
**本轮真机验证(小米 22041211AC / Android 12 / MIUI,无线 adb 192.168.88.137:44323**
- [x] 渲染帧率 6.5 → **15.1 帧/秒**,单帧 134ms → **6.4ms**(开增强 11.3ms
- [x] 拍照:`capture: nuc=yes probes=2 mirror(h=false,v=true) extremes=2 saved=true`
@@ -580,7 +606,9 @@ extremes **合并成一次 draw**(原来分两次调用,彼此看不见)
`min 22.0℃` 在冷区、Pt1/Pt2 带白底标签,互不压字
- [x] 分析界面:标点与照片烧录位置对齐,**只有一个 min、一个 max**
- [x] 分析面板数值可见且与照片一致(最高 32.9 / 最低 22.0 / 中心 24.4℃)
- [x] 图像增强 2 级:画面细节明显增强,帧率不掉
- [x] 图像增强:档位生效、修正后不再放大噪声、15.1fps 不掉
- [x] 设置持久化跨冷启动(`mag160c_settings.xml`enhanceLevel / imageFlipV
- [x] 屏幕熄灭时无空转(CPU 3.7%)、USB 读取继续、不崩溃
**教训记录**
- `dumpsys gfxinfo` 不统计 SurfaceView 的 lockCanvas 绘制。判断自绘画面性能