3. 实现自动白平衡灰度世界算法

任务目标

本案例基于灰度世界假设(Gray World Assumption)实现自动白平衡:统计图像RGB三通道的平均值,以三通道均值的均值为基准计算各通道增益,对每个像素进行增益校正,从而消除环境光源造成的色偏。输入为普通RGB图像(如偏黄或偏蓝的室内照片),输出为校正后的图像。

核心原理

灰度世界假设认为:一幅色彩丰富的自然图像,其RGB三通道的平均值应趋于同一灰度值。若图像存在色偏,则三通道均值不相等。算法通过计算各通道增益,将三通道均值拉平到同一水平:

  • 计算全图R、G、B通道均值 meanR, meanG, meanB
  • 计算灰度基准 gray = (meanR + meanG + meanB) / 3
  • 各通道增益:gainR = gray / meanR,gainG = gray / meanG,gainB = gray / meanB
  • 校正:out = clamp(pixel * gain),像素值限制在[0, 255]

完整实现(Python + OpenCV)

import cv2
import numpy as np

def gray_world_awb(img):
    """
    灰度世界自动白平衡
    img: BGR图像 (H, W, 3), dtype=uint8
    返回: 校正后的BGR图像 (H, W, 3), dtype=uint8
    """
    # 转换为float避免溢出
    img_f = img.astype(np.float32)

    # 1. 计算各通道均值
    mean_b = np.mean(img_f[:, :, 0])
    mean_g = np.mean(img_f[:, :, 1])
    mean_r = np.mean(img_f[:, :, 2])

    # 2. 灰度基准
    gray = (mean_r + mean_g + mean_b) / 3.0

    # 3. 各通道增益(防止除零)
    eps = 1e-6
    gain_r = gray / (mean_r + eps)
    gain_g = gray / (mean_g + eps)
    gain_b = gray / (mean_b + eps)

    # 4. 像素校正并裁剪到[0,255]
    out = np.zeros_like(img_f)
    out[:, :, 0] = np.clip(img_f[:, :, 0] * gain_b, 0, 255)  # B通道
    out[:, :, 1] = np.clip(img_f[:, :, 1] * gain_g, 0, 255)  # G通道
    out[:, :, 2] = np.clip(img_f[:, :, 2] * gain_r, 0, 255)  # R通道

    return out.astype(np.uint8)

# 最小调用入口
if __name__ == "__main__":
    # 读取图像(请替换为实际路径)
    img = cv2.imread("input.jpg")
    if img is None:
        print("错误:无法读取图像,请检查路径")
        exit(1)

    # 执行白平衡
    result = gray_world_awb(img)

    # 保存结果
    cv2.imwrite("output.jpg", result)
    print("处理完成,结果已保存为 output.jpg")

运行方式

  1. 安装依赖:pip install opencv-python numpy
  2. 将待校正图像命名为 input.jpg 放在脚本同目录
  3. 运行:python awb_gray_world.py

验证方法

通过以下两种方式验证算法是否生效:

  • 视觉检查:打开 output.jpg,观察原本偏黄(暖色)或偏蓝(冷色)的图像是否恢复为中性色调,白色物体应呈现为白色。
  • 数值验证:在代码中增加以下统计,观察校正前后三通道均值是否趋近相等:
# 验证辅助代码(可临时追加到main中)
mean_before = img.reshape(-1, 3).mean(axis=0)
mean_after = result.reshape(-1, 3).mean(axis=0)
print("校正前BGR均值:", mean_before)
print("校正后BGR均值:", mean_after)

通过条件:校正后三通道均值之间的最大差值小于5(例如B=120.1, G=121.3, R=119.8),且图像无明显色偏。

常见问题

  • 图像整体偏暗或过曝:灰度世界算法只做颜色校正,不调整亮度。若校正后亮度异常,说明原图本身曝光有问题,需先做曝光校正。
  • 大面积单色场景失效:若画面被单一颜色主导(如纯蓝天、纯红墙),灰度世界假设不成立,校正结果可能偏色。此时可改用更鲁棒的算法(如完美反射法),但不在本案例范围内。
  • 增益过大导致过曝:当某通道均值极低时,增益会很大,导致该通道像素被裁剪到255。这是灰度世界算法的已知局限,可通过限制最大增益(如不超过3.0)缓解。
灰度世界自动白平衡流程 输入图像(偏黄) 步骤1 计算三通道均值 meanR, meanG, meanB 步骤2 gray = 均值均值 gain = gray / mean 步骤3 像素 × 增益 裁剪到[0,255] 输出图像(中性色) 逐像素应用增益 增益公式 gain_R = (meanR+meanG+meanB) / (3 × meanR) gain_G = (meanR+meanG+meanB) / (3 × meanG) gain_B = (meanR+meanG+meanB) / (3 × meanB)