2. 完美反射白平衡算法
任务目标
实现完美反射(Perfect Reflector)白平衡算法:假设图像中最亮的像素区域能够完全反射光源颜色,据此估计场景光源色温,并对整幅图像进行颜色校正,使白色物体在不同光源下呈现为白色。
算法原理
完美反射算法核心步骤:
- 统计图像各通道(R/G/B)的亮度分布,确定每个通道的“最亮参考值”(通常取该通道前1%像素的平均值或最大值);
- 以三个通道的最亮参考值构成光源颜色估计向量;
- 将每个像素的通道值除以对应光源估计值(归一化),使最亮区域映射为白色,完成校正。
完整实现(Python + OpenCV)
import cv2
import numpy as np
def perfect_reflector_awb(img, percentile=99):
"""
完美反射白平衡
:param img: BGR图像,uint8类型
:param percentile: 取前percentile%像素作为最亮参考
:return: 校正后的BGR图像
"""
# 分离通道
b, g, r = cv2.split(img.astype(np.float32))
# 计算各通道的亮度阈值(取前percentile%像素)
def channel_gain(channel):
# 计算通道直方图
hist = cv2.calcHist([channel], [0], None, [256], [0, 256]).flatten()
total = img.shape[0] * img.shape[1]
cumsum = np.cumsum(hist)
# 找到累计像素数达到 total * percentile/100 的灰度值
threshold = np.searchsorted(cumsum, total * percentile / 100.0)
# 取该阈值以上像素的平均值作为光源估计
mask = channel >= threshold
if np.sum(mask) == 0:
return 255.0
return np.mean(channel[mask])
b_ref = channel_gain(b)
g_ref = channel_gain(g)
r_ref = channel_gain(r)
# 计算增益(以G通道为基准,防止整体亮度偏移)
max_ref = max(b_ref, g_ref, r_ref)
b_gain = max_ref / b_ref if b_ref > 0 else 1.0
g_gain = max_ref / g_ref if g_ref > 0 else 1.0
r_gain = max_ref / r_ref if r_ref > 0 else 1.0
# 应用增益并裁剪到有效范围
b_corr = np.clip(b * b_gain, 0, 255)
g_corr = np.clip(g * g_gain, 0, 255)
r_corr = np.clip(r * r_gain, 0, 255)
result = cv2.merge([b_corr, g_corr, r_corr]).astype(np.uint8)
return result
# 使用示例
if __name__ == "__main__":
# 读取图像(请替换为实际路径)
img = cv2.imread("input.jpg")
if img is None:
print("图像读取失败,请检查路径")
exit(1)
corrected = perfect_reflector_awb(img)
# 保存结果
cv2.imwrite("output_perfect_reflector.jpg", corrected)
print("校正完成,结果已保存至 output_perfect_reflector.jpg")
运行与验证
环境依赖:Python 3.6+,OpenCV(pip install opencv-python numpy)
运行方式:
python perfect_reflector_awb.py
验证方法:
- 准备一张在偏色光源(如白炽灯/荧光灯)下拍摄的包含白色物体的图像;
- 运行脚本后,观察输出图像中白色物体是否恢复为白色,整体色偏是否消除;
- 定量验证:计算校正前后图像中白色区域的平均RGB值,校正后三通道比值应接近1:1:1(例如R/G≈1.0,B/G≈1.0)。
预期输出示例:若输入图像中白色区域像素值约为(200, 150, 100)(BGR),校正后该区域应接近(200, 200, 200)左右,具体数值取决于光源估计的准确性。
常见问题
- 图像过曝:若图像中存在大面积过曝区域(像素值=255),算法会将过曝区域误判为光源,导致校正失效。建议先检查直方图,避免使用过曝图像。
- 无白色物体:若场景中不存在接近白色的高亮区域,算法估计的光源颜色可能不准确。此时可考虑改用灰度世界算法或结合其他方法。
- 参数调整:
percentile参数控制“最亮”的定义,默认99%表示取前1%最亮像素。若图像噪声较大,可适当降低该值(如95)以增强鲁棒性。