第四章 自动白平衡(AWB)调优:让色彩回归真实

自动白平衡,说白了就是让相机知道「什么是白色」。你想想看,同一张白纸,在日光灯下发青,在白炽灯下发黄,在烛光下发红。人眼会自动校正,但传感器不会。AWB 的任务,就是把这个偏差拉回来。

我在 8K HDR 项目里吃过 AWB 的亏。画面一暗,色温就开始飘,用户投诉说「你们家的摄像机拍人像像鬼片」。嗯,从那以后我对 AWB 的收敛速度和稳定性就特别敏感。

4.1 AWB 的两大基石:灰度世界与完美反射

先讲最经典的两个算法模型。几乎所有商用 ISP 的 AWB 模块,底层都离不开它们。

4.1.1 灰度世界(Gray World)

假设场景中所有颜色的平均反射率是中性灰。也就是说,整幅图像的 R、G、B 均值应该相等。如果不相等,说明有色偏,需要调整增益。

核心公式:

R_gain = G_avg / R_avg
B_gain = G_avg / B_avg

调整后:R' = R × R_gain,B' = B × B_gain,G 保持不变。

这个模型简单、计算量小,但有个致命弱点——如果场景本身就不是「灰度世界」呢?比如一片蓝天、一片绿草地,均值天然偏蓝或偏绿,强行拉平就会出错。

避坑指南:我曾经在户外航拍场景中用过纯灰度世界,结果蓝天被拉成了灰白色。后来加了场景分类器,只在室内混合光源下才主用灰度世界。

4.1.2 完美反射(Perfect Reflector / White Patch)

假设场景中最亮的像素点应该是纯白色。找到 R、G、B 三个通道各自的最大值,用它们来估算光源色温。

核心思路:

R_max = max(R_pixel)
G_max = max(G_pixel)
B_max = max(B_pixel)
R_gain = G_max / R_max
B_gain = G_max / B_max

这个方法对高光区域很敏感。如果场景里有镜面反射、灯泡、太阳直射点,效果很好。但如果场景本身没有「纯白」区域,比如拍一片深色森林,最大值可能只是噪声,结果会崩。

我的习惯:把灰度世界和完美反射做加权融合。室内场景完美反射权重高一些,室外大色块场景灰度世界权重高一些。权重系数通过标定场景自动切换。

4.2 色温估计:从像素到开尔文

色温估计是 AWB 的中间层。我们不直接调增益,而是先估算当前光源的色温值(单位 K),再查表或插值得到 R/B 增益。

为什么这么做?因为增益和色温不是线性关系。直接调增益容易过冲,而色温空间更平滑、更物理。

4.2.1 色温估计的常用方法

方法 原理 优点 缺点
R/G 与 B/G 比值法 统计全图 R/G、B/G 比值,映射到色温曲线 计算快,适合实时 受大色块干扰严重
色温查找表(LUT) 预标定不同色温下的 R/G、B/G 参考值 精度高,可定制 标定工作量大
神经网络估计 用 CNN 直接从 RAW 图预测色温 鲁棒性好,抗干扰强 算力需求高,8K 实时有压力

我个人习惯用「R/G-B/G 二维直方图 + 色温 LUT」的组合。先统计全图每个像素的 R/G 和 B/G,画成二维直方图,然后找峰值区域。峰值的位置对应光源色温。

关键点:不要用全图均值,要用直方图峰值。全图均值会被大面积色块带偏,而峰值代表场景中占比最大的中性色区域。

4.2.2 色温估计的稳定性问题

你想想看,如果场景里突然走进一个穿红衣服的人,全图 R 均值瞬间升高,色温估计会不会跳?会的。这就是 AWB 最头疼的问题——时间稳定性。

我遇到过最夸张的情况:一个穿黄衣服的人在镜头前走过,AWB 从 5500K 跳到了 4200K,画面从正常变暖,等他走开又跳回来。用户说「你们这摄像机在呼吸」。嗯,确实在呼吸。

