4. 白平衡(AWB):灰度世界法、完美反射法、色温估计、增益调整的流水线设计、FPGA中的统计模块实现

白平衡,说白了就是让白色物体在照片里看起来是白的。你想想看,在日光灯下拍的白纸,如果直接显示出来可能偏蓝;在白炽灯下拍,又可能偏黄。人眼会自动校正这种色偏,但CMOS传感器可没这个本事。所以,ISP流水线里必须有一道工序来干这个活。

我个人习惯把AWB分成两个阶段:统计阶段和校正阶段。统计阶段在FPGA里实时算,校正阶段则通过增益乘法器来调整RGB通道。今天我们就把这套流水线拆开来看。

4.1 灰度世界法(Gray World)

这个算法假设:一张色彩丰富的照片,所有像素的R、G、B平均值应该趋于相等。如果不等,说明有色偏,我们就用增益把平均值拉到同一个水平线上。

公式很简单:

R_gain = G_avg / R_avg
B_gain = G_avg / B_avg
G_gain = 1.0

我在项目中遇到过一个问题:如果场景里大面积的单色物体(比如一面红墙),灰度世界法就会失效——它会强行把红墙拉成灰色。所以,这个算法只适合色彩丰富的场景。

我的经验:灰度世界法适合做粗调,计算量小,FPGA里只需要三个累加器和一个除法器。但别指望它搞定所有场景。

4.2 完美反射法(Perfect Reflector)

这个算法的思路是:图像中最亮的那个像素点,应该代表光源的颜色。找到这个点,然后用它的RGB值来推算增益。

具体做法:

  1. 遍历所有像素,找到亮度最高的那个点(或者前0.1%最亮的点)
  2. 记录这个点的R_max、G_max、B_max
  3. 计算增益:R_gain = G_max / R_max,B_gain = G_max / B_max

嗯,这里要注意:如果场景里本身就有高亮光源(比如太阳),完美反射法也会翻车。我曾经在拍夜景时用过这个算法,结果把路灯当成了参考白点,整张图偏得一塌糊涂。

避坑指南:完美反射法对噪声非常敏感。FPGA实现时,一定要先做降噪滤波,再做最大值统计。否则一个热像素就能把整个白平衡带偏。

4.3 色温估计(Color Temperature Estimation)

灰度世界法和完美反射法都是纯统计方法,没有考虑物理意义。色温估计则更进了一步——它试图估算出当前光源的色温,然后查表得到对应的增益。

色温估计的常用方法:

  • R/G 和 B/G 比值法:计算全图的R/G和B/G比值,然后映射到色温曲线上
  • 白点检测法:先找出可能属于白色区域的像素,再用这些像素的色度值估算色温

我一般会在FPGA里同时跑两种统计:一种是全图平均,一种是白点区域统计。然后根据场景置信度做加权融合。这样既保留了灰度世界法的稳定性,又吸收了色温估计的准确性。

方法 优点 缺点 FPGA资源消耗
灰度世界法 计算简单,稳定 大色块场景失效 低
完美反射法 对亮部还原好 易受噪声和光源干扰 中
色温估计 物理意义明确 需要查表,依赖校准 中高

4.4 增益调整的流水线设计

增益调整在FPGA里就是三个乘法器的事:

R_out = R_in * R_gain
G_out = G_in * G_gain
B_out = B_in * B_gain

但流水线设计的关键在于时序和精度。我建议用定点数表示增益,比如Q8.8格式(8位整数,8位小数)。这样乘法结果可以直接截取高16位输出。

流水线结构:

  1. Stage 1:读取像素和增益系数
  2. Stage 2:执行乘法运算
  3. Stage 3:截位和饱和处理
  4. Stage 4:输出校正后的像素

我曾经在调试时发现,如果增益系数更新太快,画面会出现闪烁。后来加了一个低通滤波器,让增益缓慢变化,问题就解决了。

关键点:增益更新频率不要超过帧率的1/10。比如30fps的系统,每300ms更新一次增益就够了。

4.5 FPGA中的统计模块实现

统计模块是AWB的大脑。它需要在像素流中实时计算各种统计量。我常用的统计模块包括:

  • RGB累加器:计算全图R、G、B的和,用于灰度世界法
  • 最大值检测器:找出R、G、B的最大值,用于完美反射法
  • 直方图统计:统计R/G和B/G比值的分布,用于色温估计
  • 白点检测器:判断每个像素是否属于白色区域

下面是我常用的统计模块结构图:

AWB 统计模块流水线结构 像素输入 RGB累加器 最大值检测 直方图统计 白点检测器 加权融合 & 增益计算 增益输出 说明: 1. 四个统计模块并行工作,互不干扰 2. 白点检测器输出掩码,控制其他模块的统计范围 3. 加权融合模块根据场景置信度选择最优增益

在FPGA实现时,我建议用双缓冲结构。一帧统计,下一帧应用增益。这样既保证了实时性,又避免了统计和校正的时序冲突。

实现技巧:统计模块的位宽要留够余量。比如1080p图像,RGB累加器至少需要32位,否则会溢出。我一般用36位,多出来的4位做保护。

4.6 综合对比与选型建议

三种方法各有适用场景。我一般这样选:

  • 消费级摄像头:灰度世界法 + 白点检测,性价比最高
  • 工业相机:色温估计 + 完美反射法,精度优先
  • 车载摄像头:三种方法加权融合,鲁棒性第一

嗯,最后说一句:AWB没有银弹。最好的方案是根据应用场景做定制化设计。FPGA的好处就是灵活——你可以随时切换算法,甚至在同一帧里对不同区域用不同的白平衡策略。