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
我在项目中遇到过一个问题:如果场景里大面积的单色物体(比如一面红墙),灰度世界法就会失效——它会强行把红墙拉成灰色。所以,这个算法只适合色彩丰富的场景。
4.2 完美反射法(Perfect Reflector)
这个算法的思路是:图像中最亮的那个像素点,应该代表光源的颜色。找到这个点,然后用它的RGB值来推算增益。
具体做法:
- 遍历所有像素,找到亮度最高的那个点(或者前0.1%最亮的点)
- 记录这个点的R_max、G_max、B_max
- 计算增益:R_gain = G_max / R_max,B_gain = G_max / B_max
嗯,这里要注意:如果场景里本身就有高亮光源(比如太阳),完美反射法也会翻车。我曾经在拍夜景时用过这个算法,结果把路灯当成了参考白点,整张图偏得一塌糊涂。
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位输出。
流水线结构:
- Stage 1:读取像素和增益系数
- Stage 2:执行乘法运算
- Stage 3:截位和饱和处理
- Stage 4:输出校正后的像素
我曾经在调试时发现,如果增益系数更新太快,画面会出现闪烁。后来加了一个低通滤波器,让增益缓慢变化,问题就解决了。
4.5 FPGA中的统计模块实现
统计模块是AWB的大脑。它需要在像素流中实时计算各种统计量。我常用的统计模块包括:
- RGB累加器:计算全图R、G、B的和,用于灰度世界法
- 最大值检测器:找出R、G、B的最大值,用于完美反射法
- 直方图统计:统计R/G和B/G比值的分布,用于色温估计
- 白点检测器:判断每个像素是否属于白色区域
下面是我常用的统计模块结构图:
在FPGA实现时,我建议用双缓冲结构。一帧统计,下一帧应用增益。这样既保证了实时性,又避免了统计和校正的时序冲突。
4.6 综合对比与选型建议
三种方法各有适用场景。我一般这样选:
- 消费级摄像头:灰度世界法 + 白点检测,性价比最高
- 工业相机:色温估计 + 完美反射法,精度优先
- 车载摄像头:三种方法加权融合,鲁棒性第一
嗯,最后说一句:AWB没有银弹。最好的方案是根据应用场景做定制化设计。FPGA的好处就是灵活——你可以随时切换算法,甚至在同一帧里对不同区域用不同的白平衡策略。