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范围内)")

运行与验证

  1. 将上述代码保存为lsc_demo.py,在终端运行:
python lsc_demo.py
  1. 程序会生成两张图片:shaded_input.png(模拟渐晕输入)和corrected_output.png(校正结果)。
  2. 判定通过的标准:
  • 终端输出的校正后中心/四角亮度比应接近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三个通道分别执行相同校正(各通道系数可能不同),本案例以灰度图演示核心算法。