Files

164 lines
8.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MAG160C 热像仪渲染管线交接文档 v5
> 项目:MAG160C 热像仪(160x120, USB, VID 0x833C)自实现渲染管线 demo3
> 目标:复刻官方 CoreSDKLib.dll 渲染效果
> 状态:颗粒 ✓ / FFC 颜色 ✓ / 蒙层 ✓ / **黑洞·黑拖影 ✗(当前阻塞)**
---
## 1. 已解决问题(历史)
| 问题 | 根因 | 修复 |
|---|---|---|
| 画面颗粒重 | NUC 斜率 3 过大(官方 0.19) | `NUC_GAIN=19`(0.19) |
| FFC 后颜色跳变 | FFC 后重采集 ref 吸收场景 | `REF_REINIT_AFTER_FFC=0`:FFC(1) 后只 rebase 全局偏移 |
| 物体显示破碎/椒盐 | 固定窗口 ±312,物体 nuc 超窗口饱和 | 自适应 P2..P98 百分位窗口(下限 624,官方实测) |
| 画面"蒙一层东西" | 常数 ref 不做平场,mura(空间 std 3560)直接显示 | 启动采集每像素平场(median,运动门控) |
| 黑拖影/黑洞 | ref 冻结 + 物体移动 → 旧位置 d = live-ref < 0 → nuc 低 → 黑 | **未解决**(见 §3) |
---
## 2. 官方逆向成果(已验证,disasm 证据)
### 2.1 渲染数据流
```
USB帧(type=0)
→ 平滑器 0x41f10(模式1: 首帧 memcpy + EMA) → f20 (dev+0x41f20)
→ NUC 查表 0x180017200: d2=(f20-ref)>>1, 段查表, clamp[0,65535]
→ 3x3 加权 0x180017330(写回) → dev+0x270 (raw/NUC输出)
→ 窗口 0x4202c/0x42030 (hi/lo, 动态) → gray (dev+0x220, 2x 升采样 320x240)
→ 调色板 256 色 (pal[0]=黑, pal[255]=白) → RGB
```
### 2.2 NUC 查表(0x180017200, 完整逆向)
```
每像素:
d2 = (f20[i] - ref[i]) >> 1 (sar)
段选择: for(edx=0; edx<nsegs-1; edx++)
if (d2 <= s16 thresh[edx]) break; (thresh 在 dev+0x41858, 值 [3136, 2484, 644])
偏移 = edx * 19200 * 2
nuc = (u16 gain[段][i] * d2) >> (shift=0x11c=12) + u16 off[段][i]
clamp [0, 65535]
→ dev+0x270
```
- gain/off 表:dev+0x41870,nsegs=dev+0x41554=3,每段 19200 像素 × (gain u16, off u16)
- **注意:d2 全负(正常场景,ref≈f20+3800)→ 段0。段1/2 用于大 d(物体),官方对物体响应待验证**
### 2.3 参考帧 ref(dev+0x41ef0)
- 来源:平滑器 0x41ee0(模式4 = 累加平均 acc+=in, out=acc>>2)
- 采集:启动帧 6-9(仅 4 次调用 0x18000c620),之后**冻结**
- FFC 后:只全局偏移变化(-145/-214 counts),空间结构不变(不重采集)
- 与 f20 同源 mura(corr 0.998),精确抵消 mura → d2 空间 std 仅 ~114
### 2.4 FFC 触发(0x18000a1d2, 0x180002f50)
- 条件 A:帧号 ≥ r9 + [0x2d90](0x2d90=1800 帧 ≈ 120s 周期)
- 条件 B:帧号 ≥ r9 + r8(30/100 冷却)且 |sensor_temp - last| > [0x2d94]=250
- 动作:发 FFC(0) (0x6bb6b672, param=0),更新温度记录(0x54/0x58),重置计数(0x49c)
- FFC(1) 在 9 帧后(0x18000c620 链路),type=1 帧期间不渲染(官方冻结画面)
### 2.5 温度
- NUC 输出与温度**完全正相关(corr=1.0, 热=亮)**
- temp_mC = T2E 查表(3×nuc - C, C~5797, 表 0x249f0 645 项)
- 平滑器 0x41f40(模式?)→ 0x180010780(温度)
### 2.6 关键结论
- **官方 ref 冻结 → 官方同样会黑洞/拖影**(移动物体),官方无场景检测
- 官方 FFC 周期 120s,比 demo3 早期 27s 长得多
- 官方窗口动态(无手 span≈624,有手 span≈1381)
---
## 3. 当前阻塞:黑洞/黑拖影
### 3.1 现象
用户敲键盘(手在镜头前小幅移动):手移动后,手旧位置/背景最热处显示为黑色(d 负 → nuc 低 → 黑),拖影明显。
### 3.2 物理机制
```
ref 冻结(平场) → 物体移动 → 旧位置:
d = live(当前背景) - ref(启动背景)
若背景温度漂移/场景变化 → d < 0 → nuc < comp → 黑
```
### 3.3 已试方案与结果
| 方案 | 结果 | 失败原因 |
|---|---|---|
| 固定窗口 ±312 | 物体破碎 | 窗口太窄 |
| FFC 后重采集 ref | 颜色跳变 | 吸收场景 |
| 冻结 median 平场 | 黑洞 | ref 冻结 |
| 常数 ref(每帧全局最低) | 无黑洞但蒙层 | 不平场 |
| 平场+min 平移 | 蒙层✓(修复采集 bug 后) 黑洞回归 | ref 仍冻结 |
| SBNUC 条件更新(df<50 且 dd<80, α=1/64) | 蒙层✓ **黑洞仍存** | 见 3.4 |
### 3.4 SBNUC 失效根因(diag 实测 d=(-467±1479))
1. **df 条件(帧差<50)**:手快速移动时,手经过的像素帧差大 → 永不满足 → 永不吸收 → 拖影持续
2. **dd 阈值 80 太严**:背景 d 空间 std ~458 → 大部分背景像素 |d-med|>80 → 吸收率极低
3. **α=1/64 太慢**:完整吸收需 64 帧(4s),拖影长
4. **背景漂移**:场景整体漂移(实测 d mean 从 +1734 → -467,场景变冷)→ d 负 → 黑
### 3.5 下一步建议(按优先级)
1. **改 SBNUC 参数**:去掉 df 条件(或放宽到 200),dd 阈值 ~120,α=1/16(1s 吸收)
- 理由:只用 dd(物体距离)判断,手经过区域(背景没变,d≈med)→ 立即吸收
2. **每像素时域 d 方差检测**(Hardie Kalman SBNUC, IEEE TIP 1998):
- 维护 d[i] 短窗方差:背景稳定(方差小)→ 吸收;物体经过(方差大)→ 不吸收
3. **双缓冲 ref**:背景 ref(条件更新)+ 物体区域冻结保护
4. 验证指标(demo3_diag.txt):d mean → 0,d 空间 std 应 < 300,物体移动后旧位置 d 快速回 0
5. 若参数方案有效,复刻官方查表(0.19 线性 → 官方分段)对比官方画面
---
## 4. 代码结构与关键参数(demo3.c)
```
常量:
CONSTANT_REF=1 常数/平场+SBNUC 模式
NUC_GAIN=19 (0.19)
FFC_PERIOD=1800 官方周期(120s)
FFC_GAP=9
REF_INIT_N=12 平场采集帧数
REF_REINIT_AFTER_FFC=0 FFC 后不重采集
WIN_HALF=312 窗口下限半宽(P2-P98 自适应)
平场采集:g_ref_phase==1(启动 nread>=60 后),运动门控(帧差>30 或 4% 像素动 → 重置窗口)
SBNUC 块:CONSTANT_REF && g_ref_mura_ready 分支(行 ~885):
med = 直方图中值(live - g_ref_mura)
if (|live-prev|<50 && |(live-mura)-med|<80) mura += (live-mura)/64
平移: ref = mura - min(mura) + min(live)
关键数组:g_ref_mura[NPIX] 平场, g_reference[NPIX] 渲染用
```
### 编译
```
gcc -O2 -w -DMAG160C_STATIC -I"C:\Project\MAG160C\csdk\third_party\libusb\win64" -I"C:\Project\MAG160C\csdk\include" -I"C:\Project\MAG160C\csdk\src" -o "C:\Project\MAG160C\build-artifacts\mag160c_demo3.exe" "C:\Project\MAG160C\csdk\tools\mag160c_demo3.c" "C:\Project\MAG160C\csdk\src\mag160c_display.c" "C:\Project\MAG160C\csdk\src\mag160c_error.c" "C:\Project\MAG160C\csdk\third_party\libusb\win64\libusb-1.0.x64.a" -lgdi32 -luser32
```
### 运行/测试
```
Stop-Process -Name mag160c_demo3 -Force
Start-Process "C:\Project\MAG160C\build-artifacts\mag160c_demo3.exe" -WorkingDirectory "C:\Project\MAG160C\build-artifacts"
日志:demo3_diag.txt(每帧 ref/live/nuc/窗口/d), demo3_auto_*.bmp(每 30 帧自动截图)
用户测试:启动 → 等平场(~5s) → 手放镜头前小幅移动(敲键盘) → 观察黑拖影
```
### 工具
- `build-artifacts/tsdk_pair2.exe <dir> <npairs> <delay>`:官方 SDK 抓帧(需先停 demo3;若 "no channel" 需重插设备)
- `build-artifacts/mag160c_frame_stats.exe`:libusb 直连抓帧
- 反汇编:`analysis/disasm/coresdk_windows_disasm.txt`(UTF-16,193k 行)
- 官方数据:`analysis/pairs_nuc2/pair_000.*`(f20/ref/raw=nuc/gray/rgb/cbrgb/t32/thr/gain)
---
## 5. 方法参考(专利/开源)
- Scribner et al., "Adaptive nonuniformity correction for IR focal-plane arrays using neural networks", SPIE 1541, 1991/1993 — 最经典 SBNUC
- Hardie et al., "Scene-based nonuniformity correction with reduced ghosting using a recursive Kalman filter", IEEE Trans. Image Process. 7(10), 1998 — **专治移动物体鬼影,与当前问题最相关**
- FLIR/ULIS 自适应 FFC 专利(如 US 7,940,301 系列)— 静止场景才刷新校正表
- 开源:seek-thermal-suite(madsci1016)、Melexis MLX90640 API(无快门自校正)
- 核心思想:背景像素"静止且接近参考"才更新;物体区域冻结
## 6. 未完成逆向
- [ ] 官方查表段 1/2(大 d 物体)的增益/偏移值与物体响应(线性 0.19 vs 官方分段)
- [ ] 官方窗口(0x4202c/0x42030)更新机制(动态 span 怎么算)
- [ ] 0x180016ae0 菜单表初始化(0x417xx/DDT)
- [ ] FFC 状态机 0x73bf4(帧 75/130)
- [ ] 官方输出 2x 升采样算法(0x220 38400 → RGB)