Bootstrap

LSC(镜头阴影矫正)——每日挑战第二天

LSC(Lens Shading Correction)是ISP算法中的一个重要组成部分,用于校正镜头遮挡(lens shading)现象。镜头遮挡是由于镜头和图像传感器的光学特性导致的图像亮度不均匀的现象。通常,图像的中心部分较亮,而边缘部分较暗。LSC算法的目标是通过校正这种亮度不均匀,使得图像在整个视场中具有相同的亮度水平。

网格矫正法的基本步骤:

  1. 图像划分:将原始图像划分为多个小的网格区域。每个网格的大小由用户指定,这样可以根据具体需求调整网格的密度。
  2. 计算网格均值:对每个网格区域的像素值进行平均计算,得到每个网格的平均亮度值。
  3. 计算增益矩阵:选取某个基准网格(通常是中心网格)的平均亮度值,计算其他网格相对于基准网格的亮度增益值。
  4. 插值计算:对于网格之间的像素点,使用插值法计算其增益值,以保证校正后的图像平滑过渡。
  5. 应用增益:将计算得到的增益矩阵应用于原始图像,对每个像素的亮度进行调整,得到光照均衡校正后的图像。

通过以上步骤,网格矫正法能够有效地校正图像的光照不均匀性,提高图像的整体质量。接下来,我们将通过 Python 代码演示如何实现这一方法。

import cv2
import numpy as np
import matplotlib.pyplot as plt


def calculate_lsc_gain(image, side_num):
    height, width, _ = image.shape
    side_y = height // side_num
    side_x = width // side_num

    # Separate color channels
    image_r = image[:, :, 0]
    image_g = image[:, :, 1]
    image_b = image[:, :, 2]

    # Initialize matrices to store block means
    image_point_r = np.zeros((side_num + 1, side_num + 1))
    image_point_g = np.zeros((side_num + 1, side_num + 1))
    image_point_b = np.zeros((side_num + 1, side_num + 1))

    # Calculate block means
    for i in range(side_num + 1):
        for j in range(side_num + 1):
            x_start = max(0, j * side_x - side_x // 2)
            x_end = min(width, j * side_x + side_x // 2)
            y_start = max(0, i * side_y - side_y // 2)
            y_end = min(height, i * side_y + side_y // 2)

            data_r = image_r[y_start:y_end, x_start:x_end]
            data_g = image_g[y_start:y_end, x_start:x_end]
            data_b = image_b[y_start:y_end, x_start:x_end]

            image_point_r[i, j] = np.mean(data_r)
            image_point_g[i, j] = np.mean(data_g)
            image_point_b[i, j] = np.mean(data_b)

    # Initialize gain matrices
    rGain = np.zeros((side_num + 1, side_num + 1))
    gGain = np.zeros((side_num + 1, side_num + 1))
    bGain = np.zeros((side_num + 1, side_num + 1))

    # Calculate LSC gain
    center_i = side_num // 2
    center_j = side_num // 2
    for i in range(side_num + 1):
        for j in range(side_num + 1):
            rGain[i, j] = image_point_r[center_i, center_j] / image_point_r[i, j]
            gGain[i, j] = image_point_g[center_i, center_j] / image_point_g[i, j]
            bGain[i, j] = image_point_b[center_i, center_j] / image_point_b[i, j]

    return rGain, gGain, bGain


def apply_lsc_correction(image, rGain, gGain, bGain, side_num):
    height, width, _ = image.shape
    side_y = height // side_num
    side_x = width // side_num

    corrected_image = np.zeros_like(image, dtype=np.float32)

    for i in range(height):
        for j in range(width):
            gainStepX = min(side_num - 1, i // side_y)
            gainStepY = min(side_num - 1, j // side_x)

            # Bilinear interpolation
            rGainTmp = (rGain[gainStepX + 1, gainStepY] - rGain[gainStepX, gainStepY]) * (i % side_y) / side_y + \
                       (rGain[gainStepX, gainStepY + 1] - rGain[gainStepX, gainStepY]) * (j % side_x) / side_x + \
                       (rGain[gainStepX + 1, gainStepY + 1] + rGain[gainStepX, gainStepY] - rGain[
                           gainStepX + 1, gainStepY] - rGain[gainStepX, gainStepY + 1]) * \
                       (i % side_y) / side_y * (j % side_x) / side_x + rGain[gainStepX, gainStepY]

            gGainTmp = (gGain[gainStepX + 1, gainStepY] - gGain[gainStepX, gainStepY]) * (i % side_y) / side_y + \
                       (gGain[gainStepX, gainStepY + 1] - gGain[gainStepX, gainStepY]) * (j % side_x) / side_x + \
                       (gGain[gainStepX + 1, gainStepY + 1] + gGain[gainStepX, gainStepY] - gGain[
                           gainStepX + 1, gainStepY] - gGain[gainStepX, gainStepY + 1]) * \
                       (i % side_y) / side_y * (j % side_x) / side_x + gGain[gainStepX, gainStepY]

            bGainTmp = (bGain[gainStepX + 1, gainStepY] - bGain[gainStepX, gainStepY]) * (i % side_y) / side_y + \
                       (bGain[gainStepX, gainStepY + 1] - bGain[gainStepX, gainStepY]) * (j % side_x) / side_x + \
                       (bGain[gainStepX + 1, gainStepY + 1] + bGain[gainStepX, gainStepY] - bGain[
                           gainStepX + 1, gainStepY] - bGain[gainStepX, gainStepY + 1]) * \
                       (i % side_y) / side_y * (j % side_x) / side_x + bGain[gainStepX, gainStepY]

            corrected_image[i, j, 0] = image[i, j, 0] * rGainTmp
            corrected_image[i, j, 1] = image[i, j, 1] * gGainTmp
            corrected_image[i, j, 2] = image[i, j, 2] * bGainTmp

    return np.clip(corrected_image, 0, 255).astype(np.uint8)


if __name__ == "__main__":
    filePath = '../images/LSC.png'
    side_num = 16
    meshON = True

    # Load image
    image = cv2.imread(filePath)

    # Calculate LSC gain
    rGain, gGain, bGain = calculate_lsc_gain(image, side_num)

    # Apply LSC correction
    corrected_image = apply_lsc_correction(image, rGain, gGain, bGain, side_num)

    # Display images
    plt.figure(figsize=(12, 6))
    plt.subplot(121)
    plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
    plt.title('Original Image')

    plt.subplot(122)
    plt.imshow(cv2.cvtColor(corrected_image, cv2.COLOR_BGR2RGB))
    plt.title('Corrected Image')
    plt.show()

原文链接:https://blog.csdn.net/wtzhu_13/article/details/118460646?spm=1001.2014.3001.5502

;