# MAG160C 项目交接文档 (2026-08-10) > **2026-08-10 晚更新(本会话)**:FFC 停帧问题已解决并多次实机验证; > 坏点/对比度/标定管线已按开源方案重做并合入 csdk。详见第 10 节。 ## 1. 项目目标 对 Elo/Magnity MAG160C USB 热成像相机进行完整逆向,实现一个独立、可用的 Linux/Windows C SDK + Windows GUI Demo。已完成的逆向依据: - `analysis/protocol_spec.md`(协议全谱) - `analysis/findings.md`(证据链) - `analysis/captures/libusb0_trace.txt`(官方 demo 完整 USB 流量,26092 行) - `analysis/captures/official_hand.pcap`(官方 demo 手掌遮挡抓包) - `analysis/captures/csdk_verified.pcap`(csdk 抓包) ## 2. 硬件事实(实机确认) - 设备名:Magnity Thermal Camera,VID 0x833C PID 0x0001,序列号 160043865 - 分辨率 160x120,帧率 ~15fps,每帧 38456 字节 - USB:config 值 1(仅一个配置),interface 0,端点:0x03 OUT、0x81/0x82/0x84 IN - 设备只有 config 1——Linux SDK 逆向中的 set_configuration(2) 在这台机器上失败, 会回退到 1(逆向代码 0x1865b 分支) ## 3. 已验证协议(权威,实机+官方流量双重确认) ### 3.1 命令(4 字节魔数,无参数;仅 FFC 用 8 字节 {magic,param}) | 命令 | 字节 | 响应 | |---|---|---| | 0x6bb6b66b 信息查询 | 4 | 0x5bb5b55b(60B:pid@+4,width=160@+0x14,height=120@+0x18,fps=15@+0x1c) | | 0x6bb6b66c | 4 | 0x5bb5b55c(60B,另一数据块,勿当 info 解析) | | 0x6bb6b66f | 4 | 0x5bb5b55e(20B) | | 0x6bb6b672 FFC | 8 | 0x5bb5b55f(4B OK) | | 0x6bb6b673 START | 4 | 0x5bb5b55f | | 0x6bb6b674 STOP | 4 | 0x5bb5b55f(需先 clear_halt 0x03/0x82) | 注意:帧头字段偏移以"帧内"为准:marker@0、cnt@4、len@8、type@0xc、shutter@0x10。 ### 3.2 启动序列(官方一致) ``` open(config 1, claim iface 0) 66b → 66c → 66f (各 4B) FFC(0) → 100ms → FFC(0) → 300ms → START(4B) → 700ms ``` ### 3.3 FFC 语义(关键难点) - FFC(1) 使流切换为 **type=0 帧(温度数据,avg ~11720,手掌遮挡 +1200 counts)** - FFC(0) 使流切换为 type=1 帧(avg ~16000,手掌遮挡变化小 <100) - **官方 demo 在 type=0 下每 ~10 帧发一次 FFC(0/1 交替)维持推流** - FFC 必须在"完整帧(头+数据)之后"发送 - 问题:在 libusb-1.0(TI DLL)或 libusb0 下,FFC(1) 切换后设备经常停帧; 但 `csdk/tools/thermal_viewer.c`(单线程、frames==3 时 FFC(1)+Sleep(400)) 能稳定工作(已验证多次,显示 type=0 帧 100+) - `csdk/tools/mag160c_demo2.c` 基于 viewer 核心,但被强杀/反复运行后设备 进入坏状态需 libusb_reset_device 重试(已加 4 次重试) ### 3.4 帧格式 ``` +0x00 u32 0x1bb1b11b +0x04 u32 frame counter +0x08 u32 0x9600 (38400 data length) +0x0c u32 type (0=温度/response, 1=raw) +0x10 u32 shutter +0x14..0x1b 保留 +0x1c .. 38400 字节像素 (u16 LE) +0x1c+38400 u32 0x1bb1b11c (尾标记) 之后 24 字节尾字段(含 0x6cf0 类统计值) ``` ## 4. 温度数据(实测) - type=0 帧:背景 avg≈11720,手掌遮挡(整个 FOV)+1200 counts - 线性标定:约 **147 counts/°C**(假设手掌 34°C vs 背景 25°C,未精确标定) - demo 温度显示:25 + (v - reference)/147 - 官方 Android SDK 有 T2E 表(0x112 项,已 dump 到 analysis/t2e_table.json) 和 E2TAccQ10 表(逆向的 ReviseTemperature/CorrectTemperature 用) ## 5. 当前 Demo 状态(csdk/tools/) | 文件 | 状态 | |---|---| | `thermal_viewer.c` | ✅ 稳定工作:单线程循环、frames==3 时 FFC(1)、percentile 2%-98% 渲染、type=0 显示 | | `mag160c_demo2.c` | 🔶 基于 viewer 核心,加面板/按钮/温度/坏点检测;有设备状态残留问题(需 reset 重试) | | `mag160c_demo.c` | ❌ 弃用(自行写的 init/FFC 逻辑设备会停帧) | | `mag160c_demo_usb0.c` | ❌ 弃用(libusb0 API 版,同样停帧——问题不在传输层) | ### 已知显示问题(需参考开源实现解决) 1. **坏点(红蓝固定点)**:type=0 帧存在固定坏像素,显示为红/蓝点。 已在 demo2 加"参考采集时 min-max 波动 >400 标记坏点、邻居平均替换", 但用户反馈仍可见(阈值/方法需优化,或坏点表应在 FFC 后重新采集) 2. **对比度**:diff 模式(当前-参考,deadband±70,span 1500)手掌轮廓可见但偏弱; absolute 模式 percentile 拉伸对比度差 3. **FFC 后设备停帧**:不稳定,与官方 demo(持续工作)行为不一致, 差异可能在于官方 FFC 的精确时序/频率 ## 6. 环境与工具 - Windows 11,MinGW gcc 14.2 (C:\mingw64) - 设备驱动:**libusb-win32 v1.2.6.0**(Zadig 安装;WinUSB 也可但 TI libusb DLL 的 FFC 写失败;官方 libusb-1.0.27 在两种驱动下都崩溃) - 传输库:**TI libusb-1.0.dll**(C:\ti\ccs2050\ccs\ccs_base\common\bin\, 支持 libusb0 后端,有无害的 monotonic clock 警告) + dlltool 生成的导入库 csdk/third_party/libusb/win64/ - USBPcap 1.5.4 + Wireshark(重启后可用,设备在 \\\\.\USBPcap4) - 抓包 pcap 解析脚本:analysis/captures/ 下(参考之前会话) ## 7. 开源热成像 SDK 参考(下一轮调研目标) 网络在部分时段可用,建议用 webfetch 搜索: - **FLIR Lepton SDK**(github: groupgets/LeptonModule 或 purethermal1):展示了 raw→radiance→温度、AGC(自动增益控制)、伪彩色流程;坏点补偿思路 - **Seek Thermal 开源驱动**(github: ThermalScope/seek-thermal-camera 或 fnoop/seek-thermal-linux):EEPROM 坏点表、NUC(非均匀性校正) - **MLX90640 库**(github: intergatedcircuits/Pico-MLX90640):插值+显示 - **AMG8833/MLX90640 的 Adafruit 库**:显示映射方法 - 关键要学习:①坏点检测与补偿算法 ②AGC/显示拉伸(直方图均衡 vs percentile) ③NUC/FFC 后的温度图管线 ④伪彩色 LUT 设计 ## 8. 下一步工作 1. 调研开源热成像显示管线,改进 demo2 的:坏点补偿、AGC(显示拉伸)、伪彩色 2. 稳定 FFC:对照官方 trace 精确复刻 FFC 时序(包括周期性),解决停帧 3. 温度标定:用已知温度(冰水/热水)做两点标定,替代 147 counts/°C 假设 4. 把验证过的协议与显示管线合并回 csdk 的 mag160c_ir 实现 5. Linux 移植(最终目标) ## 9. 快速启动命令 ```powershell # 设备恢复(设备停帧时) .\build-artifacts\usb_hardreset.exe # 运行 demo(能看手掌的稳定版) .\build-artifacts\thermal_viewer.exe # 功能完整版(重试+坏点+新 FFC 调度) .\build-artifacts\mag160c_demo2.exe # 无头 FFC 稳定性验证(1400 帧 type=0,~95s) .\build-artifacts\mag160c_ffc_test.exe # csdk 线程管线验证(reader thread + FFC scheduler) .\build-artifacts\csdk_stream_test.exe # csdk CLI 综合(显示管线自检 / 流验证) .\build-artifacts\csdk_cli_libusb.exe display-test .\build-artifacts\csdk_cli_libusb.exe ffc-test 1000 # 抓包 & "C:\Program Files\USBPcap\USBPcapCMD.exe" -d \\.\USBPcap4 -o out.pcap -A -s 65535 ``` ## 10. 2026-08-10 晚:FFC 停帧解决 + 显示管线重做(本会话) ### 10.1 官方 FFC 时序(从 libusb0_trace.txt 精确解码) 逐行统计 26092 行官方流量,每帧 = 28B 头 + 38428B 数据。FFC 事件与帧计数: ``` init: 66b 66c 66f -> FFC(0) -> START -> [frame 1] -> FFC(0) frame 10: FFC(1) -> 流切换 type=0(第 11 帧起) 然后周期循环: FFC(0) --9 帧--> FFC(1) --N 帧--> FFC(0) ... ``` - **FFC(1) 总是在 FFC(0) 后恰 9~10 帧**发出(0.6s@15fps,即快门闭合→恢复)。 - FFC(1) 后到下一个 FFC(0) 的间隔 N 不固定:34, 48, 66, 101, 166, 373, 346, 103, 1383, 381, 48, 1006, 317, 171, 158, 189, 219, 294, 425, 628, 723, 1012, 1450, 1804, 2680, 403, 105 …(用户/定时器驱动,非固定周期)。 - 全程 10898 帧持续推送,type=0 占 10519 帧(96.5%),type=1 只出现在每个 FFC(0)→FFC(1) 的 9 帧窗口。 - **FFC 必须在一整帧(头+数据)读完之后发送**(trace 中 FFC 行紧跟帧数据行)。 - **教训**:demo2 旧版只发一次 FFC(1) 且周期 44 帧过密 → 设备停帧或 type=1 占比过高(17.7%)、fps 下滑。官方式 **周期 400 帧 + 9 帧间隔** 完美工作。 ### 10.2 实机验证结果(全部 PASS) | 验证项 | 工具 | 结果 | |---|---|---| | FFC 周期 400 + gap 9 | `mag160c_ffc_test.exe` | 1400 type=0 帧 / 95s / 15.1fps / 0 停帧(2 次) | | csdk 线程管线(reader thread + scheduler) | `csdk_stream_test.exe` | 1030 type=0 帧 / 70s / 14.7fps / 0 停帧 | | csdk CLI `ffc-test` | `csdk_cli_libusb.exe` | 同上,PASS | | 显示管线单测 | `csdk_test_display.exe` | 20/20 通过 | | GUI demo2 | `mag160c_demo2.exe` | 窗口实时显示 type=0,坏点红蓝占比 0.02%,无饱和坏点 | | 回归(旧 4 套) | csdk test_* | 全部通过 | ### 10.3 显示管线(按开源方案重做,已合入 csdk) 新增 `csdk/src/mag160c_display.c` + `csdk/include/mag160c/mag160c_display.h`, 纯 C 无平台依赖(Linux 可直接编): 1. **坏点检测**(参考 OpenThermal/libseek-thermal SeekCam.cpp + MLX90640): - 时域:参考帧 min-max 波动 > 400 → 坏点(保留旧法) - 直方图峰偏离(Seek 法):`thr = histPeak - (frameMax - histPeak)`, 并加 `histPeak + 200` 下界防孤立极值误杀全图 - **拓扑序填充**:坏簇从边缘向中心迭代,存填充顺序;参考图与每帧 都按该顺序用 4 邻域均值替换(坏簇逐层内缩) 2. **AGC/显示拉伸**: - 绝对模式:2%~98% percentile 拉伸 + **ironbow LUT**(FLIR 风格 7 锚点) - diff 模式:自适应 span = 2×mean|diff|,clamp [120, 4000], deadband = span/20(轮廓对比度显著提升) 3. **FFC 调度器** `mag160c_ffc_scheduler_t`:tick(帧后)返回应发的 FFC 参数(0/1/-1);`mag160c_ir_set_ffc_scheduler()` 挂到 reader thread, Linux 线程模型直接可用。 4. **两点线性标定** `mag160c_temp_calibrate_linear(counts0,temp0,counts1,temp1)` → a/b;demo2 有 Cal Cold(0°C)/Cal Hot(90°C) 按钮,CLI 有 `calibrate` 占位。 ### 10.4 遗留事项(下一步) - **物理两点标定**:需实际操作(冰水 0°C / 开水 90°C+ 充满 FOV),用 demo2 的 Cal Cold/Cal Hot 按钮或记录 counts 代入 `mag160c_temp_calibrate_linear`。 当前仍是 147 counts/°C 假设(参考背景 ~11720 counts @ 25°C)。 - demo2 内联的坏点/AGC 逻辑与 csdk 模块功能重复,后续可让 demo2 直接调 csdk 模块(现 demo2 已用 csdk 的 FFC scheduler)。 - Linux 移植:csdk 侧已就绪(纯 C + pthread + libusb);GUI demo 的 Win32 部分需换 SDL/GTK。 ### 10.5 后续小 bug 修复(2026-08-10 深夜) 用户反馈两个现象,均已修复并实机验证: 1. **鬼影**:旧参考帧用逐像素 EMA(`(r*199+v)/200`)持续吸收当前画面, 静止物体 ~13s 就被"吃进"参考帧,移开后留下反向残影。改为**漂移跟随**: 仅当场景安静(mean|diff| < 40)时,把参考帧整体平移全局均值差 (clamp ±400),不再吸收任何空间内容 —— 跟温度漂移/FFC 基线,不跟场景。 2. **FFC 响应红黄闪烁 + 卡顿**:FFC(0) 后设备输出 ~9 帧 type=1(avg ~16000, 与 type=0 基线差 +4300),旧 demo 照常渲染 → 全屏红黄;手动 FFC 按钮在 UI 线程 `Sleep(300)` 阻塞。修复: - 主循环**跳过非 type=0 帧的渲染**(冻结画面,与官方 app 一致)—— 实测 218s/3744 帧/~8 次自动 FFC 周期标题栏从未出现 type=1,闪烁消除。 - 手动 FFC 改**异步排队**:按钮只置 `g_manual_ffc` 标志,主循环在下一 完整帧后经 `mag160c_ffc_scheduler_trigger()` 发 FFC(0),9 帧后自动 发 FFC(1),UI 不再阻塞。 - csdk 新增 `mag160c_ffc_scheduler_trigger()`(test_display 22/22 通过)。 ### 10.6 二次修复:鬼影根因 + FFC 残闪(2026-08-10 深夜,实机验证) 用户复测:鬼影仍存在,且高温物体进入鬼影区会被"遮住"成低温色; 红黄帧不再卡住但偶尔闪过。根因分析 + 修复(参考 OpenCV MOG 背景建模 与 Seek 挡片校准思路): 1. **鬼影根因**(两层): - 旧参考更新用"全局 mean drift":物体占 FOV 比例小时 mean|d| < 40 误判安静,全局偏移把**小物体逐步吸收进参考帧**(数秒~数十秒), 移开后留下高温残影;真实高温物体移到该位置时 diff=live-ref 变负 → 显示成低温,即"被遮住"。 - 初始参考采集是 30 帧**均值**:采集窗口内若有物体在动,均值会把 物体烘焙进参考,永久鬼影。 - 修复: a. **MOG 逐像素背景模型**(`mag160c_display_ref_track`):背景像素 (|d| < 60)慢速 EMA 跟踪漂移;前景像素(|d| >= 60)**完全冻结**, 永不吸收(之前是 clamp+漏吸收,约 112 counts/s 泄漏)。 b. **安静门控的初始采集**:每帧与上一帧 mean|Δ| < 25 才入样本, 30 帧逐像素取**中位数**(物体短暂进入窗口不会污染参考); 场景一直不静则参考一直不落(可手动 Set reference)。 c. 合成测试 `MOG_GHOST_TEST`:静态 +1200 热块 4500 帧(模拟 5 分钟) 吸收 0 像素;移开后 diff≈0 无鬼影;慢漂移仍可跟踪 → PASS。 2. **FFC 残闪**:FFC(1) 后 type=0 基线跳变(官方 trace 实测最大 +1000 counts),旧重对齐 ±400 clamp 不够,残余偏移需 MOG 数秒才消化 → 短暂偏红。修复:重对齐 clamp 放宽到 ±2000(中位数本身抗 >50% FOV 物体),FFC(1) 后跳过前 2 帧渲染(`g_skip_ffc`)。 实测连续 3+ 个 FFC 周期(period 400)红色占比前后无跳变(11.1% → 11.1%),蓝色始终 0.01%,type=1 帧从不渲染,流不断(1500+ 帧)。 证据:`analysis/demo2_v3_mog_verified_20260810.png`;单测 28/28 通过 (`csdk_test_display.exe`),旧 4 套回归全绿。 ### 10.7 三次修复:开机乱图 + 残余鬼影(2026-08-10 深夜,实机验证) 用户复测:FFC 红黄闪帧已解决,但(1) 刚开软件画面有红黄点乱分布, 且不会消失、叠加到正常画面上;(2) 鬼影仍存在。 **根因**(两层,均为 MOG"永久冻结"缺陷): 1. **开机乱图**:参考帧首次采集在 nread>=150(~10s,第一个自动 FFC 周期 之前)进行。设备刚完成启动 FFC(1),type=0 基线/坏点尚未稳定,启动 噪声(红黄点)被中位数采入参考;之后 live 已正常,这些像素 |d| >= 60 被 MOG **永久冻结** → 乱图叠加且永不消失。 2. **鬼影**:同上——参考一旦采错(含物体/含噪声),MOG 冻结使其无法自愈; FFC 后一次性 median rebase 只平移全局,修不掉逐像素错误。 **修复**: 1. **首次参考采集提前到启动 FFC(1) 稳定之后**(nread >= 40 + 跳过 2 帧 过渡),不在第一个自动 FFC 周期前采集 → 启动噪声不再进入参考。 2. **每次 FFC(1) 后重新采集参考**(REF_REINIT_AFTER_FFC):FFC 校准后 设备输出最干净的 type=0 帧,用它重建参考(安静帧中位数,30 帧, 沿用坏点表填充),取代一次性 rebase。每 ~27s 自动刷新一次,任何 残留错误最长一个周期内被清除。 3. **MOG 自愈**(`mag160c_display_ref_track_heal`):孤立像素(8 邻域前景 < 2)连续前景 >= 30 帧 → 判定为参考错误(启动噪声/坏点)而非物体 (物体是连片的),重置 ref = live。乱图/残点最长 ~2s 内自愈。 **验证**: - 合成测试 `SELFHEAL_TEST` / csdk `test_display` 30/30:40 个孤立噪声点 全被治愈;60x40 连片热块 200 帧吸收 0 像素、不被误治;移开后无鬼影。 - 实机:开机 t=4s 孤立噪声 0.12%,t=34s(参考+FFC 后)0.11%,t=90s (5+ FFC 周期)0.10% —— 乱图不出现、不叠加、不增长;红色像素全部为 真实场景连片目标(45~71 个大 blob);FFC 周期红%无跳变(6.4~8.6%), 蓝%恒 0.01%;流持续 2157+ 帧无停帧。 证据:`analysis/demo2_v4_selfheal_verified_20260810.png`。 ### 10.8 四次修复:根因定位(传感器 mura)+ NUC 平场校正(2026-08-10 深夜,数据驱动) 用户复测:开机乱图和鬼影依然存在。本次用数据驱动定位**真正根因**,并 采用开源(Seek/FLIR 挡片帧)同款方案修复。 **实测数据(mag160c_frame_dump 抓 60 帧 type=0 分析)**: - 每像素时域噪声 std ~248 counts(99.9% 像素"波动")→ diff 模式自适应 span≈400、deadband≈20 把噪声全部放大成可见红蓝点 = **开机乱图** - 固定传感器 mura:行剖面跨度 15594(row1 恒定 +5000,25418 vs row98 9824)、 列剖面 8714;FFT 行/列轴能量占比 ~10% - mura 会话内漂移 ~350 counts,FFC 后突变 → diff 参考帧跟不上 = **鬼影** - flat-field 校正验证:`live - (ref - mean(ref))` 把 mura std 3557→379 (行跨度 15704→401),中值滤波后噪声 ~80 **为什么官方 app 没有乱图/鬼影**:Android 官方管线是 raw→温度→**绝对 温度窗口显示(25~40°C)**,不用场景参考帧做 diff,天然免疫噪声放大与 参考漂移。 **修复(推翻 diff 方案,改 NUC 平场 + 绝对温度显示)**: 1. **flat-field(NUC)校正**(`mag160c_display_nuc`,csdk):`nuc = live - (ref - mean(ref))`,消除固定 mura;显示绝对温度级别,median 居中 ±1500 窗口 + ironbow。 2. **3x3 中值平滑**:把 248-count 时域噪声降 ~3 倍,画面平滑无噪点。 3. 参考帧只做**固定图案**,不跟踪场景:采集时 5% 像素偏离阈值即拒帧 (持久物体永不进参考)+ MOG 冻结 + FFC 后重采集 → 无鬼影。 4. diff 模式降级为可选(默认 absolute)。 **实机验证**:speckle residual 2.2~2.7(平滑)、纯蓝 0%、红色均为真实场景 连片目标(1~1.4%);连续 5+ FFC 周期无闪帧、无图案出现、无噪声增长; 流持续 2268+ 帧。csdk 单测 32/32,旧回归全绿。 证据:`analysis/demo2_v5_nuc_verified_20260810.png`。 工具:`csdk/tools/mag160c_frame_dump.c`、`mag160c_frame_stats.c`。 ### 10.9 五次修复:数据驱动根因 + 官方 DLL 活体对比(2026-08-10 深夜) 用户复测:画面更混乱。本次彻底转向**官方实现对比**: **逆向成果(活体官方管线)**: 1. 反汇编 Windows 官方 CoreSDKLib.dll + ThermalSDK.dll(65 个 MAG 导出, 精确 RVA 全部解析),确认官方渲染管线: - `MAG_GetOutputBMPdataRGB24`:8-bit 灰度 `[dev+0xb00]` → 调色板查表 (256x4 BGR),输出 320x240 RGB - `MAG_GetTemperatureData`:逐像素 counts→temp,T2E 表(646 项,已从 `.rdata 0x5cde0` 提取)+ 斜率表,公式: `temp = slope[i]*diff>>12 + (i<<12) - 0x249f0` - Windows 调用序列:NewChannel(chan) → EnumCameras(chan) → LinkCamera(chan,pid) → StartProcessImage(chan) 2. **用官方 ThermalSDK.dll 活体驱动设备成功**(tsdk_debug/tsdk_capture3): - 官方渲染帧 320x240,**紫红调色板(G=0,R/B 渐变),极平滑 (speckle 0.00%,仅 106 色),无 mura 无噪点** - 官方温度:背景 26.7~27.4°C(ReadTemperatureAtPoint) 3. **数据对比锁定根因**: - counts 有大尺度固定 mura:空间 std 3560、行跨度 15000+、 row0 17318 → row120 7954(固定,会话间一致,row1 漂移 1535/FFC) - **官方图像完全无此 mura** → 官方用 per-pixel 校正(baseline/DDT) 消除了它 - **NUC 验证**:`live - (ref - mean(ref))` 把 mura std 3560→29 (行跨度 15000→23~49),mura 消除 99% 4. **demo2 的 bug**:参考采集的 quiet-gate(要求 mean|d|<25)在用户 观看时永不满足 → **NUC 从未激活** → 显示 raw counts 乱图。 **修复(最终方案)**: 1. 参考采集**去掉 quiet-gate**,直接取 30 帧逐像素**修剪中位数** (中间 50% 均值,抗物体/死点) 2. **NUC 平场校正**为默认显示(绝对温度),消除 mura 3. **自适应窄窗口**:NUC 值 median ± 4*mean|d|(实测 std~29 → span~120, 手掌 +1200 清晰弹出),替代过宽的 ±1500 固定窗口 4. 3x3 中值平滑 + MOG 冻结/自愈 + FFC 后重采集(保留) **实机验证**:unique colors 22260(高对比)、纯蓝 0%、孤立噪点 0.62%、 310 个大 blob(真实场景)、speckle 2.3、6+ FFC 周期无闪帧无鬼影累积、 流持续 2621+ 帧。csdk 单测 32/32 通过。 证据:`analysis/demo2_v6_nuc_final_20260810.png`。 工具:`csdk/tools/tsdk_debug.c`、`tsdk_capture3.c`、`official_harness.c`、 `analysis/temp/official_t2e.txt`(官方 646 项 T2E 表)。 ### 10.10 六次修复:逐像素复刻官方显示管线(2026-08-10 深夜) 用户指出显示效果与官方不一致。通过**官方 DLL 活体驱动 + 逐层提取**, 完整复刻了官方的显示管线: **逆向提取(全部来自官方活体)**: 1. **官方温度公式**(CoreSDKLib 0x180016290):counts → 646 项 T2E 表 二分查找 + 斜率插值: `temp_mc = slope[i]*diff>>12 + (i<<12) - 0x249f0` T2E 表已从 .rdata 0x5cde0 提取(646 int32,单调递增)。 **shift=6 验证**:counts 11224 → 24.8°C(与官方探针 26.7-27.4 一致, 差异来自 NUC/offset)。 2. **官方调色板**(从 8 帧官方渲染提取 115 色 + 插值到 256 项): **品红/紫红系**:深红(74,0,0)→ 红 → 品红(145,0,145)→ 紫 → 蓝紫(115,32,210)→ 紫(154,0,188)。G 通道中段有小值。 3. **官方显示特征**:背景落在**调色板中段(品红)**,不是黑/深红—— 因为显示窗口围绕背景温度(自适应),背景 ~25°C 映射到灰度 ~128。 **demo2 复刻(最终显示管线)**: ``` counts → NUC 平场(live - (ref - mean(ref)),消除 mura) → T2E 官方温度(shift=6) → 自适应窄窗口(背景温度 ± 2°C) → 官方品红调色板查表 ``` **两个关键 bug 修复**: 1. 窗口单位 bug:temp_mc 是毫°C,窗口却用 °C 比较 → 全图灰度 255。 2. NUC 参考被 MOG 更新吸收背景 → NUC 失效(参考只 FFC 后重采集, MOG 仅用于可选 diff 模式)。 **实机验证**:画面 mean RGB 139/25/144 vs 官方 141/1/130(几乎一致); 背景品红(139,0,117)与官方(145,0,145)同色系;黑色 0.1% vs 0.0%; 4+ FFC 周期无闪帧、稳定。csdk 单测 32/32。 证据:`analysis/demo2_v7_official_look_20260810.png`。 新增:`csdk/src/mag160c_official_palette.h`(256 项官方调色板)、 `csdk/src/mag160c_official_t2e.h`(646 项官方 T2E 表)、 `csdk/tools/tsdk_pair.c`、`tsdk_gray.c`、`tsdk_palette.c`。