Files

10 KiB
Raw Permalink Blame History

MAG160C 逆向交接文档 v2(2026-08-11)

本文件是当前最新、最完整的上下文快照。 覆盖硬件/协议/官方SDK逆向/ 显示管线演进/全部失败教训。下一轮请从第 1 节开始读,严格按第 7 节 的方法论执行。

1. 项目目标

对 Elo/Magnity MAG160C USB 热成像相机(160x120, 15fps)完整逆向:

  1. 官方从"USB 读取 raw → 显示到屏幕"的完整管线逐层复原
  2. 自研 C SDK(csdk/)+ Windows demo 的最终屏幕画面必须与官方 app 一致
  3. Linux 移植(最终目标)

2. 硬件与协议(已验证,权威)

2.1 USB 拓扑

  • VID 0x833C PID 0x0001,序列号 160043865,config 1,interface 0
  • 端点:0x03 OUT(命令)、0x82 IN(命令响应)、0x81 IN(帧流)、0x84 IN(大读取,未用)
  • 驱动:libusb-win32 v1.2.6.0;传输库:TI libusb-1.0.dll + dlltool 导入库

2.2 命令(已验证,与官方流量一致)

命令 字节 响应
0x6bb6b66b 4 0x5bb5b55b 60B(pid@0, w=160@0x10, h=120@0x14, fps=15@0x18)
0x6bb6b66c 4 0x5bb5b55c 60B(另一块,勿当 info)
0x6bb6b66f 4 0x5bb5b55e 20B
0x6bb6b672 FFC 8(magic+param) 0x5bb5b55f 4B
0x6bb6b673 START 4 0x5bb5b55f
0x6bb6b674 STOP 4 0x5bb5b55f(需先 clear_halt 0x03/0x82)

启动序列:66b → 66c → 66f → FFC(0)×2 → 300ms → START → 700ms

2.3 FFC 语义与时序(已精确解码,稳定方案已验证)

  • FFC(1):流切换为 type=0(温度数据,手掌 +1200 counts)
  • FFC(0):流切换为 type=1(raw)
  • 官方 cadence:FFC(0)→ 恰 9 帧 → FFC(1)→ 间隔 34~2680 帧 → 循环
  • 已验证稳定方案:period=400 帧 + gap=9 帧(FFC 必须在完整帧后发)
  • 实测:1400+ type=0 帧 / 15.1fps / 0 停帧(多次)

2.4 帧格式(重要:像素偏移!)

28B 头: 0x1bb1b11b | cnt | len=0x9600(38400) | type | shutter | 保留
38400B: 像素 u16 LE
28B 尾: 0x1bb1b11c @ offset 38400 | 统计值(如 0x7839)

关键:第二次 bulk read 返回 38428 字节 = 38400 像素(从偏移 0 开始)+ 28 尾。 demo 曾用偏移 +28 读像素是错的(错位 14 u16)。 正确:像素从 data[0] 开始。

3. 实机数据(决定性事实)

3.1 counts 数据特征

  • 背景 counts 均值 11224(会话间 1122413431 漂移)
  • 巨大固定 mura:空间 std 3560,行跨度 15000+ (row0 ~17318 → row120 ~7954,row119 回升;两个会话剖面几乎相同)
  • row1 会话内恒定(+5000),漂移 62~1535(FFC 状态不同)
  • 每像素时域噪声 std ~248 counts(99.9% 像素波动,非坏点)
  • 坏点:min=0/max=45340 恒定出现的像素(少数)

3.2 NUC 验证(关键结论)

  • live - (ref - mean(ref)):mura std 3560 → 29,行跨度 15000 → 23~49
  • NUC 后温度(官方 T2E shift=6):24.9°C 均匀(std 0.19),与官方探针 26.7~27.4°C 接近
  • 结论:NUC 平场校正是消除 mura 的正确方法

4. 官方 SDK 逆向成果(本会话最大收获)

4.1 可活体驱动的官方管线

Windows 官方 CoreSDKLib.dll(490KB, 65 导出,精确 RVA 已解析)+ ThermalSDK.dll(90KB, 19 导出)。ThermalSDK 高层 API 可直接驱动设备:

