app+docs: 按真机 libcxsdk 反汇编定案——灰度 LUT 改用 Android 版 HistDeRedundance(固定基值/pivot=两段均值/步进上限),曲线插值温度补 fpaTempFix;推翻上轮'参考帧累积'机制(CAccumulator 是 4 帧块平均,与我们等价)
This commit is contained in:
@@ -262,3 +262,87 @@ raw 帧**逐个推进 `CAccumulator`(`Reset(pixels, baseLineAcc=4, 0)`,mode
|
||||
`PushBaselineRaw` 的语义),FFC(1) 之后重置;
|
||||
2. 用同一套灰度指标回归:目标空间 HF ≈0.34、帧间噪声 ≤4;
|
||||
3. 之后同步 csdk(pivot + 温度链 + 参考累积)。
|
||||
|
||||
## 10. 定案(真机 libcxsdk 反汇编 + 官方照片定量):显示 LUT 才是差异,§9 的机制被推翻
|
||||
|
||||
数据源换成**手机上的官方库本体**:`adb` 从官方 App 的 APK 目录取
|
||||
`lib/arm/libcxsdk.so`(arm32,本 App 只用 arm),IDB 里按 vtable 指针
|
||||
(`0x5a7xx` 段)解析出真实函数体,逐条指令核对(Hex-Rays 会吞掉隐式除数,
|
||||
必须看反汇编)。以下结论**全部以该反汇编为准**。
|
||||
|
||||
### 10.1 先纠正前两轮的错误结论
|
||||
|
||||
| 前结论 | 反汇编事实 |
|
||||
|---|---|
|
||||
| §8「官方不启用 CDF 75% pivot,所以我们要关掉」 | **错**。pivot 支路由 `theFunc._96_4_` 控制,`Controller::Controller()` 把它设为 **1**,全库无第二处写入 → 官方**是开着**的;而且它的写法不是 75% 分位,而是 `max(center_index, (meanBelow + meanAbove) >> 1)`。当时"关掉更接近"是因为**用的 LUT 本身是 PC 版**(结构与 Android 版不同),两点误差互相抵消。 |
|
||||
| §9.3「官方参考帧是长窗口 IIR 指数平均,比我们干净」 | **错**。`CAccumulator::PushFrame` 的 `mode≥4` 分支是**恰好 mode 帧的块平均**(`sum>>log2(mode)`,计满清零),mode=2 才是 `(buf+new)>>1`。`Controller::PushFrame` 的快门状态机对 **A+1..A+E 共 E=baseLineAcc=4 帧**各推一次 → 官方参考 = 4 帧块平均 = **和我们完全一样**。 |
|
||||
| §9.2「官方画面空间噪声比我们低 2.3×」 | **测量有分辨率偏差**:官方 App 显示的是 SDK 原生的 160×120 输出(照片 640×480 = 4×),我们的实时画面是 320×240(SDK 2× 后再 ×3 = 960×720 照片)。逐屏像素 HF 随放大倍数变化,两个 App 的放大倍数不同 → 该数字不可比。 |
|
||||
|
||||
### 10.2 官方每帧链路的完整配置(都已定位到 App 自己的调用)
|
||||
|
||||
`Controller::StartProcess(cb, fpaW, fpaH, sn, devType, shutterCloseSpeed,
|
||||
shutterOpenSpeed, ffcTriggerFrame, ffcTriggerTemperature, palette,
|
||||
baseLineAcc, caliPath)` —— 对应 App 侧
|
||||
`UsbCommunication.startTransfer()` 的实参;真机 BasePara2 实测:
|
||||
`shutterCloseSpeed=5, shutterOpenSpeed=4, ffcTriggerFrame=1800,
|
||||
ffcTriggerTemperature=250, enlargeRange=8, baseLineAcc=4, fpaTempFix=1699`。
|
||||
|
||||
| 阶段 | 官方取值 | 我们 |
|
||||
|---|---|---|
|
||||
| FFC 相位 A/E/B | 5 / 4(=baseLineAcc)/ 4 帧 | 5 / 4 / 4 ✔(`ffcStep`) |
|
||||
| 参考帧 | 4 帧块平均(`CAccumulator` mode=4) | 4 帧等权平均 ✔ 等价 |
|
||||
| 曲线插值温度 | `帧尾 FPA + fpaTempFix(1699)`(App 加,SDK 的 `SelectCaliCurve`/`GenerateVolatileLens` 用它) | **帧尾 FPA(少了 1699)✗ 本轮修复** |
|
||||
| 窗口 | `winLo=min(mean−range/2, statMin)`、`winHi=max(mean+range/2, statMax)`,`range=(enlargeRange*1000)>>3=1000`(对比度 0;`this+0x6c` 全库未写 → 亮度项恒不生效) | 一致 ✔(DDT 头 +20 读到的正是 8) |
|
||||
| 灰度 LUT | Android 版 `HistDeRedundance`(见 10.3) | **PC 版结构 ✗ 本轮修复** |
|
||||
| 时域平滑 `CSmoother` | 关(`this+0x380c = IntrinsicPara[0x20]`,构造默认 1,需 >1 才生效) | 未实现 ✔ |
|
||||
| 显示侧累积 `CAccumulator(+0x37a4)` | 关(`this+0x3808 = 1` → `Raw2Temperature` 直通) | 默认关 ✔ |
|
||||
| `setEX` 电子变倍 | 关(`imageEX` 默认 0 → `SetEX(0)` → `0x3814=0`) | 无此功能 ✔ |
|
||||
| 7×7 细节增强 | **开**:`MapTemperature` 把 `0x3864` 置 1 → `PushFrame` 随后无条件调 `FilterDetailEnhancement_Simple(gray, 255<<3=2040)` | 用户可开(默认 0)→ **待办** |
|
||||
| 翻转 | App 侧 `dwFlip` 只是存进全局 `0x6b90c` 结构,本库无人消费(翻在 App/显示层做) | 我们在显示/保存层做 ✔ |
|
||||
|
||||
### 10.3 真正的差异:灰度 LUT(Android 版 vs PC 版)
|
||||
|
||||
拿我们**自己照片里存的 NUC 计数块**与**官方照片**做像素级对齐(官方照片 = 官方实时渲染,两者同场景同机位):
|
||||
|
||||
- 垂直翻转后相关性 **r = 0.99** → **计数本身几乎一致**,差异**只在"计数→调色板索引"的映射**;
|
||||
- 官方映射 ≈ `0.84 × 我们的LUT + 21`(被"压缩并抬升"):官方平坦背景落在索引 **45–55 的一段平台**上,我们的旧 LUT 把它压到 **0–20**(暗端被压死)→ 这就是"官方对比度更高 / 更细腻 / 条纹更少"观感的来源;
|
||||
- 逐条核对反汇编后确认 Android 版 `HistDeRedundance` 与 PC 版(我们原来移植的)**结构不同**:
|
||||
固定基值 `16*(448+447*brightness/200)`(PC 版是"自动居中 + 时域平滑"的二分搜索)、
|
||||
步进上限 `max(1,(0x1800+4j)·k>>13)`(`k=min(0x200,16·span/range)`)、
|
||||
反向 CDF 从 `hist[pivot]` 起(PC 版从 `pivot+1`)、平滑后 `hist[1023]=hist[1022]`、
|
||||
pivot 用"两段均值的平均"。
|
||||
|
||||
**已落地**:`RenderPipeline.androidLutOf()` = 逐指令移植(含 golden 向量单测
|
||||
`AndroidLutTest`),实时会话 `androidLut = true`;PC 版路径保留,C 参考黄金测试不受影响。
|
||||
|
||||
### 10.4 在线拟合与遗留项
|
||||
|
||||
用官方照片做目标(同一 NUC 帧、逐像素比对,均方误差以索引计):
|
||||
|
||||
| 配置 | 平均误差 | 低端 p5/p25 |
|
||||
|---|---|---|
|
||||
| 我们旧 LUT(PC 版 + pivot 开,= 09-12 照片) | ≈35 | 8 / 17 |
|
||||
| 我们旧 LUT(PC 版 + pivot 关,= round-30 实时) | ≈14 | 15 / 29 |
|
||||
| **Android 版移植(k 按公式 = 21)** | **12.5** | 24 / 36 |
|
||||
| Android 版移植,k=16(拟合最优) | **5.9** | 45 / 54 |
|
||||
| 官方照片实测 | — | 45 / 52 |
|
||||
|
||||
→ 移植已在正确轨道上;**遗留一处常数**:反汇编算出 `k = 16·span/range = 21`,
|
||||
数据偏好 ≈16。两个可能来源,都需要真机同刻 A/B 才能定:
|
||||
① 计数统计仍有细微差别(最可能就是 §10.2 的 `+fpaTempFix`,它改变插值曲线→改变计数分布);
|
||||
② 该 build 的 `v45` 常数与反汇编读出的 16 不同(已在反汇编里逐位核对过 `LSLS R6,R0,#4` + `uidiv`,倾向排除)。
|
||||
**在真机上先验证 `+fpaTempFix` 是否让计数分布与官方一致**,再看 k。
|
||||
|
||||
### 10.5 本轮已改代码
|
||||
|
||||
1. `RenderPipeline.androidLutOf()`:Android `HistDeRedundance` 逐指令移植(新增,含测试);
|
||||
2. `IrSession` 实时管线改用 `androidLut = true`,删除 round-30 的 `cdfPivot75 = false` 临时开关;
|
||||
3. `RenderPipeline.fpaTempFix`(构造参数)+ `ffcStep`/`frameRemote` 调 `rebuildTables(shutter + fpaTempFix)`,
|
||||
`IrSession` 从 `BasePara2` 传入(官方 `UsbCommunication` 同款语义)。
|
||||
|
||||
### 10.6 待办
|
||||
|
||||
1. 真机 A/B(手机当前被 PIN 锁屏,需机主解锁):同一静止场景,官方实时 vs 我们实时,用"调色板反解灰度 + 逐像素对齐"复核 10.4 的 k/计数假设;
|
||||
2. 7×7 细节增强按官方默认打开(强度 2040)并回归——本轮先不动,因为离线拟合显示我们的
|
||||
`DetailEnhance` 在 2040 下反而略微变差,疑移植细节待核;
|
||||
3. 同步 csdk(Android 版 LUT + fpaTempFix + 温度链)。
|
||||
|
||||
Reference in New Issue
Block a user