简介:基于神经网络的红外图像非均匀性校正是一份面向红外成像、图像处理与深度学习交叉领域的技术PDF,重点讲解利用随机梯度下降法训练的神经网络模型对红外焦平面非均匀性进行自适应校正,适合从事红外探测、热成像及相关算法研究的工程师和研究生阅读。压缩包内仅含1个PDF文档,大小约1MB,为2018年发表于《红外技术》的期刊论文原版,内容涵盖盲元检测与补偿、双边滤波期望输出计算、神经网络模型构建及实验对比等完整环节,目前已有293人学习浏览。论文先分析非均匀性成因,再结合双边滤波获取期望输出,并用随机梯度下降法训练网络,使校正过程能随场景自适应更新。读者可从中获得场景自适应非均匀性校正的完整实现思路,了解其相对传统标定方法的优势,并参考网络结构与参数更新策略,便于迁移到自身红外图像处理项目中。
1. 红外图像非均匀性校正为什么离不开场景自适应
把 384×288 的红外焦平面正对 300 K 面源黑体,采出来的图像不是均匀灰色,而是一幅带固定网状斑纹的画面。这个现象不是镜头脏污,而是每个像元的增益和偏置天然不同,形成固定图案噪声。传统两点标定能在出厂前压掉一部分,但红外焦平面的响应会随温度、积分时间和场景漂移,标定参数用一段时间就会失效。这篇工作把非均匀性校正改造成一个带标签反馈的神经网络:先做盲元检测与补偿,再用双边滤波估计每个像元的期望输出,最后用随机梯度下降动态更新增益和偏置。对做红外目标探测、热成像系统或嵌入式图像算法的工程师来说,这是从“看着均匀”过渡到“测量可信”的关键一步。
2. 盲元检测与两点校正:先看清 IRFPA 非均匀性从哪来
红外焦平面非均匀性来自三个层面:半导体材料掺杂浓度和表面态密度差异导致阈值电压不同;模拟多路读出电路的一致性做不到理想;光学镜头的精度差异也会引入额外固定图案。把单个像元抽象出来,任意辐射条件下的输出可以写成:
y(φ) = ω · x(φ) + b
x 是像元实际输出码值,y 是期望输出码值,ω 和 b 分别是该像元的增益和偏置。所有非均匀性校正算法最终都在估计这两个参数。
2.1 固定图案噪声的定量描述
面源黑体实测是判断非均匀性最直接的方法。在资源给出的实验中,对 300 K 黑体,焦平面原始输出码值分布在 1.2×10⁴~1.3×10⁴,直方图呈矮胖形态,按标准定义计算得到非均匀性 NU 为 0.6%。
2.1.1 NU 指标怎么算
红外焦平面阵列非均匀性指标按 GB/T 17444 定义:
NU = sqrt( Σ(y_ij(φ) - ȳ(φ))² / (r·c) ) / ȳ(φ)
r、c 分别是焦平面行列数,y_ij(φ) 是辐射 φ 下像元 (i,j) 的输出码值,ȳ(φ) 是整帧平均码值。NU 越小,固定图案越弱。这个指标特别适合用来做校正前/后的黑体帧对比。
2.1.2 为什么几个码值的差异会要命
弱小目标探测时,目标与背景温差很小,在图像上只表现为几个码值的差别。固定图案噪声如果压制不到位,这些目标会直接淹没在空间不均匀的背景里。固定图案在时域上稳定,但空间上有规律可循,因此空域平滑不能根治,硬平滑还会顺手抹掉目标。
2.2 两点校正与盲元补偿
两点校正假设像元输出线性,用 T1、T2 两档黑体温度做两点拟合。每个像元的期望输出用整帧均值代替:
ω = (ȳ(T1) - ȳ(T2)) / (x(T1) - x(T2))
b = ȳ(T1) - ω·x(T1)
得到系数后逐像元做一次乘加。计算量极小,这是它至今没有被淘汰的原因。
2.2.1 盲元必须先检测再补偿
盲元是响应很小或完全无响应的像元。这类像元在做增益计算时,分母接近零甚至为零,直接算出来的 ω 会异常巨大。常见做法是采集多个黑体温度点,观察每个像元的响应曲线:正常像元随温度升高单调上升,异常像元的输出曲线明显偏离。定位后用空间邻域填充;若出现空间连续坏元,用整帧平均值填充。顺序上,盲元补偿必须放在神经网络训练之前,否则盲元会以离群样本身份进入代价函数,拖偏周围区域的参数。
2.3 两点校正的两个边界
第一个边界是线性假设。像元输出随辐射通量变化不是严格线性的,多点分段标定可以缓解,但数据量成倍增加,标定流程也更重。第二个边界是时间漂移。增益和偏置会随焦平面温度、积分时间变化,标定参数会逐渐失效。两点校正后的 300 K 黑体帧 NU 从初始 0.6% 降到 0.54%,说明它有效,但它无法在系统运行中自主更新。对需要实时识别跟踪的平台,场景自适应校正是更合适的路线。
| 校正方法 | 期望输出来源 | 能否在线更新 | 主要代价 |
|---|---|---|---|
| 两点标定 | 两档黑体均值 | 否,需要定期遮挡标定 | 存储系数表,中断成像 |
| 多点分段标定 | 多个黑体温度点 | 否 | 数据量和计算量随温度点增加 |
| 神经网络场景校正 | 当前帧双边滤波估计 | 是,每帧可更新 | 需要梯度运算和标签估计 |
这张表把三类方法拉到同一维度看:表里前两行只在实验室和固定场景有优势,一旦平台运动、温度变化,第三行才是能持续工作的方案。
3. 神经网络校正的核心:双边滤波标签与随机梯度下降
基于神经网络的场景校正并不需要很深的结构。Scribner 提出的神经结构示意图里包含输入层、隐藏层和输出层,真正参与可学习参数的校正层是增益 ω 和偏置 b,输出是线性乘加 y = ωx + b。隐藏层在实现时通常退化为恒等激活,这样既保留了反向传播和梯度下降的训练框架,又让参数语义非常明确,实时成像链路能够承受增量更新开销。
3.1 训练样本与特征归一化
把 384×288 的盲元补偿后图像拉成一行,每个像元是一个样本,整帧数据就是一个大矩阵。问题是输入码值范围是 0~65535,直接拿来算残差,residual * input的数量级可能到 10⁸,学习率只能压到极小,否则一个迭代就爆炸。常见的做法是均值归一化:把图像缩放到 [0,1],再让增益初始为 1 附近、偏置初始为 0 附近,这样学习率可以从 0.01 起步。
3.1.1 标签用双边滤波而不是邻域均值
期望输出是训练标签,决定参数朝哪个方向走。如果直接用 3×3 邻域均值,边缘会被明显磨掉,训练完的校正链路不仅不能增强目标,还会把纹理抹得更平。双边滤波把权重拆成空间距离和灰度距离两部分:
y = (1/C) Σ α(空间距离) · β(灰度距离) · x(邻域)
空间权重 σ_s 决定取多大窗口,灰度权重 σ_r 决定灰度差多大的邻居可以参与平均。灰度差越大权重越小,因此跨越边缘的像素基本不参与平滑,同质区域则充分平均。这对红外图像特别重要——保留边缘的同时压掉像元间的固定图案,而目标轮廓和衣服褶皱这类高频细节不会被当成噪声一起消掉。
3.1.2 为什么时域高通滤波解决不了静止场景
时域高通滤波利用运动目标产生的高频分量,减去时域低通估计来校正偏置。缺点是场景静止时,低通帧逼近当前帧,高通输出几乎没有信号,校正失去方向。双边滤波只依赖当前帧空间信息,有边缘和纹理就能产生有效残差,对静止场景也能维持更新。
3.2 代价函数、L2 正则与 SGD 更新
校正层输出与双边滤波标签 f 之间的误差用平方损失:
J(ω,b) = (1/2n) Σ_i [h(ω x_i + b) - f_i]²
选择平方损失源于线性回归中的高斯噪声假设:误差服从零均值高斯分布时,最大化似然函数等价于最小化平方残差。前半部分的 1/2 是为了对平方求导时消掉系数,属于常见写法。
3.2.1 正则项防止参数图过拟合
相邻像元特征高度相关,直接最小化平方损失有可能让某个像元的参数异常放大,结果是校正后图像重新出现颗粒状图案。加 L2 正则:
J_reg = J + λ Σ θ²
λ 是正则系数,θ 包括该帧训练中所有增益和偏置参数。λ 太小正则不起作用,太大校正强度不足。归一化图像上,一般从 1e-4 开始试。
3.2.2 线性激活下的梯度与学习率
若校正层激活函数取恒等映射 h(c) = c,残差 r = ωx + b - f,对参数的偏导分别是:
∂J/∂ω = r·x, ∂J/∂b = r
SGD 更新公式为:
ω ← ω - α·r·x, b ← b - α·r
学习率 α 过小,收敛缓慢,容易停在局部极值;过大则在极值附近振荡,图像上表现为校正系数来回抖动。批量梯度下降通常还要在梯度前除以样本数 N,SGD 单样本更新时等效于 N=1。实现上,用实验室两点标定的增益和偏置作为初始值,会比随机初始化更快,也更容易避免一开始就走入死角。
3.2.3 超参数对照表
| 超参数 | 设置偏小 | 设置偏大 |
|---|---|---|
| 学习率 α | 收敛慢,几十帧才稳定 | 参数振荡,校正图闪烁 |
| 正则系数 λ | 参数图出现椒盐状异常值 | 校正不彻底,固定图案残留 |
| 双边滤波窗口 | 条纹噪声残留明显 | 边缘模糊,目标细节丢失 |
| σ_r 灰度权重 | 接近普通均值滤波 | 保边过强,噪声被当结构保留 |
这个表是为实际调试准备的。调参时可以先固定 λ = 1e-4、α = 0.01,然后调双边滤波窗口和 σ_r,最后再回头微调学习率。
3.3 一份可运行的 NumPy 最小实现
教学版代码如下,帧数据已做均值归一化:
import numpy as np def bilateral_label(img, sigma_r=0.08): # img: 已归一化到 [0,1] 的红外帧 # 3x3 离散空间高斯权重 spatial_w = np.array([[0.075, 0.124, 0.075], [0.124, 0.204, 0.124], [0.075, 0.124, 0.075]]) h, w = img.shape label = np.zeros_like(img) for i in range(1, h - 1): for j in range(1, w - 1): wnd = img[i-1:i+2, j-1:j+2] center = img[i, j] gray_w = np.exp(-((wnd - center) ** 2) / (2 * sigma_r ** 2)) weight = spatial_w * gray_w label[i, j] = np.sum(weight * wnd) / np.sum(weight) return label # 主循环:单帧在线更新 frame = get_frame().astype(np.float32) # 实际工程替换为相机读帧接口 img = (frame - frame.min()) / (frame.max() - frame.min()) gain = np.ones_like(img) # 也可用两点标定出的增益图初始化 bias = np.zeros_like(img) # 也可用两点标定出的偏置图初始化 lr = 0.01 for _ in range(20): label = bilateral_label(img, sigma_r=0.08) corr = gain * img + bias residual = corr - label gain -= lr * residual * img bias -= lr * residualgain -= lr * residual * img对应线性激活下的梯度公式,bias -= lr * residual是偏置梯度。spatial_w是 3×3 窗内预计算好的空间高斯权重,gray_w随中心像元与邻域的灰度差动态变化,这正是双边滤波保边的关键。为了可读性,这里用双循环实现;工程上通常把双边滤波改成行缓冲滑窗或 GPU 卷积,避免每帧做全幅遍历。归一化后lr=0.01可以稳定跑;如果直接输入原始 16 bit 码值,residual * img会放大上万倍,学习率至少要降到 1e-8 才可能不发散。
注意:代码里的
spatial_w只是示例权重,实际部署时应按窗口半径离散化高斯核生成;σ_r 需要配合输入尺度调整,归一化到 [0,1] 时 σ_r=0.08 是一个合理的起点。
4. 实验对比:从 NU 0.6% 到 MSE 减半的验证路径
验证非均匀性校正算法不能只看效果图。这套实验按“黑体帧→自然场景→加噪场景”三层递进:先用 384×288 焦平面采集黑体图做盲元检测,再用两点标定结果初始化增益偏置,最后在自然场景里对比两点校正、均值滤波和神经网络校正。
4.1 测试条件与参数初始化
4.1.1 用两点标定结果做权重初值
两个温度点 T1/T2 黑体对应得到初始 ω 和 b。如果网络随机初始化,SGD 需要从线性响应里“重新发现”整体增益平衡,收敛慢且容易落入局部极值。用两点标定结果做初值,残差从一开始就只剩漂移成分,几个 epoch 就能进入稳定区间。这个做法和嵌入式平台上的部署思路一致:先离线标定一次打底,再交给在线算法跟踪漂移。
4.1.2 加高斯随机噪声的鲁棒性测试
为了对比去噪能力和校正能力,实验对场景图加入高斯随机噪声,分别用均值滤波和神经网络校正处理。这里有个容易踩的坑:均值滤波在压非均匀性的同时也在做空间平滑,把头发、衣服褶皱等高频细节一并抹掉。神经网络校正由于标签来自双边滤波,残差回归会保留边缘结构,所以细节更完整。
4.2 MSE 定量结果
MSE 按归一化后的图像计算:
MSE = (1/N) Σ (y_pred - y_label)²
其中 y_pred 是校正输出,y_label 是参考真值。若在原始 16 bit 码值上计算,数值会大几个数量级,通常先归一化再统计,避免指标被数值尺度主导。
4.2.1 均值滤波与神经网络校正的数值差距
加噪场景的对比结果如下:
| 处理方式 | 加噪后 MSE | 纹理保持情况 |
|---|---|---|
| 均值滤波 | 0.0011 | 边缘模糊,残留颗粒状噪声 |
| 神经网络 + SGD | 0.00058 | 头发、衣服褶皱等纹理可辨 |
MSE 从 0.0011 降到 0.00058,并不是一个夸张的数值提升,但对弱小目标检测链路来说,意味着校正后的输出与参考真值的平均偏差更小,对后续阈值分割更友好。主观上看,神经网络校正后的场景更干净,同时没有出现均值滤波常见的“塑料感”。
4.2.2 最容易暴露校正失败的是静止场景
如果目标静止、背景单一,每个像元输出几乎恒定,双边滤波标签接近自身平滑版,残差趋近于零,SGD 无法持续更新参数。遇到这种情况,不能只靠算法救场。常见做法是周期性短时遮挡或引入微动扫描,强制产生时间/空间变化,让梯度重新恢复。这也在侧面解释了为什么基于场景的校正只在场景时间-空间变化时更新校正参数,单一不变场景里梯度下降学不到有效信息。
4.3 0.6% 到 0.54% 之后看什么
两点校正后的 300 K 黑体帧 NU 从 0.6% 降到 0.54%,提升看起来不大,但这是一次性标定的上限。神经网络校正的价值在长时间连续工作时持续逼近真实响应,不需要人工介入标定。对实际项目来说,非均匀性多压掉一点,后续检测算法就能少一点由固定图案产生的误警,这是工程上最直接的收益。
5. 实时系统里的工程技巧与验证方法
实时链路里,非均匀性校正跑在成像前端,算力预算通常很小。能把 SGD 塞进去的原因是该问题只有两个参数图,一次更新就是一次乘加:增益图乘归一化图像,偏置图直接加减残差。真正要处理的是学习率、数值尺度和验证方式。
5.1 逐帧在线更新与学习率退火
在线更新意味着每来一帧,校正系数都发生微小变化。学习率恒定容易在低温漂阶段被残余噪声反复扰动。常见做法是按迭代次数退火:
lr = base_lr / (1 + decay * t)
base_lr=0.01、decay=0.001 时,前几十帧快速逼近稳定值,后续缓慢微调,既保留场景自适应能力,又不会让参数图抖动。
5.2 三个低成本的验证动作
上线前建议做三件事。第一,保留一帧黑体焦平面图像,每隔若干周期重新计算 NU,看是否长期漂移;第二,把增益图和偏置图的梯度范数输出出来,确认在单调衰减而不是来回振荡;第三,打开残差图观察是否残留边缘结构。若残差图还能清晰看到边缘,说明 σ_r 设置过小、标签不够平滑;若边缘信息被同时抹掉,说明 σ_r 设置过大。
注意:残差图和梯度范数是比单帧效果图更稳定的排错手段,尤其适合 FPGA 上无法跑 Python 调试的环境。
5.3 调参起点和最后一处细节
参数可以从这组值起步:窗口半径 3,σ_s 取窗口半径的 1.2 倍,σ_r 取 0.08(图像归一化后),学习率 0.01,正则系数 1e-4。如果条纹噪声依旧明显,把 σ_r 逐步提到 0.15,同时把窗口从 3×3 扩到 5×5。按这个方向调,固定图案噪声会被慢慢吸收,而边缘纹理还在,这也是双边滤波标签相对普通邻域均值最直观的差别。
本文还有配套的精品资源,点击获取