// 已验证可用的调用(tsdk_debug/tsdk_capture3/tsdk_gray/tsdk_palette):
SetDllDirectoryA("C:\\Project\\MAG160C\\IR_Camera_SDK-1.0.1\\windows\\windows\\app");
LoadLibraryA("ThermalSDK.dll");   // 依赖同目录 CoreSDKLib.dll 等
SetUnitMode(0); SetTempBoundary(30,44,37); SetNewIRFrameDelegate(onIR);
Start();  // 内部:NewChannel(0) -> EnumCameras -> LinkCamera(chan,pid) -> StartProcessImage
// 回调:onIR(buf, 320, 240, 3) 拿到官方渲染 RGB 帧(2x 放大)
// ReadTemperatureAtPoint(x, y, res) -> 16B 结构, tempRaw=double @16, tempArm=double @24

4.2 已提取的官方数据(analysis/ 目录)

数据 位置 说明
官方 T2E 表(646 int32) analysis/official_t2e_table.txt 从 .rdata 0x5cde0 提取,单调递增 51→4200129
官方渲染帧 ×8 build-artifacts/official_ir_00..07.rgb 320x240 RGB,品红系
官方灰度图 build-artifacts/official_gray.bin 160x120,93% 像素=0,顶部14行坏点带
官方调色板(错误读取) build-artifacts/official_palette_live.bin Jet 色系 BGR,疑似偏移错误,勿用
官方调色板(帧反推 115色) analysis/temp/official_palette_full.npy 品红系,可信
官方探针温度 记录在 handoff 背景 26.7~27.4°C
官方 T2E 表(已转C头) csdk/src/mag160c_official_t2e.h 646 项
官方调色板(已转C头,插值) csdk/src/mag160c_official_palette.h 256 项,品红系(可能需修正)

4.3 官方温度公式(0x180016290 反汇编,权威)

x = counts << (7 - shift)          ; shift 参数运行时确定(本机验证=6)
i = 二分查找 T2E[i] <= x < T2E[i+1]
diff = x - T2E[i]
slope[i] = (0x1000000 + (T2E[i+1]-T2E[i])/2) / (T2E[i+1]-T2E[i])
temp_mc = (slope[i]*diff >> 12) + (i<<12) - 0x249f0   ; 毫°C

验证:counts 11224 → shift=6 → 24.82°C;12500 → 31.83°C;13000 → 34.48°C NUC 后背景 → 24.9°C(均匀)。

4.4 官方渲染机制(部分逆向)

  • MAG_GetOutputBMPdataRGB24(chan, buf, size, order):8-bit 灰度 [dev+0xb00] → 调色板查表(256×4 BGR)→ 输出 320x240 RGB
  • MAG_GetOutputBMPdata(chan, w, buf):返回灰度缓冲指针 dev+0xaf0(19200B)
  • 未逆向:counts → 灰度(dev+0xaf0)的生成逻辑(AGC/温度窗口在哪)
  • 未确认:调色板确切偏移(dev+0xb00 vs graybuf+0x10 读到的数据不符)

4.5 官方显示效果(用户标准)

  • 官方 app 画面:背景品红(145,0,145),热物体紫红渐变,顶部坏点带白色
  • 官方灰度:93% 像素=0(说明显示窗口下限 > 背景温度,背景灰度≈0? 但渲染背景是品红 → 矛盾,需重新验证灰度与渲染的对应!)
  • 注意:official_gray.bin 与 official_ir_03.rgb 是不同会话抓的, 不能直接配对!必须同一时刻抓灰度+RGB+温度

5. 显示管线演进与失败教训(重要)

版本 方案 结果 教训
v1 原始 直接显示 counts + percentile 乱图/坏点 raw 不可直接显示
v2 EMA 参考 + diff 鬼影 EMA 吸收静态场景
v3 全局漂移 + 坏点拓扑填充 鬼影仍在 参考吸收小物体
v4 MOG 冻结 + 自愈 乱图叠加 参考采集被 quiet-gate 卡住
v5 MOG 冻结 + FFC 重采集 画面更混乱 参考从未建立(NUC 未激活)
v6 NUC 平场 + 自适应窗口 平滑但对比度差、颜色不对 找到了 NUC,但窗口/调色板错
v7 NUC + T2E + 官方调色板 品红背景与官方一致但什么都分辨不出 窗口/灰度映射仍不对,对比度丢失

