4. AWB经典算法-灰度世界法
灰度世界法,说白了就是图像白平衡领域里最基础、最直觉的一种方法。我最早接触AWB时,第一个上手的就是它。你想想看,如果一张照片里所有颜色的平均值刚好是灰色,那这张照片的白平衡大概率就是对的——这个假设,就是灰度世界法的核心。
4.1 灰度世界假设原理
这个假设其实很朴素:一张色彩丰富的自然图像,其R、G、B三个通道的像素平均值应该趋于相等。换句话说,整张图的平均颜色应该是中性灰(Gray)。
为什么会这样?因为自然界中各种颜色的物体足够多,统计下来,它们的平均反射率就是灰色。我在项目中遇到过一些极端场景,比如整个画面都是蓝色天空或者红色墙壁,这时候灰度世界法就会失效——嗯,这个我们后面再细说。
核心公式:
假设图像平均颜色为 (R_avg, G_avg, B_avg),则三个通道的增益为:
R_gain = G_avg / R_avg
G_gain = 1.0
B_gain = G_avg / B_avg
校正后像素值 = 原始像素值 × 对应通道增益
4.2 算法实现步骤
灰度世界法的实现步骤其实很简单,我一般把它拆成5步:
- 计算各通道均值:遍历图像所有像素,分别累加R、G、B值,除以总像素数。
- 确定参考值:通常取G通道均值作为参考,因为人眼对绿色最敏感。
- 计算增益系数:用参考值除以各通道均值,得到R_gain、G_gain、B_gain。
- 应用增益校正:每个像素的R、G、B值乘以对应的增益系数。
- 像素值裁剪:将超出[0, 255]范围的值截断到边界。
代码实现也很直接,我贴一段我常用的C++实现:
void grayWorldAWB(Mat& src, Mat& dst) {
// 1. 计算各通道均值
Scalar meanVal = mean(src);
double R_avg = meanVal[2];
double G_avg = meanVal[1];
double B_avg = meanVal[0];
// 2. 以G通道为参考
double ref = G_avg;
// 3. 计算增益
double R_gain = ref / R_avg;
double G_gain = 1.0;
double B_gain = ref / B_avg;
// 4. 应用增益
vector<Mat> channels(3);
split(src, channels);
channels[2] *= R_gain; // R通道
channels[1] *= G_gain; // G通道
channels[0] *= B_gain; // B通道
// 5. 合并并裁剪
merge(channels, dst);
dst.convertTo(dst, CV_8UC3);
}
我的小技巧:实际项目中,我习惯先对图像做一次高斯模糊再计算均值,这样可以减少噪点对增益计算的影响。尤其是低光照场景下,这个预处理能明显提升稳定性。
4.3 优缺点分析
灰度世界法最大的优点就是简单、快速。不需要任何训练数据,不需要标定,几行代码就能跑起来。我早期做手机相机调试时,经常用它做白平衡的快速验证。
但它的缺点也很明显:
| 优点 | 缺点 |
|---|---|
| 实现简单,计算量小 | 假设过于理想,真实场景常不满足 |
| 无需先验知识 | 大面积单色场景会严重偏色 |
| 对色彩丰富的图像效果不错 | 对暗部噪声敏感 |
| 适合实时处理 | 无法处理多光源混合场景 |
我曾经踩过的坑:有一次做户外监控摄像头的白平衡,画面里一大片绿色草坪,灰度世界法直接把整个画面拉成了紫色。后来我才意识到,当某个颜色占比超过60%时,灰度世界法基本就废了。
4.4 适用场景
灰度世界法虽然简单,但用对地方还是很香的。我个人建议在以下场景优先考虑它:
- 色彩丰富的自然场景:比如风景照、多人合影、街拍等。
- 实时预览:手机相机取景框、视频通话等对延迟敏感的场景。
- 作为其他算法的初始化:很多高级AWB算法会用灰度世界法做第一轮粗调。
- 资源受限的嵌入式设备:比如树莓派、海思芯片等。
但如果你遇到以下情况,建议换算法:
- 画面主体是单一颜色(蓝天、草地、红墙)
- 场景中有明显的主光源色温偏移
- 需要高精度色彩还原的专业摄影
4.5 灰度世界法知识图谱
下面这张图是我自己整理的灰度世界法核心逻辑,方便你快速理解整个流程:
4.6 改进思路
灰度世界法虽然简单,但我们可以给它打几个补丁:
- 加权灰度世界:给不同亮度区域的像素赋予不同权重,避免暗部噪声干扰。
- 动态阈值裁剪:排除过亮和过暗的像素,只统计中间调区域。
- 分块处理:将图像分成若干块,每块独立计算增益,再插值融合。
我记得有一次做车载摄像头项目,光线变化特别剧烈,单纯用灰度世界法根本扛不住。后来我加了动态阈值裁剪,把最亮5%和最暗5%的像素排除掉,效果好了很多。你想想看,那些过曝和欠曝的区域本来就不该参与白平衡计算,对吧?
一句话总结:灰度世界法是AWB的入门必修课,简单但有效。用它做快速原型验证非常合适,但生产环境建议配合其他算法一起使用。