1. 基于灰度世界假设的AWB校正
任务目标
实现经典灰度世界白平衡算法:假设场景中RGB三通道的平均值趋于同一灰度值,据此估计光源颜色并校正偏色图像。输入一张偏色图像,输出校正后的图像及三通道增益系数,用于验证算法有效性。
环境依赖
Python 3.8+,需安装 numpy 与 opencv-python(仅用于图像读写,核心算法不依赖OpenCV)。
核心实现
import numpy as np
def gray_world_awb(img):
"""
灰度世界白平衡校正
img: HxWx3 uint8 BGR图像 (OpenCV格式)
返回: 校正后图像(uint8 BGR), 增益系数(gains)
"""
# 转换为float避免溢出
img_f = img.astype(np.float32)
# 计算各通道均值
mean_b = np.mean(img_f[:, :, 0])
mean_g = np.mean(img_f[:, :, 1])
mean_r = np.mean(img_f[:, :, 2])
# 灰度世界假设:三通道均值应相等,取整体均值作为目标灰度
gray_target = (mean_b + mean_g + mean_r) / 3.0
# 计算增益并防止除零
eps = 1e-6
gain_b = gray_target / (mean_b + eps)
gain_g = gray_target / (mean_g + eps)
gain_r = gray_target / (mean_r + eps)
# 应用增益并裁剪到有效范围
corrected = np.zeros_like(img_f)
corrected[:, :, 0] = np.clip(img_f[:, :, 0] * gain_b, 0, 255)
corrected[:, :, 1] = np.clip(img_f[:, :, 1] * gain_g, 0, 255)
corrected[:, :, 2] = np.clip(img_f[:, :, 2] * gain_r, 0, 255)
return corrected.astype(np.uint8), (gain_b, gain_g, gain_r)
# 最小调用入口
if __name__ == "__main__":
import cv2
# 读取偏色图像(请替换为实际路径)
img = cv2.imread("input.jpg")
if img is None:
raise FileNotFoundError("无法读取图像,请检查路径")
corrected_img, gains = gray_world_awb(img)
cv2.imwrite("output.jpg", corrected_img)
# 打印增益系数
print(f"Gain B: {gains[0]:.3f}, Gain G: {gains[1]:.3f}, Gain R: {gains[2]:.3f}")
# 验证:校正后三通道均值应接近
corrected_f = corrected_img.astype(np.float32)
print(f"校正后均值 B: {np.mean(corrected_f[:,:,0]):.2f}, "
f"G: {np.mean(corrected_f[:,:,1]):.2f}, "
f"R: {np.mean(corrected_f[:,:,2]):.2f}")
运行与验证
- 将上述代码保存为
awb_gray_world.py,准备一张明显偏色的测试图像(如白炽灯下拍摄的照片)命名为input.jpg放在同目录。 - 运行
python awb_gray_world.py。 - 通过条件:程序无报错退出;生成的
output.jpg中原本偏色区域(如偏黄或偏蓝的白色物体)恢复为中性色;控制台打印的校正后三通道均值基本接近(差值小于5视为有效)。
效果评估要点
灰度世界算法对色彩丰富的场景效果良好,但对大面积单色场景(如蓝天、绿草)会失效,因为灰度假设不成立。若测试图像校正后出现互补色偏(如原偏黄变为偏蓝),说明场景不满足灰度世界假设,属正常现象,可换用色彩丰富的图像验证。
上图展示了灰度世界算法的完整处理链路:从偏色输入中统计通道均值,计算各通道增益,最终使输出图像的三通道均值趋于一致,从而消除光源颜色带来的色偏。