3. AWB进阶

AWB进阶:动态阈值算法 学习卡片

任务目标

在自动白平衡(AWB)处理中,经典灰度世界法假设场景平均色为灰色,但遇到大面积单色物体(如蓝天、绿草)时会产生严重色偏。本案例实现基于YUV色彩空间的动态阈值白平衡算法,通过自适应统计YUV空间中像素分布,动态筛选参考白点,从而在复杂场景下获得比固定阈值法更稳健的白平衡校正效果。

算法原理

动态阈值法核心思想:将RGB图像转换到YUV空间,利用U、V色度分量的统计特性动态确定白点判定阈值,而非使用固定常数。算法先计算U、V分量的均值与偏差,再以均值为中心、以偏差的加权值为半径划定动态范围,仅将落入该范围且亮度足够的像素视为参考白点,最后用这些白点的平均RGB值校正整幅图像。

核心代码

import numpy as np
import cv2

def dynamic_threshold_awb(img):
    """
    基于YUV空间的动态阈值白平衡
    img: BGR图像, uint8, 0-255
    返回: 校正后的BGR图像
    """
    # 转换到YUV
    img_yuv = cv2.cvtColor(img, cv2.COLOR_BGR2YUV).astype(np.float32)
    Y, U, V = cv2.split(img_yuv)

    # 动态阈值参数
    T_Y = 0.85 * 255      # 亮度下限(排除过暗像素)
    T_U = 0.25 * 255      # 色度偏差缩放系数
    T_V = 0.25 * 255

    # 计算U、V的均值与平均偏差
    mean_U = np.mean(U)
    mean_V = np.mean(V)
    mad_U = np.mean(np.abs(U - mean_U))
    mad_V = np.mean(np.abs(V - mean_V))

    # 动态判定阈值(以均值为中心,偏差加权为半径)
    lower_U = mean_U - T_U * mad_U
    upper_U = mean_U + T_U * mad_U
    lower_V = mean_V - T_V * mad_V
    upper_V = mean_V + T_V * mad_V

    # 构建白点掩码:亮度足够 + 色度在动态范围内
    mask = (Y > T_Y) & (U > lower_U) & (U < upper_U) & \
           (V > lower_V) & (V < upper_V)

    # 若白点过少,回退到全图均值(防止除零)
    if np.sum(mask) < 10:
        mask = np.ones_like(mask, dtype=bool)

    # 提取白点对应的BGR像素
    bgr_white = img[mask]
    mean_b = np.mean(bgr_white[:, 0])
    mean_g = np.mean(bgr_white[:, 1])
    mean_r = np.mean(bgr_white[:, 2])

    # 以G通道为基准计算增益并校正
    gain_b = mean_g / (mean_b + 1e-6)
    gain_r = mean_g / (mean_r + 1e-6)

    result = img.astype(np.float32)
    result[:, :, 0] *= gain_b
    result[:, :, 2] *= gain_r

    # 饱和截断
    result = np.clip(result, 0, 255).astype(np.uint8)
    return result

# 最小调用示例
if __name__ == "__main__":
    # 读取图像(请替换为实际路径)
    img = cv2.imread("test.jpg")
    if img is None:
        print("请提供有效的图像路径")
    else:
        corrected = dynamic_threshold_awb(img)
        # 保存结果
        cv2.imwrite("awb_result.jpg", corrected)
        print("处理完成,结果已保存为 awb_result.jpg")

运行与验证

环境依赖:Python 3.7+,NumPy,OpenCV(pip install numpy opencv-python)。

运行方式:将代码保存为 dynamic_awb.py,与测试图像置于同一目录,执行 python dynamic_awb.py。

验证方法:

  1. 准备两张测试图:一张正常光照下的标准色卡图,一张大面积蓝色天空或绿色草地的场景图。
  2. 运行后观察输出 awb_result.jpg:色卡图中灰色块应呈中性色(R≈G≈B);蓝天场景中天空应恢复为自然的蓝色,地面/建筑等原本偏色的区域色偏应明显减轻。
  3. 定量验证(可选):在图像中选取已知为白色的区域(如白纸),比较校正前后该区域R、G、B均值之差。校正后三者差值应小于校正前,且最大通道差通常不超过15(0-255范围)。

判定通过条件:程序无报错运行完成;输出图像无过曝或欠曝的异常色块;主观视觉上白平衡明显改善,且大面积单色场景未出现灰度世界法常见的整体偏色现象。

动态阈值白点筛选流程(YUV空间) BGR图像 转YUV空间 计算U/V均值 与偏差 动态阈值 筛选白点 提取白点BGR均值 (R_w, G_w, B_w) 计算增益并校正 G_w/B_w, G_w/R_w 白点数 < 10? 回退全图均值

关键说明:动态阈值中的缩放系数 T_U、T_V 取0.25为经验值,实际场景中可在0.1~0.5间调整。亮度下限 T_Y 取0.85×255,用于排除暗部噪声干扰。当检测到的白点像素过少(<10)时,算法自动回退到全图均值计算增益,避免极端场景下的除零或异常放大。