4、白平衡与色彩校正:AWB算法原理、色温估计、色彩校正矩阵、色彩空间转换

白平衡和色彩校正,是手机拍照「好看」的第一道关卡。你想想看,一张照片如果偏蓝或者偏黄,用户第一反应就是「这手机不行」。我做了这么多年Camera调试,AWB(自动白平衡)调得好不好,直接决定了成片率。

说白了,AWB要解决的核心问题就一个:让白色物体在任何光源下都呈现为白色。听起来简单,做起来可没那么容易。

核心概念速览:
  • AWB(自动白平衡):自动消除光源色温影响,还原物体真实颜色
  • 色温估计:判断当前场景的光源类型(日光、白炽灯、荧光灯等)
  • 色彩校正矩阵(CCM):修正传感器与标准色空间之间的偏差
  • 色彩空间转换:将RAW数据映射到sRGB/Display P3等标准色域
AWB与色彩校正整体流程 RAW 输入 色温估计 AWB 增益 CCM 校正 色彩空间转换 sRGB 输出 反馈调整 Gamma/LUT 💡 关键点: AWB 和 CCM 是串联关系——先做白平衡消除色温偏差,再做 CCM 修正传感器特性。 顺序搞反了,色彩就会乱套。我在项目中见过有人把 CCM 放在 AWB 前面,结果怎么调都偏色。

4.1 色温估计——猜猜现在是什么光

色温估计是AWB的第一步,也是最关键的一步。传感器不知道当前是日光还是白炽灯,它只能看到一堆RGB数值。我们需要从这些数值里「猜」出光源色温。

常用的方法有几种:

  • 灰度世界法(Gray World):假设场景中所有颜色的平均值是灰色。如果R/G/B均值不相等,就说明有色偏。这个方法简单,但遇到大面积纯色场景(比如蓝天、绿草地)就翻车了。
  • 完美反射法(Perfect Reflector):假设场景中最亮的像素是白色。找到这些像素,用它们的RGB比例来估计色温。嗯,这个方法在暗光下容易出问题。
  • 色温曲线法:在色度图上预先标定不同光源的轨迹(普朗克轨迹),然后根据当前色度坐标找到最近的色温点。这个方法精度高,但需要大量标定数据。
我的经验:实际产品中很少只用一种方法。我习惯用「灰度世界 + 色温曲线」融合方案——先用灰度世界做粗估计,再用色温曲线做精调。遇到大面积单色场景时,还要加入人脸检测作为辅助判断。曾经有个项目,用户拍了一整面红墙,灰度世界直接崩了,后来加了人脸肤色约束才搞定。

4.2 AWB增益计算——给RGB通道「调音量」

估计出色温后,下一步就是计算R/G/B三个通道的增益。目标是把白色物体的RGB值拉到相等。

假设我们估计当前色温下,白色物体的R/G/B比例是 [1.2, 1.0, 0.9],那么增益就是:

R_gain = 1.0 / 1.2 ≈ 0.833
G_gain = 1.0 / 1.0 = 1.0
B_gain = 1.0 / 0.9 ≈ 1.111

实际应用中,增益不能无限大。我一般会限制在 [0.5, 2.0] 范围内,否则噪声会被放大到不可接受的程度。

⚠️ 注意:增益太大 = 噪声爆炸。低光场景下,B通道增益如果超过2.0,蓝色通道的噪声会非常明显。我曾经在一个夜景项目里,为了把偏黄的灯光拉回白色,B增益设到了2.5,结果照片上全是蓝色噪点。后来加了增益上限和降噪联动,才解决问题。

4.3 色彩校正矩阵(CCM)——给传感器「纠偏」

做完AWB,颜色看起来正常了吗?其实还不够。传感器的RGB响应和标准人眼视觉(CIE 1931)之间是有偏差的。这就是CCM要解决的问题。

CCM是一个3×3矩阵,把传感器RGB转换到标准色空间:

[ R_std ]   [ a11  a12  a13 ]   [ R_sensor ]
[ G_std ] = [ a21  a22  a23 ] * [ G_sensor ]
[ B_std ]   [ a31  a32  a33 ]   [ B_sensor ]

这个矩阵怎么来的?靠标定。用24色卡在标准光源下拍照,然后通过最小二乘法拟合出最优矩阵。

参数 典型值范围 说明
对角元素 (a11, a22, a33) 0.8 ~ 1.2 主通道增益,通常接近1.0
非对角元素 -0.3 ~ 0.3 通道间串扰修正,值越大说明传感器越「不标准」
矩阵行和 ≈ 1.0 保证亮度不变,如果偏差太大说明标定有问题
调试心得:CCM不是一成不变的。不同色温下,传感器的响应特性会变化。我一般会标定3~5组CCM(低色温、中色温、高色温),然后根据AWB估计的色温做插值。这样在色温变化时,色彩过渡才自然。

4.4 色彩空间转换——从RAW到sRGB

最后一步,是把校正后的RGB数据映射到目标色空间。手机摄像头最常用的是sRGB和Display P3。

转换过程包括:

  1. 线性RGB → 非线性RGB:应用Gamma曲线(sRGB Gamma ≈ 2.2)
  2. 色域裁剪:把超出目标色域的颜色映射回来
  3. 量化:从12/14bit RAW数据量化到8bit输出

这里有个坑——色域裁剪。sRGB的色域比传感器原生色域小很多,很多鲜艳的颜色会被裁掉。我见过一些手机拍出来的红花变成「死红」,就是因为色域裁剪太粗暴。

我的做法:用「软裁剪」代替硬裁剪。在色域边界附近做平滑过渡,而不是一刀切。这样颜色看起来更自然,不会出现明显的色块断层。另外,如果支持Display P3,尽量用P3——它的色域比sRGB大25%,能保留更多色彩细节。

4.5 避坑指南——我踩过的那些坑

  • 坑1:AWB和CCM顺序搞反——先做CCM再做AWB,会导致色温估计被CCM扭曲。我曾经在一个项目里调试了三天,发现怎么调都偏色,最后发现是流水线顺序错了。
  • 坑2:CCM过拟合——用24色卡标定CCM时,如果只针对特定光源,换到其他光源下颜色就崩了。我建议至少用D65、D50、A光源三组数据做联合优化。
  • 坑3:忽略暗角影响——镜头边缘的亮度下降会导致AWB估计偏差。如果不做暗角校正,边缘区域的色温估计会偏。我习惯在AWB之前先做LSC(镜头阴影校正)。
  • 坑4:增益饱和——低光下AWB增益过大,导致通道饱和。饱和后的像素无法恢复,颜色信息永久丢失。解决方案是限制最大增益,或者改用多帧融合。
⚠️ 重要提醒:AWB和CCM的调试,一定要在真实场景下验证。实验室里的标准光源和实际生活中的混合光源(比如日光+LED)差别很大。我每次调完参数,都会拿着手机去办公室、商场、公园拍一圈,看看有没有偏色场景。