2. 噪声模型与数据集构建:传感器噪声来源与建模

做深度学习降噪,第一步不是调网络结构,而是搞清楚——你到底在降什么噪声。

我记得刚入行那会儿,拿到一个手机模组的RAW图,直接拿公开数据集训练的网络去跑,结果效果一塌糊涂。后来才发现,不同传感器、不同ISO下的噪声特性完全不一样。说白了,不懂噪声模型,降噪就是盲人摸象。

2.1 传感器噪声三大来源

CMOS图像传感器的噪声,主要来自三个地方。我习惯把它们分成“天生随机型”和“固定模式型”两类。

噪声类型 来源 特性 与信号关系
光子散粒噪声 光子到达的随机性 时域随机,符合泊松分布 √信号
读出噪声 模拟电路、ADC转换 时域随机,近似高斯分布 与信号无关
固定模式噪声 像素工艺偏差、暗电流不均匀 空间固定,帧间不变 与信号弱相关

2.2 光子散粒噪声

这是物理极限,你躲不开。光子到达传感器是随机的,就像下雨天雨滴落在窗玻璃上,每个位置接到的雨滴数不一样。

数学上,它服从泊松分布:

P(k) = (λ^k * e^(-λ)) / k!

其中λ是平均光子数。注意一个关键特性:方差等于均值。也就是说,信号越强,噪声值越大,但信噪比反而提高。

实战要点:散粒噪声的强度与√信号成正比。在暗光下(信号小),散粒噪声不明显;在亮光下,它才是主要噪声源。

2.3 读出噪声

这是电路层面的噪声。像素把光生电荷转换成电压,再经过模拟放大、ADC量化,每一步都会引入噪声。

读出噪声的特点是:与信号无关,近似高斯分布。在暗光下,读出噪声是主要限制因素。

我曾经调试一个工业相机项目,发现暗部噪点特别多。排查了半天,最后发现是ADC的参考电压纹波太大。换了LDO之后,读出噪声直接降了30%。嗯,硬件上的坑,有时候比算法还多。

2.4 固定模式噪声

这个噪声很有意思。它不随时间变化,但每个像素的“偏置”不一样。你拍一张均匀灰卡,放大看,每个像素的响应都有细微差异。

固定模式噪声分两种:

  • 像素固定模式噪声:每个像素的暗电流、转换增益不同
  • 列固定模式噪声:列放大器、列ADC的偏差

怎么处理?标定+校正。我习惯在产线端做暗场标定,存一份校正表。但注意,温度变化会影响暗电流,所以有些高端方案会做实时暗场校正。

避坑指南:我曾经在项目中直接用单帧暗场做校正,结果忽略了温度漂移。夏天和冬天的校正效果差了2个dB。后来改成多温度点标定,才解决问题。

2.5 噪声建模方法

把三种噪声统一建模,我推荐泊松-高斯模型:

y = x + n_p(x) + n_g

其中:

  • x:理想信号
  • n_p(x):散粒噪声,方差 = α·x
  • n_g:读出噪声,方差 = β

写成更实用的形式:

σ² = α · x + β

α是散粒噪声系数,β是读出噪声方差。这两个参数,每个传感器、每个增益档位都不一样。

我的习惯:拿到一个新传感器,第一件事就是拍一组暗场和灰场,拟合出α和β。这个参数表,我会存到ISP的配置文件中。

2.6 合成噪声数据生成

有了噪声模型,就可以生成合成噪声数据了。为什么要做合成数据?因为真实数据太贵了。SIDD数据集拍了5个场景,用了10台手机,花了几个月。而合成数据,你可以在一天内生成10万张。

生成流程:

  1. 准备干净图像:用高ISO、多帧平均,或者直接用无噪声的渲染图
  2. 计算噪声参数:根据目标ISO,查表得到α和β
  3. 生成散粒噪声:对每个像素,从泊松分布采样
  4. 生成读出噪声:从高斯分布采样
  5. 叠加:把噪声加到干净图像上
import numpy as np

def add_noise(clean, alpha, beta):
    # 散粒噪声
    shot_noise = np.random.poisson(clean * alpha) / alpha - clean
    # 读出噪声
    read_noise = np.random.normal(0, np.sqrt(beta), clean.shape)
    # 叠加
    noisy = clean + shot_noise + read_noise
    return noisy

注意:合成数据要覆盖ISO从100到6400的范围。我一般每个ISO生成5000对图像,保证网络见过各种噪声强度。

2.7 真实噪声数据集介绍

合成数据虽然方便,但和真实数据总有差距。所以,真实数据集是验证模型泛化能力的试金石。

SIDD (Smartphone Image Denoising Dataset)

  • 来源:5部智能手机,10个场景
  • 内容:静态场景下,每张图拍多帧,平均得到干净参考
  • 规模:约30,000对图像
  • 特点:真实传感器噪声,包含散粒噪声、读出噪声、固定模式噪声

DND (Darmstadt Noise Dataset)

  • 来源:4台相机,50个场景
  • 内容:低ISO多帧平均作为干净参考,高ISO作为噪声图
  • 规模:50对图像(测试集)
  • 特点:分辨率高,噪声水平标注准确
数据集 图像数量 传感器类型 噪声范围 干净参考获取方式
SIDD 30,000+ 手机CMOS ISO 100-6400 多帧平均
DND 50 相机CMOS ISO 100-25600 低ISO多帧平均

避坑指南:我曾经直接用SIDD训练,在DND上测试,结果PSNR掉了3个dB。为什么?因为手机和相机的噪声特性不一样。所以,训练集和测试集的传感器要匹配,或者做域自适应。

2.8 本章知识体系

下面这张图,把本章的核心逻辑串起来了:

噪声模型与数据集构建知识体系 传感器噪声来源 光子散粒噪声 读出噪声 固定模式噪声 噪声建模方法 泊松-高斯模型 参数拟合 (α, β) 数据集构建 合成噪声数据 真实数据集 (SIDD/DND) 核心思路:理解噪声物理来源 → 建立数学模型 → 生成训练数据 合成数据用于训练,真实数据用于验证,两者互补

2.9 小结

这一章,我们拆解了传感器噪声的三个来源,建立了泊松-高斯模型,也聊了合成数据和真实数据怎么用。

我个人觉得,噪声模型是降噪算法的地基。地基没打牢,上面盖多高的楼都白搭。你想想看,如果连噪声是什么分布都不知道,你怎么设计网络结构?怎么调损失函数?