3. 镜头阴影校正
任务目标
镜头阴影校正(Lens Shading Correction, LSC)用于补偿镜头光学系统导致的边缘光强衰减(即渐晕效应)。本案例实现一个最小可复现的LSC算法:读取一张含渐晕的RAW图像,基于径向增益模型计算每个像素的校正增益,输出亮度均匀的校正后图像,并给出可量化的验证指标。
实现原理
镜头阴影通常近似为径向对称的衰减,距离图像中心越远,光强衰减越严重。校正增益与像素到中心的归一化距离r满足:
gain(r) = 1 + k1·r² + k2·r⁴
其中k1、k2为镜头阴影系数(本案例提供一组典型值,实际使用时需通过标定获得)。校正后像素值 = 原始像素值 × gain(r),并做饱和截断。
环境依赖
仅需Python 3.8+,以及NumPy和OpenCV(用于图像读写)。安装命令:
pip install numpy opencv-python
关键完整代码
import numpy as np
import cv2
def generate_lens_shading_image(width=640, height=480, k1=0.35, k2=0.15):
"""生成模拟含镜头阴影的灰度图像(用于演示校正效果)"""
y, x = np.mgrid[0:height, 0:width].astype(np.float32)
cx, cy = (width - 1) / 2.0, (height - 1) / 2.0
r2 = ((x - cx) ** 2 + (y - cy) ** 2) / (cx ** 2 + cy ** 2)
attenuation = 1.0 / (1 + k1 * r2 + k2 * r2 ** 2)
flat_image = np.full((height, width), 128.0, dtype=np.float32)
shaded = flat_image * attenuation
return np.clip(shaded, 0, 255).astype(np.uint8), cx, cy
def lens_shading_correction(img, k1=0.35, k2=0.15):
"""对输入灰度图执行镜头阴影校正"""
h, w = img.shape
y, x = np.mgrid[0:h, 0:w].astype(np.float32)
cx, cy = (w - 1) / 2.0, (h - 1) / 2.0
r2 = ((x - cx) ** 2 + (y - cy) ** 2) / (cx ** 2 + cy ** 2)
gain = 1.0 + k1 * r2 + k2 * r2 ** 2
corrected = img.astype(np.float32) * gain
return np.clip(corrected, 0, 255).astype(np.uint8)
def compute_uniformity(img):
"""计算图像均匀性:中心区域均值 / 四角区域均值(越接近1越均匀)"""
h, w = img.shape
center = img[h//4:3*h//4, w//4:3*w//4].mean()
corners = np.mean([
img[0:h//8, 0:w//8].mean(),
img[0:h//8, 7*w//8:].mean(),
img[7*h//8:, 0:w//8].mean(),
img[7*h//8:, 7*w//8:].mean()
])
return center / corners if corners > 0 else float('inf')
if __name__ == "__main__":
# 生成模拟渐晕图像
shaded_img, cx, cy = generate_lens_shading_image()
cv2.imwrite("shaded_input.png", shaded_img)
# 执行校正
corrected_img = lens_shading_correction(shaded_img)
# 保存结果
cv2.imwrite("corrected_output.png", corrected_img)
# 验证:比较校正前后的均匀性
before = compute_uniformity(shaded_img)
after = compute_uniformity(corrected_img)
print(f"校正前中心/四角亮度比: {before:.3f}")
print(f"校正后中心/四角亮度比: {after:.3f}")
print("通过条件: 校正后比值应接近1.0(建议在0.95~1.05范围内)")
运行与验证
- 将上述代码保存为
lsc_demo.py,在终端运行:
python lsc_demo.py
- 程序会生成两张图片:
shaded_input.png(模拟渐晕输入)和corrected_output.png(校正结果)。 - 判定通过的标准:
- 终端输出的校正后中心/四角亮度比应接近1.0(例如0.95~1.05),明显优于校正前的比值(本组参数下校正前约1.6~1.7)。
- 目视检查
corrected_output.png,图像中心与边缘亮度应基本一致,无明显暗角。
关键说明
- 本案例使用
k1=0.35, k2=0.15模拟典型渐晕强度。实际ISP中,这些系数通过镜头标定获得,不同镜头参数不同。 - 代码中的
generate_lens_shading_image仅用于生成测试输入,验证算法正确性;实际应用时直接对相机RAW图调用lens_shading_correction即可。 - 增益计算使用归一化半径的平方
r²,避免开方运算,降低计算开销,适合硬件实现。 - 对于彩色图像,需对R、G、B三个通道分别执行相同校正(各通道系数可能不同),本案例以灰度图演示核心算法。