解决方案:加入时间域低通滤波。色温估计值不直接输出,而是经过一阶 IIR 滤波器:

CCT_out = α × CCT_current + (1 - α) × CCT_prev

α 取 0.1~0.3,收敛慢但稳定。如果检测到场景切换(亮度突变),可以临时把 α 提到 0.8 快速跟上。

4.3 AWB 收敛速度与稳定性:鱼与熊掌

收敛速度和稳定性是一对矛盾。收敛快了,画面容易闪烁;收敛慢了,用户觉得反应迟钝。8K HDR 场景下,这个问题更突出——因为 8K 帧率通常只有 30fps,每一帧的信息量巨大,但时间分辨率反而低了。

4.3.1 收敛速度的瓶颈

AWB 收敛慢,通常不是算法算不动,而是统计量不够。8K 图像有 3300 万像素,全图统计一次耗时约 2-3ms(在专用 ISP 硬件上)。但如果你做多帧统计,比如取 5 帧平均,收敛延迟就是 5 帧 × 33ms = 165ms。用户能明显感觉到「白平衡在追」。

我的做法:分区域统计。把 8K 图像分成 16×16 的网格,每个网格独立统计 R/G、B/G。只取中间 80% 的网格(排除边缘暗角区域),用这些网格的统计量做色温估计。这样单帧统计量就够了,不需要多帧平均,收敛延迟降到 1 帧。

4.3.2 稳定性保障机制

收敛快了,怎么保证不闪?我总结了三道防线:

  1. 统计量置信度判断:如果当前帧的统计量与前几帧偏差超过阈值,先不更新,等下一帧确认。
  2. 增益变化率限制:每帧 R/B 增益的变化量不超过 0.02(归一化后)。即使色温估计跳了,增益也慢慢变。
  3. 场景切换检测:用亮度直方图做场景切换检测。切换时快速收敛,非切换时慢速平滑。

曾经踩过的坑:我在一个监控项目中,把增益变化率限制设得太严(0.005/帧),结果摄像机从室内移到室外,白平衡花了 3 秒才稳定。用户说「这摄像机是不是坏了」。后来改成自适应变化率——偏差大时变化率放宽,偏差小时收紧。

4.4 AWB 调优的整体流程

下面这张图是我在项目中常用的 AWB 调优流程,从 RAW 图输入到最终增益输出:

AWB 调优流程 AWB 调优流程 RAW 图像输入 16×16 分块 R/G B/G 统计 置信度判断 & 场景切换检测 色温估计(直方图峰值 + LUT) R/B 增益计算 + 变化率限制 增益输出到 ISP 流水线 关键参数 • 分块数:16×16 • 置信度阈值:0.7 • 增益变化率:0.02/帧 避坑提醒 • 不要用全图均值 • 场景切换时加速收敛 • 排除边缘暗角区域

4.5 实战调优参数参考

下面是我在 8K HDR 项目中最终采用的 AWB 参数配置。不同场景可以微调,但大方向可以参考:

参数 推荐值 说明
分块数 16×16 8K 分辨率下每块约 40×30 像素,统计量足够
有效区域 中心 80% 排除边缘暗角,避免暗角偏色干扰
灰度世界权重 0.4 室外大色块场景可降到 0.2
完美反射权重 0.6 室内高光场景可升到 0.8
IIR 滤波系数 α 0.2 场景切换时临时升到 0.8
增益变化率上限 0.02/帧 30fps 下约 0.67/秒,视觉上平滑
色温 LUT 精度 100K 步长 2500K~7500K 共 51 个标定点

最后说一句:AWB 调优没有银弹。灰度世界和完美反射只是起点,真正落地要靠场景自适应、时间域平滑和大量的实拍验证。我每次调完 AWB,都会在 D65(6500K)、A(2856K)、TL84(4000K)三种标准光源下拍 24 色卡,确认色偏在 ΔE 3 以内才算过关。