2. AWB基础

任务目标

实现完美反射(Perfect Reflector)白平衡算法。该算法假设图像中最亮的像素区域可作为场景中白色或灰色参考,通过统计这些高亮像素的RGB均值来估计光源颜色,进而对整幅图像进行通道增益校正,消除色偏。

算法原理

完美反射算法的核心步骤:

  1. 统计图像RGB三通道的直方图,确定各通道的亮度阈值(通常取累计占比前1%的像素作为“最亮点”集合);
  2. 计算这些高亮像素在各通道的均值,作为光源颜色估计值 (R_max, G_max, B_max);
  3. 以最大通道值为基准,计算各通道增益 gain = max_val / channel_max;
  4. 将增益逐像素乘回原图,并做饱和截断。

完整实现

本案例使用Python + OpenCV实现,输入任意彩色图像,输出校正后的图像及增益参数。代码自包含,无需额外数据文件。

import cv2
import numpy as np

def perfect_reflector_awb(img, percentile=99.0):
    """
    完美反射白平衡
    Args:
        img: BGR图像, uint8, 0-255
        percentile: 高亮像素截取百分位 (默认99, 即取最亮1%像素)
    Returns:
        out: 校正后BGR图像, uint8
        gains: (gain_r, gain_g, gain_b) 各通道增益
    """
    # 分离通道
    b, g, r = cv2.split(img.astype(np.float32))

    # 计算各通道高亮阈值 (取百分位对应的像素值)
    thr_b = np.percentile(b, percentile)
    thr_g = np.percentile(g, percentile)
    thr_r = np.percentile(r, percentile)

    # 生成掩码:三通道同时高于各自阈值的像素视为"最亮点"
    mask = (b >= thr_b) & (g >= thr_g) & (r >= thr_r)

    # 若掩码为空(极端情况), 退化为全图最大像素
    if not np.any(mask):
        mask = (b == b.max()) & (g == g.max()) & (r == r.max())

    # 高亮像素各通道均值作为光源估计
    r_max = r[mask].mean()
    g_max = g[mask].mean()
    b_max = b[mask].mean()

    # 以最大通道值为基准计算增益
    max_val = max(r_max, g_max, b_max)
    gain_r = max_val / r_max if r_max > 0 else 1.0
    gain_g = max_val / g_max if g_max > 0 else 1.0
    gain_b = max_val / b_max if b_max > 0 else 1.0

    # 应用增益并截断到[0,255]
    out_r = np.clip(r * gain_r, 0, 255).astype(np.uint8)
    out_g = np.clip(g * gain_g, 0, 255).astype(np.uint8)
    out_b = np.clip(b * gain_b, 0, 255).astype(np.uint8)

    out = cv2.merge([out_b, out_g, out_r])
    return out, (gain_r, gain_g, gain_b)

if __name__ == "__main__":
    # 读取图像 (请替换为实际路径)
    img = cv2.imread("input.jpg")
    if img is None:
        raise FileNotFoundError("未找到输入图像 input.jpg")

    corrected, gains = perfect_reflector_awb(img)

    # 保存结果
    cv2.imwrite("output_awb.jpg", corrected)
    print(f"增益 R={gains[0]:.3f}, G={gains[1]:.3f}, B={gains[2]:.3f}")
    print("校正图像已保存至 output_awb.jpg")

运行与验证

环境依赖:Python 3.7+,安装 opencv-python 和 numpy。

pip install opencv-python numpy
python awb_perfect_reflector.py

验证方法:

  1. 准备一张有明显色偏的图像(如室内白炽灯下拍摄、偏黄或偏蓝),命名为 input.jpg 放在脚本同目录;
  2. 运行脚本,观察终端输出的三通道增益值——若图像偏黄(R通道过强),则 gain_r 应小于1,gain_b 应大于1,反之亦然;
  3. 打开 output_awb.jpg,检查白色物体(如白墙、白纸)是否恢复为中性白,整体色偏是否明显消除;
  4. 若图像中不存在白色或高亮物体,算法效果会受限,这是完美反射算法的固有假设,属正常现象。

预期输出示例(仅作逻辑演示,非实测值):对于一张偏黄的图像,可能输出 增益 R=0.82, G=0.95, B=1.18,校正后高亮区域RGB趋于接近。

常见问题

  • 校正后过曝:若图像本身过亮,增益放大后高光细节丢失。可适当降低 percentile(如98.0)使参考像素更少、增益更温和。
  • 无白色物体时效果差:算法依赖“最亮像素为白色”的假设,若场景中最亮区域是彩色物体(如红色灯光),校正会产生错误色偏。此时需改用灰度世界或其他算法。