10 KiB
10 KiB
MAG160C 逆向交接文档 v2(2026-08-11)
本文件是当前最新、最完整的上下文快照。 覆盖硬件/协议/官方SDK逆向/ 显示管线演进/全部失败教训。下一轮请从第 1 节开始读,严格按第 7 节 的方法论执行。
1. 项目目标
对 Elo/Magnity MAG160C USB 热成像相机(160x120, 15fps)完整逆向:
- 官方从"USB 读取 raw → 显示到屏幕"的完整管线逐层复原
- 自研 C SDK(csdk/)+ Windows demo 的最终屏幕画面必须与官方 app 一致
- 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 RGBMAG_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 核心失败教训
- 不能边猜边试:v1-v7 都是"猜显示算法→实机看效果→再猜"。 用户明确要求:先把官方"读取→显示"全流程逆向完毕,再改代码。
- 最终屏幕画面必须与官方一致:用户以此为标准,不是"看起来平滑"。
- 参考帧/NUC 的副作用(鬼影)未解决:NUC 参考冻结后无更新, 温度漂移会导致残留。
- 官方灰度图与渲染帧未配对:不同会话数据不可用于像素级对比。
- 调色板偏移未确认: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 具体步骤(建议顺序)
- 同帧抓取:写一个 harness(基于 tsdk_debug),在同一帧内抓:
- 官方灰度(MAG_GetOutputBMPdata → dev+0xaf0)
- 官方渲染 RGB24(MAG_GetOutputBMPdataRGB24)
- 官方温度(MAG_GetTemperatureData 或 ReadTemperatureAtPoint 多点多帧)
- 官方调色板(需先确认正确偏移) 存成配对文件(如 official_pair_%03d.gray/.rgb/.bin)。
- 逆向 counts→灰度 生成代码:在 CoreSDKLib.dll 找写 dev+0xaf0 的 函数(帧处理线程),确认:AGC 算法(线性?直方图?)、温度窗口、 是否含 NUC/坏点。这是"读取→显示"缺失的核心环节。
- 确认调色板:用同帧灰度+RGB 精确提取 256 项调色板 (gray→color 逐项),替换现在的插值版。
- 像素级对比:用我们的 counts + 逆向的完整管线重建画面,与 官方同帧渲染逐像素对比(相关系数、色差),迭代到一致。
- 温度标定:用官方温度数据校准 shift 和 offset,替换 147 counts/C。
- 鬼影:参考帧方案在官方管线确定后重新设计(官方是否有参考帧? 还是纯逐帧处理?)。
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