用户最新反馈(2026-08-11):v7 画面"什么都分辨不出来"(对比度丢失, 物体与背景无法区分),且"还是有鬼影"。结论:即使色系对了,灰度映射/ 窗口机制仍然错误,参考帧方案仍有残留问题。必须回到官方完整管线

5.1 核心失败教训

  1. 不能边猜边试:v1-v7 都是"猜显示算法→实机看效果→再猜"。 用户明确要求:先把官方"读取→显示"全流程逆向完毕,再改代码
  2. 最终屏幕画面必须与官方一致:用户以此为标准,不是"看起来平滑"。
  3. 参考帧/NUC 的副作用(鬼影)未解决:NUC 参考冻结后无更新, 温度漂移会导致残留。
  4. 官方灰度图与渲染帧未配对:不同会话数据不可用于像素级对比。
  5. 调色板偏移未确认:graybuf+0x10 读到的 Jet 色系与渲染帧品红系矛盾, 说明读错位置或存在多个调色板。

6. 当前代码状态

  • csdk/tools/mag160c_demo2.c:最新版(官方管线尝试,v7)
    • 显示:counts → NUC → T2E temp(shift=6)→ 自适应窗口(背景±2°C)→ 品红调色板(插值版)
    • 已知问题:对比度差(分辨不出物体)、可能有鬼影
  • csdk/tools/mag160c_ffc_test.c / csdk_stream_test.exe:FFC 稳定性验证(已 PASS)
  • csdk/tools/tsdk_*.c:官方 ThermalSDK 活体 harness(tsdk_debug 最稳定)
  • csdk/src/mag160c_display.c:纯 C 显示模块(NUC/坏点/AGC/FFC 调度)
  • csdk/src/mag160c_official_t2e.h / mag160c_official_palette.h:官方表
  • csdk/tests/test_display.c:32/32 通过
  • 证据图:analysis/demo2_v2..v7_*.png

7. 下一轮方法论(必须遵守)

7.1 总原则

先把官方"读取→显示"全流程逆向完毕并像素级对比一致,再动 demo 代码。

7.2 具体步骤(建议顺序)

  1. 同帧抓取:写一个 harness(基于 tsdk_debug),在同一帧内抓:
    • 官方灰度(MAG_GetOutputBMPdata → dev+0xaf0)
    • 官方渲染 RGB24(MAG_GetOutputBMPdataRGB24)
    • 官方温度(MAG_GetTemperatureData 或 ReadTemperatureAtPoint 多点多帧)
    • 官方调色板(需先确认正确偏移) 存成配对文件(如 official_pair_%03d.gray/.rgb/.bin)。
  2. 逆向 counts→灰度 生成代码:在 CoreSDKLib.dll 找写 dev+0xaf0 的 函数(帧处理线程),确认:AGC 算法(线性?直方图?)、温度窗口、 是否含 NUC/坏点。这是"读取→显示"缺失的核心环节。
  3. 确认调色板:用同帧灰度+RGB 精确提取 256 项调色板 (gray→color 逐项),替换现在的插值版。
  4. 像素级对比:用我们的 counts + 逆向的完整管线重建画面,与 官方同帧渲染逐像素对比(相关系数、色差),迭代到一致。
  5. 温度标定:用官方温度数据校准 shift 和 offset,替换 147 counts/C。
  6. 鬼影:参考帧方案在官方管线确定后重新设计(官方是否有参考帧? 还是纯逐帧处理?)。

7.3 工具与入口

  • 设备空闲检查:Get-PnpDevice | ? InstanceId -match 833C
  • 官方 harness:build-artifacts\tsdk_debug.exe(最稳定,先跑这个验证设备)
  • 我们的帧 dump:build-artifacts\mag160c_frame_dump.exe <n> <dir>
  • 分析脚本:analysis/temp/(Python,numpy/scipy/PIL 可用)
  • 官方 DLL 反汇编:objdump -d -Mintel(RVA 见 analysis/temp/exports2.py)

7.4 环境

  • Windows 11 + MinGW gcc 14.2(C:\mingw64\bin),无 cmake
  • libusb:csdk/third_party/libusb/win64/
  • 官方 SDK:IR_Camera_SDK-1.0.1/windows/windows/app/
  • Python 3.10 + numpy/scipy/PIL