docs: 第三十七轮交接——官方条纹更不明显的定位:逐行固定偏移(我们独有),逆向排除全部每帧候选;测量数据与下一步清单见渲染文档 §16
This commit is contained in:
@@ -599,3 +599,82 @@ JPEG 只能解释一部分:把我们那张(960×720 q95,202 KB)按 640×
|
||||
|
||||
→ 修好后我们**比官方更平滑**(官方因最近邻 4× 反而有 4 像素大块,见 x8 放大对照图)。
|
||||
单测 119 全绿(`PhotoNucMappingTest` 更新为 160×120→960×720 的新策略)。
|
||||
|
||||
## 16. 「官方背景条纹更不明显」——逆向排除全部候选后,定位为**我们独有的逐行固定偏移**(2026-10-06 深夜,交接轮)
|
||||
|
||||
用户发了同场景双截图(官方 vs 我们,均为竖屏、12 px/传感器像素、同一调色板铁虹)并要求
|
||||
"看逆向出来的代码是不是还漏了什么"。本轮做了两件事:把官方每帧链路逐条再对一遍(IDA 批量
|
||||
反编译),并对两台 App 的显示结果做**调色板弧长反演**的定量对比。**结论:每帧算法没有遗漏;
|
||||
差异是一个官方没有、我们有的"逐传感器行固定偏移"(残余行 FPN,显示上就是水平条纹)。**
|
||||
|
||||
### 16.1 逆向再核对(libcxsdk = 普通版 MAG-Cx 的 SDK,全部读反编译原文)
|
||||
|
||||
- **内参来源定案**:`Controller::StartProcess(cb, w,h,sn,devType, close,open, ffcFrame,ffcTemp, palette, baseLineAcc, cali)`
|
||||
只写 Controller+0x28(w)/+0x2c(h)/+0x18(palette)/+0x40(baseLineAcc),其余字段保持
|
||||
`Controller::Controller()` 的默认:+0x44=**1**、+0x48=**1**、+0x4c=5。
|
||||
映射到 CFunctions:0x3804=baseLineAcc=**4**、0x3808=**1**(温度累积器**旁路**)、
|
||||
0x380c=**1**(**CSmoother 关**)、0x3810=5。→ 官方手机链路**没有**平滑器/累积器,
|
||||
之前 §8/§9/§10 的结论不用改。
|
||||
- **每帧链路** = `Calibration`(DDT 有效时走 `CalibrationMain_RTV`:
|
||||
`d=(raw−base)>>1` → 按段阈值选 `(gain,off)` → `(d*gain>>12)+off`,clamp 0..0xffff)
|
||||
+ `BlindCompensation`(盲元按 3..8 邻域均值替换,DDT 盲元表) + Mirror(关) +
|
||||
`TempRangeStat` + `GrayEnlarge`(内含 `HistDeRedundance`)。E2X/E4X 仅当 EX≠0
|
||||
(App imageEX=0),`FilterDetailEnhancement(_Simple)` 仅当 CFunctions+0x28≠0
|
||||
(**从未被写**=0)。→ 与我们的实现一一对应,**没有缺的阶段**。
|
||||
- **标定表只在 FFC 窗口重建**:`DoSomething(param_1==0)`→`SelectCaliCurve`+
|
||||
`GenerateVolatileLens`;param_1≥1 时在窗口各帧**分块** `InterpolateShort/UShort`
|
||||
(块大小按 `(13+总字节+尾-2)/(13-1)+7&~7`,完成后置 0x2d24=1)。不在每帧跑 →
|
||||
我们"FFC 时 rebuildTables"一致。
|
||||
- **FFC 时序逐帧一致**:触发→cb(0) 关快门 →帧 1..5→帧 6..9 逐帧 `PushBaselineRaw`
|
||||
(首帧 Restart,4 帧块平均)→**第 9 帧回调 cb(1) 开快门**→帧 10..13 DoSomething→帧 14 起正常。
|
||||
我们的状态机(idx 1..5 / 6..9 / idx==9 onFfc(1) / 10..13)完全同相。
|
||||
- **设备配置命令**:`setFrameRate`(P2D_SetFrameRate=0x6BB6B679,载荷 interFrame/interLine
|
||||
两个 u32;fpsMode 0→9/12,否则 105/105)只在 **devType 1/2** 时发;我们 devType=**3**
|
||||
→ 官方也不发。`P2D_SetParameter1/2` 官方 USB 路径只发 Get。→ 原始流配置两边相同。
|
||||
- **工具链记录**:普通版 APK=`app/【普通版】MAG-Cx.apk`(libcxsdk.so 372KB armeabi,
|
||||
md5 4d8d98bb…,与 analysis/sdk_re/android_app/bin 相同;JNI 层是 libcxx2java.so 67KB)。
|
||||
`analysis/ida/libcoresdk_arm64.so` 是**专业版 MAG-Mx** 的库,别拿它推普通版
|
||||
(它的 0x439d80/88 内参在 .bss,文件里读不到)。IDA Pro 9.4 批量反编译命令:
|
||||
`idat.exe -A -S"<script.idc>" -L"<log>" <so>`(脚本按 `get_next_func` 遍历;
|
||||
对 `__imp__` 导入 thunk 会异常中断,注意跳过;Ghidra headless 兜底)。
|
||||
- `test_frames.bin` 夹具是合成/重复帧(60 帧 mean/std 完全相同),**不能**用于噪声分析。
|
||||
|
||||
### 16.2 定量对比(调色板弧长反演,脚本在 %TEMP%\mag160c_re\analyzer.py,临时件)
|
||||
|
||||
方法:ironbow 256 色表(VendorPalettes)→ RGB 弧长参数化(消除调色板斜率影响)→
|
||||
12 px/传感器像素块中值采样到 160×120 → 3×3 高通。数据:用户双截图(竖屏)+
|
||||
真机连拍 3 帧(官方横屏 crop、我们竖屏,均 PNG 截屏无 JPEG 伪影)。
|
||||
|
||||
| 指标(弧长单位 ×1e-2) | 官方 | 我们 | 比值 |
|
||||
|---|---|---|---|
|
||||
| 整图低频 σ(对比度/音调曲线) | 20.2 | 21.2 | 1.05(一致) |
|
||||
| scene(>8px) σ(真实场景对比度) | — | — | 0.95~0.97(一致) |
|
||||
| 高频 σ(单帧 1~8px 频带) | 1.16~1.21 | 2.10~2.51 | **~2×** |
|
||||
| 时间分量(连拍差分/√2) | 0.52 | 0.75 | 1.44× |
|
||||
| **沿显示水平线均值的 std(=逐传感器行固定偏移)** | **0.106~0.15(max 0.57)** | **1.20~1.84(max 12.1)** | **8~17×** |
|
||||
|
||||
分块统计(背景块):scene 比 0.95、1-8px 频带比 1.58、时间比 2.0 —— 我们多出来的
|
||||
能量集中在 1~8px 频带且**逐帧可复现(固定)**。
|
||||
|
||||
### 16.3 结论与交接(下一步)
|
||||
|
||||
- **缺陷**:我们的渲染里有一个官方没有的**逐传感器行固定偏移**(残余行 FPN)。
|
||||
显示旋转 90° 后,传感器行=屏幕水平线 → 就是用户看到的"背景条纹"。
|
||||
它是固定的(连拍均值里都在),所以不是每帧算法、也不是显示插值(两边显示链等价:
|
||||
都是 160×120 数据 → 12 px/px 双线性上屏)。
|
||||
- **候选(按嫌疑排序)**:
|
||||
1. FFC 参考帧被污染/时序错位:官方与我们都"关 5 帧→采 4 帧→第 9 帧开",但我们的
|
||||
帧计数从自己的处理循环来;USB 抖动/丢帧会让采集窗错相(§9.4 曾测得
|
||||
"延到 8 帧反而变差"——设备实际快门相与我们假设的错位的旁证)。
|
||||
参考≠纯快门帧 → 减出的残差里留下行结构。
|
||||
2. DDT 段表 (gain,off) 的布局/插值在当前 FPA 温度下与我们不一致
|
||||
(我们 `rebuildTables(shutterAtFfc + fpaTempFix)`;官方 `SelectCaliCurve` 的温度
|
||||
来源、端点选择、Interpolate 的语义需要逐字段比对)。
|
||||
3. 盲元处理差异(我们已实现 `nucAndBlind`,但要和官方 `BlindCompensation` 的
|
||||
邻域定义逐条对——它用 10 int/条 的记录、邻居偏移含 ±1 与 ±行距)。
|
||||
- **验证路径(下一个模型从这里接)**:
|
||||
1. App 加"原始帧录制"开关(IrSession 读线程帧入口处写 files/,含一次完整 FFC 的
|
||||
60+ 帧与帧头);真机录一段。
|
||||
2. 离线重放:raw → 参考 → NUC → 表插值 → LUT,**每一级都算"沿行均值 std"**,
|
||||
找出引入行偏移的那一级;再用录到的数据做 A/B(改窗口/改表温度/改盲元)复现官方数值。
|
||||
3. 真机 A/B 验收指标就用 16.2 的表:目标"逐行固定偏移 std ≤ 0.2"。
|
||||
|
||||
@@ -489,6 +489,27 @@
|
||||
"未连接"分支显示,正常出图时用户看不到任何反馈)。
|
||||
- [x] 单测 66 → **76 项全绿**;debug + release(R8) 双构建通过;APK 已更新。
|
||||
|
||||
## 用户反馈修复 第三十七轮(2026-10-06 深夜,"官方背景条纹更不明显"——逆向排除全部候选,定位为逐行固定偏移;交接轮)
|
||||
|
||||
用户:"很明显啊,官方背景里面的条纹就是要更不明显,你看看逆向出来的代码,是不是还漏掉了什么"。
|
||||
本轮**只做了调查与测量,无代码改动**。完整证据与数据表见
|
||||
`docs/android_app/rendering_diff_phone_20261006.md` §16,交接清单也在那里(16.3)。
|
||||
|
||||
- 逆向:官方每帧链路(CalibrationMain_RTV + BlindCompensation + TempRangeStat +
|
||||
GrayEnlarge/HistDeRedundance)、内参(0x3808=1、0x380c=1、0x3804=baseLineAcc=4、
|
||||
0x3810=5、EX=0、增强=0)、FFC 时序(关5→采4→第9帧开)、表只在 FFC 窗口重建、
|
||||
setFrameRate 仅 devType1/2 —— 全部与我们一致,**没有遗漏的阶段**。
|
||||
- 测量(调色板弧长反演 + 真机连拍):对比度一致;高频噪声我们 ~2×;**主导项是
|
||||
"逐传感器行固定偏移":我们 std 1.2~1.84(max 12.1)vs 官方 0.11~0.15(max 0.57)**。
|
||||
- 下一步(按序):① app 加原始帧录制(含 FFC 窗口)→ ② 离线逐级重放找引入行偏移的级
|
||||
(参考帧污染/表插值温度/盲元邻域)→ ③ 修复后用 §16.2 指标验收(逐行 std ≤ 0.2)。
|
||||
- 现场状态:热像仪已被用户拔下充电;手机 rotation 被我锁成竖屏
|
||||
(`su -c 'settings put system accelerometer_rotation 0'`,原值 1,**测完要恢复**);
|
||||
官方 App 已 force-stop,我们的 App 在前台(USB 权限对话框"确定"在 (1193,1897),
|
||||
勾选框未勾,"一律打开"关联仍指向官方)。
|
||||
- 工具痕迹:`%TEMP%\mag160c_re\`(IDA 批处理脚本、libcsxx 反编译、analyzer.py、
|
||||
截图与 npy 中间件)——按约定属临时件,可删。
|
||||
|
||||
## 用户反馈修复 第三十六轮(2026-10-06 夜,"我们颗粒更大"→ 照片改单级放大,实时回退插值)
|
||||
|
||||
用户:"我们的app图片看起来像素颗粒更大啊,特别是高低温分界的边沿,是不是啥滤波没开。"
|
||||
|
||||
Reference in New Issue
Block a user