2、客观评测指标详解(上):信噪比(SNR)的计算与测量方法、不同光照条件下的SNR表现、SNR与画质的关系

各位同学,今天我们聊一个非常基础但又极其重要的指标——信噪比,也就是 SNR。很多刚入行的朋友觉得 SNR 不就是个比值嘛,看看就完了。但说实话,我在项目里踩过的坑,有一半都跟 SNR 的误判有关。你想想看,一个指标如果测不准,后面所有的调优都是白费功夫。

2.1 什么是信噪比?

信噪比,全称 Signal-to-Noise Ratio,说白了就是有用信号和噪声的比值。单位是 dB,公式很简单:

SNR = 10 * log10(Psignal / Pnoise)

其中 Psignal 是信号功率,Pnoise 是噪声功率。比值越大,说明信号越干净,画质越好。

我个人习惯把 SNR 理解为「水杯里的糖水」——信号是糖,噪声是水。糖越多,水越少,喝起来越甜。但现实中,噪声永远存在,你只能尽量让糖多一点儿。

核心认知: SNR 不是值,而是相对值。同一个场景,不同传感器测出来的 SNR 可能差很多,这跟 sensor 的量子效率、读出噪声、暗电流都有关系。

2.2 SNR 的计算与测量方法

测量 SNR 的方法有好几种,我挑最常用的两种讲。

2.2.1 均匀区域法

这是最直观的方法。拍一张均匀灰卡或均匀光照下的 flat field 图像,然后:

  1. 选取一块平坦区域(比如 100x100 像素)
  2. 计算该区域像素值的均值 μ,作为信号强度
  3. 计算该区域像素值的标准差 σ,作为噪声强度
  4. SNR = 20 * log10(μ / σ)

注意这里用的是 20log,因为像素值是电压或数字码值,属于幅度量。如果是功率量才用 10log。这个细节很多人搞混,我刚开始也犯过这个错。

// 伪代码示例
def calculate_snr(image, roi):
    patch = image[roi.y:roi.y+roi.h, roi.x:roi.x+roi.w]
    mean_val = np.mean(patch)
    std_val = np.std(patch)
    if std_val == 0:
        return float('inf')
    snr = 20 * np.log10(mean_val / std_val)
    return snr

小技巧: 选 ROI 时尽量避开边缘和镜头阴影区域。我一般选图像中心偏一点的位置,因为中心区域的光学衰减最小,测出来的 SNR 最接近 sensor 的真实能力。

2.2.2 双图像法

有时候场景不是均匀的,比如你拍的是实景。这时候可以用双图像法:

  1. 连续拍两张完全相同的场景(固定相机、固定光照)
  2. 两张图像逐像素相减,得到差异图像
  3. 差异图像的标准差就是噪声的估计(因为信号被抵消了)
  4. 原始图像的标准差作为信号+噪声的估计
  5. 通过公式反推 SNR

这个方法的好处是不需要均匀场景,但要求两张图像严格对齐。我曾在手机模组测试中用过这个方法,结果因为手持微抖动,两张图没对齐,算出来的 SNR 直接负了……后来加了稳像算法才搞定。

2.3 不同光照条件下的 SNR 表现

SNR 不是一成不变的。光照越强,信号越强,SNR 越高。但这里有个非线性关系,我画了张图来说明。

不同光照条件下的 SNR 变化趋势 光照强度 (lux) 0 10 100 1000 10000 0 dB 20 dB 40 dB 60 dB 0 lux 10 lux 100 lux 1000 lux 10000 lux 低光区 (SNR < 20dB) 中光区 (20-40dB) 高光区 (SNR > 40dB) 说明:低光区 SNR 增长缓慢,中光区线性增长,高光区趋于饱和(受 sensor 满阱容量限制)

从图上可以清楚看到三个区域:

  • 低光区(<10 lux): SNR 很低,通常不到 20dB。这时候噪声主要是读出噪声和暗电流噪声,信号被噪声淹没。我做过一个夜景项目,SNR 只有 12dB,画面全是噪点,降噪算法怎么调都救不回来。
  • 中光区(10-1000 lux): SNR 随光照线性增长。这是大多数室内场景的范围,也是 ISP 调优的主战场。
  • 高光区(>1000 lux): SNR 增长放缓,最终趋于饱和。因为 sensor 的满阱容量有限,信号不能无限增大。

注意: 高光区 SNR 饱和不代表画质最好。我见过一些项目为了追求高 SNR 拼命增加曝光,结果高光过曝,细节全丢。SNR 高不等于画质好,这个后面会细讲。

2.4 SNR 与画质的关系

SNR 和画质的关系,我用一个表格来总结:

SNR 范围 画质表现 典型场景 ISP 处理重点
< 20 dB 噪声明显,细节丢失严重 夜景、暗光室内 强降噪、多帧融合
20 - 30 dB 可接受,但仍有可见噪点 黄昏、普通室内 适度降噪、边缘保护
30 - 40 dB 画质良好,噪声不明显 白天室内、阴天室外 轻微降噪、锐化
40 - 50 dB 画质优秀,几乎无噪声 晴天室外、强光 锐化、色彩增强
> 50 dB 画质极佳,但可能过曝 直射阳光、雪地 高光压缩、HDR

这里有个关键点:SNR 和主观画质不是线性关系。我做过一个盲测实验,30dB 和 35dB 的图像,人眼几乎分不出区别。但 20dB 和 25dB 的差距,一眼就能看出来。所以 SNR 的「及格线」大概在 25-30dB 之间。

我的经验: 在 ISP 调优时,不要盲目追求高 SNR。有时候为了 SNR 提高 3dB,付出的代价是功耗翻倍、帧率减半。性价比最高的 SNR 区间是 30-40dB,这个范围内画质和资源消耗最平衡。

2.5 避坑指南

最后分享几个我踩过的坑:

  • 不要用 JPEG 算 SNR: JPEG 有损压缩会改变噪声分布,算出来的 SNR 不准。一定要用 RAW 或 BMP 格式。
  • 注意暗电流补偿: 测 SNR 前要先做暗电流校正,否则暗场下的噪声会被低估。
  • 区分 temporal noise 和 fixed pattern noise: 前者是时域噪声,多帧平均可以消除;后者是空域噪声,平均没用。测 SNR 时要说明测的是哪种。
  • ROI 大小要一致: 不同大小的 ROI 算出来的标准差不一样,对比 SNR 时要用相同尺寸的 ROI。