7.2 KiB
7.2 KiB
官方 PC 端 vs 逆向 SDK:同一帧逐像素对比(2026-10-06)
目的:热像仪接 PC 后,用官方 Windows 软件采图,与逆向出来的 SDK/App 管线 渲染同一帧做逐像素对比,找出"照片到底差在哪些细节上"。 证据图:
docs/android_app/pc_vs_ours_20261006.png(官方 / 我们 / 差异×8 / 灰度 ×16)。
结论速览
| 环节 | 一致性 | 证据 |
|---|---|---|
| NUC(端点插值 + 增益/阈值表 + 盲元补偿 + ref) | 逐像素完全一致 | 抽检 4 帧:19200/19200 像素相等,max diff = 0 |
| 调色板 | 完全一致 | 官方 .pal、官方彩色图颜色集合、我们的 PALETTE256_ARGB 三者 256/256 相同 |
| 灰度映射(窗口 + 直方图 LUT + 2× 上采样) | 平均 +1.3 级、最大 10 级(/255) | 320×240 灰度逐像素;本轮场景计数 9600–11000 |
| 彩色输出 | 60.9–72 % 字节完全相同,平均 |Δ| 1.4–1.9/255,最大 20 | 官方 .rgb(BGR24)vs 我们导出的 PNG |
| 细节增强(7×7 DDE) | 官方这份渲染没开;我们默认等级 0 也关 | 官方彩色 = palette(官方灰度),逐像素 max diff = 0 |
| 显示窗口 | 下界规则不同 | 官方 20/20 帧 winHi = 数据max;12/20 帧 winLo = 数据min,其余仅低 1–7 计数。我们 winLo = mean−500,本例比数据 min 低 188 计数 |
| 温度换算 | 系统差:+0.1 ℃ @27 ℃ → −0.7 ℃ @38 ℃ | 官方 t32 是 NUC 计数的精确直线(k=8.539 mC/count,残差 ≤0.5 mC),我们的固定 T2E 表斜率 8.26→7.67 递减 |
一句话:渲染管线(NUC/调色板/灰度)已经和官方 PC SDK 对得上,肉眼几乎无差别; 真正还差的是温度曲线(最高到 0.7 ℃)和窗口下界规则(造成约 1 级亮度偏差)。
1. 官方 Windows 侧用谁
| 候选 | 判定 |
|---|---|
app/【PC分析软件】…exe(内部名 ThermoX 2.5.3.6,巨哥电子) |
是网络码流软件:面板是"指定IP / 启用DHCP Server / 传输混合/纯视频/纯温度码流",刷新扫不到 USB 相机,运行期不加载任何 USB 库 → 不吃本机 USB 机芯 |
IR_Camera_SDK-1.0.1/windows/windows/app/EloThermal.exe(官方 SDK 演示,C# 源码在仓库) |
能连 USB 出图(CameraSDK/ThermalSDK + libusb0),但没有任何存图功能(全源码无 Encoder/Save)→ 只能截屏 |
build-artifacts/tsdk_pair3.exe(本仓库工具,调用官方 ThermalSDK.dll + CoreSDKLib.dll) |
✅ 采用:一次采集给出官方渲染图、原始帧、温度、调色板、LUT、DDT 全套 |
2. 方法(可复现)
# 1) 设备驱动(本机原来没装,CM_PROB_FAILED_INSTALL)
# 厂商 INF:IR_Camera_SDK-1.0.1/windows/windows/drivers/amd64/ThermoCube_stream.inf
# (libusb-win32 1.2.6.0,cat 是 libwdi 自签证书) → 需先把该证书导入
# "受信任的根证书颁发机构" + "受信任的发布者",再:
pnputil /add-driver ThermoCube_stream.inf /install # 设备变 OK,libusb0 服务 RUNNING
# 2) 官方基准采集(输出目录用第 1 个参数,勿落在仓库里)
cd <temp>
tsdk_pair3.exe <temp>\off20 20 6000 > off20_stdout.txt
# 每帧产出 19 个文件:gray / rgb / cbrgb(BGR24) / raw / f20 / ref / t32 / pal /
# lut / h1024 / cdf / hist / thr0 / thr1 / thrw / g0 / g1 / gw / blind (+official.ddt)
# 3) 用我们的管线离线渲染同一批帧(临时 JVM 单测,用完已删)
# RenderPipeline.loadDdt(official.ddt) 后:
# repeat(4){ frameRemote(pair.ref, phase=2, shutter) } // ref = 官方的参考帧
# frameRemote(pair.f20, phase=0, shutter) // 渲染
# 产出 our_XXX.png / .nuc / .t32,再用 Python 与官方逐像素比
新解码出的官方内部缓存语义(供后续逆向用):
| 缓冲 | 地址 | 含义 |
|---|---|---|
| 帧输入 | dev+0x41f20 | 官方喂给 NUC 的帧数据(= USB 帧 payload 域,均值 ~12000) |
| 参考帧 | dev+0x41ef0 | NUC 用的 ref |
| 传感器温度 | dev+0x54 | 端点插值用的 FPA 温度(与 DDT 锚点同量纲,m℃) |
| NUC 输出 | dev+0x270 | 校正后计数(均值 ~9600–11000);MAG_GetTemperatureData_Raw 的输入 |
| 端点选择 | dev+0x41840 | 官方的 sel,与我们的 endpoint() 取值完全一致 |
关键验证:把
dev54当帧尾 FPA 温度喂进我们的管线,NUC 输出与官方pair_*.raw19200/19200 像素逐位相等——这同时锁定了帧尾 FPA 字段的语义。
3. 温度:官方是"每设备线性响应",我们用的是固定曲线
官方 t32(19200 像素 × int32 毫度)与 NUC 计数之间是精确直线:
t_mC = 8.539 * counts - 55688 # 残差 ≤ 0.5 mC;逐帧斜率 8.5358–8.5424(≈常数)
同一计数下不同像素的温度离散为 0 mC(无逐像素差异)→ 说明官方对"已校正计数"
只做一次全局线性换算(对应 ConvertResponse2Temperature 一族,csdk 里已有实现
mag160c_temp_convert_response,但安卓 App 未使用)。
我们的 TempMath.countsToTempMc 是固定 T2E 反查表,局部斜率随计数递减:
| 计数区间 | 官方斜率 | 我们的斜率 | 比值 |
|---|---|---|---|
| 9600–9900 | 8.5390 | 8.2581 | 1.034 |
| 9900–10200 | 8.5391 | 8.1993 | 1.041 |
| 10200–10600 | 8.5390 | 7.9505 | 1.074 |
| 10600–11000 | 8.5390 | 7.6706 | 1.113 |
→ 温度读数偏差:≈27 ℃ 处 +0.1 ℃,≈38 ℃ 处 −0.62 ℃(累计最大 −0.70 ℃)。
4. 建议的下一步
- 温度(优先):安卓端改用设备响应换算。官方 PC 侧对已校正计数是线性映射,
系数随设备(本机实测 k=8.539 mC/count、b≈−55.7 k mC,随 FPA 温度微动 ~±50 mC)。
需要先定位系数的来源(DDT / BasePara 里的标定字段),再按官方公式实现;
csdk/src/mag160c_temp.c::mag160c_temp_convert_response已是同款算法,可作参照。 - 窗口:把
statsWindow()从"mean ± (dev24*1000>>dev4cShift)/2向外扩"改成官方行为 (上界 = 数据 max、下界 = 数据 min,20 帧实测 20/20 与 12/20 如此,其余差 ≤7 计数)。 这一项解释了灰度上 ~1.3 级的系统性偏差。 - 手机侧对照照(未完成):本轮只覆盖"渲染",没覆盖官方手机 App 的拍照路径。 建议:同一静止场景,官方手机 App 与我们的 App 各拍一张同调色板照片; 官方 MDT 里存的就是 NUC 后帧,可以直接喂我们的显示阶段逐像素比 (需要给管线加一个"只跑显示阶段"的离线入口)。
- PC 端 C 工具链:本机 libusb-1.0 1.0.19 对 libusb0.sys 绑定不可用
(
claim_interface→ Win32 错误 87;官方走 libusb0.dll API 正常)。 若要在这台机器跑 csdk 的 demo3/render_offline,需要换 libusb-1.0 版本, 或把设备改绑 WinUSB/libusbK。
5. 复现清单(临时文件不在仓库)
- 官方基准数据(20 帧全套,35 MB)与差异图在
%TEMP%\mag160c_wincmp\off20\(compare_visual.png/compare_tempdiff.png/compare.txt); 仓库内只保留docs/android_app/pc_vs_ours_20261006.png一张证据图。 - 驱动安装脚本痕迹:
%TEMP%\mag160c_wincmp\pnputil*.log、cert.log。