4. 动态阈值AWB算法
任务目标
实现基于动态阈值(Dynamic Threshold)的自动白平衡(AWB)算法。该算法在YCbCr色彩空间中统计图像色度分布,根据亮度自适应地筛选白点候选区域,并利用筛选出的白点估计场景光照色温,最终通过增益校正恢复图像中性色。
算法原理与实现路径
动态阈值AWB的核心在于:并非所有高亮度像素都是白点,而是需要在色度空间中寻找满足特定分布约束的像素集合。本实现采用以下步骤:
- 将RGB图像转换至YCbCr空间,分离亮度与色度信息;
- 对Cb、Cr分量分别计算均值与偏差,形成动态判定阈值;
- 依据亮度范围与色度偏移距离双重条件筛选白点候选;
- 对筛选出的白点求取R、G、B三通道均值,计算各通道增益并校正全图。
完整实现代码
import numpy as np
import cv2
def dynamic_threshold_awb(img):
"""
动态阈值自动白平衡
img: BGR图像, uint8, 0-255
返回: 校正后的BGR图像
"""
# 1. 转换到YCbCr空间
ycrcb = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
Y, Cr, Cb = cv2.split(ycrcb.astype(np.float32))
h, w = Y.shape
# 2. 计算Cb/Cr的均值与偏差
Cb_mean = np.mean(Cb)
Cr_mean = np.mean(Cr)
Cb_abs_dev = np.mean(np.abs(Cb - Cb_mean))
Cr_abs_dev = np.mean(np.abs(Cr - Cr_mean))
# 3. 动态阈值判定条件
# 亮度范围: 避免过暗噪声与过曝区域
Y_min, Y_max = 0.1 * 255, 0.95 * 255
# 色度距离阈值: 均值±偏差的缩放(动态自适应)
scale = 1.5
Cb_low, Cb_high = Cb_mean - scale * Cb_abs_dev, Cb_mean + scale * Cb_abs_dev
Cr_low, Cr_high = Cr_mean - scale * Cr_abs_dev, Cr_mean + scale * Cr_abs_dev
# 4. 构建白点掩膜
mask = ((Y > Y_min) & (Y < Y_max) &
(Cb > Cb_low) & (Cb < Cb_high) &
(Cr > Cr_low) & (Cr < Cr_high))
# 5. 若白点过少(极端色温), 退化为全图均值
if np.sum(mask) < max(10, 0.01 * h * w):
mask = np.ones_like(mask, dtype=bool)
# 6. 计算白点区域的RGB均值
bgr = img.astype(np.float32)
B_mean = np.mean(bgr[:, :, 0][mask])
G_mean = np.mean(bgr[:, :, 1][mask])
R_mean = np.mean(bgr[:, :, 2][mask])
# 7. 计算增益(以G通道为基准)
gain_B = G_mean / (B_mean + 1e-6)
gain_R = G_mean / (R_mean + 1e-6)
# 8. 应用增益并饱和截断
corrected = img.astype(np.float32)
corrected[:, :, 0] *= gain_B
corrected[:, :, 2] *= gain_R
corrected = np.clip(corrected, 0, 255).astype(np.uint8)
return corrected
# 最小调用示例
if __name__ == "__main__":
# 生成模拟偏色图像(纯色块, 便于验证)
img = np.zeros((200, 200, 3), dtype=np.uint8)
img[:, :, 0] = 180 # B偏强(模拟低色温偏蓝场景)
img[:, :, 1] = 120
img[:, :, 2] = 80
result = dynamic_threshold_awb(img)
# 验证: 校正后B/G/R应趋于接近
b_mean = np.mean(result[:, :, 0])
g_mean = np.mean(result[:, :, 1])
r_mean = np.mean(result[:, :, 2])
print(f"校正后均值 B={b_mean:.1f}, G={g_mean:.1f}, R={r_mean:.1f}")
print("通过条件: 三通道均值差异小于15")
运行与验证
环境依赖:Python 3.7+,NumPy,OpenCV(pip install numpy opencv-python)。
运行方式:将上述代码保存为 awb_dynamic.py,执行 python awb_dynamic.py。
验证方法:代码内置了模拟偏色图像的测试。输入图像B通道显著高于R通道(模拟偏蓝场景),算法应通过增益调整使三通道均值收敛。判定通过条件为校正后三通道均值差小于15。对于真实图像,可替换 img 为实际图片路径(cv2.imread),观察校正后中性色区域(如白墙、灰卡)是否恢复为无色偏状态。
关键说明
动态阈值相比固定阈值(如Cb、Cr均在[0,255]内取固定区间)的优势在于:阈值随图像内容自适应变化,对色温跨度大的场景鲁棒性更强。本实现中 scale 参数控制色度筛选的严格程度,值越小白点筛选越严格;当筛选白点过少时自动回退至全图均值,避免极端色温下无白点可用的失效情况。亮度上下限用于排除暗部噪声与高光裁剪区域对色度统计的干扰。