4. 坏点校正

任务目标

传感器制造缺陷或老化会导致个别像素点输出异常(过亮、过暗或恒定值),即坏点(Dead Pixel)。本案例实现一个最小可复现的坏点校正模块:检测图像中的孤立坏点,并使用邻域中值滤波进行校正,同时保证正常像素不受影响。

核心思路

坏点检测基于邻域统计:若中心像素值与周围8邻域的中值偏差超过设定阈值,则判定为坏点。校正时直接用该邻域中值替换坏点值。该方案对稀疏坏点(占像素总数<0.1%)有效,适用于RAW域或灰度图像。

完整实现

import numpy as np

def dead_pixel_correction(image, threshold=40):
    """
    坏点检测与校正(灰度图,单通道)
    :param image: 2D numpy数组,uint8或uint16
    :param threshold: 像素值与邻域中值的差超过该值则判为坏点
    :return: 校正后图像, 坏点掩码(True表示坏点)
    """
    img = image.astype(np.int32)
    h, w = img.shape
    padded = np.pad(img, 1, mode='reflect')
    corrected = img.copy()
    bad_mask = np.zeros((h, w), dtype=bool)

    for i in range(h):
        for j in range(w):
            # 提取3x3邻域(含中心)
            neighborhood = padded[i:i+3, j:j+3].flatten()
            center_val = img[i, j]
            median_val = np.median(neighborhood)

            # 检测:中心与邻域中值差异过大
            if abs(center_val - median_val) > threshold:
                bad_mask[i, j] = True
                # 校正:用排除中心后的邻域中值替换
                neighbors = neighborhood[neighborhood != center_val]
                corrected[i, j] = np.median(neighbors) if len(neighbors) > 0 else median_val

    return corrected.astype(image.dtype), bad_mask

if __name__ == "__main__":
    # 构造测试图:8x8灰度图,含3个坏点
    test_img = np.array([
        [50, 52, 48, 51, 49, 50, 53, 51],
        [51, 200, 50, 49, 52, 48, 50, 52],   # (1,1)亮点坏点
        [49, 50, 51, 48, 50, 51, 49, 50],
        [50, 48, 52, 51, 49, 50, 48, 51],
        [52, 50, 49, 50, 0, 51, 52, 50],     # (4,4)暗点坏点
        [48, 51, 50, 52, 50, 49, 51, 48],
        [50, 49, 51, 48, 52, 50, 49, 52],
        [51, 50, 48, 51, 49, 52, 50, 255]    # (7,7)亮点坏点
    ], dtype=np.uint8)

    corrected_img, mask = dead_pixel_correction(test_img, threshold=40)

    print("检测到坏点坐标:", np.argwhere(mask).tolist())
    print("校正后坏点位置像素值:", corrected_img[mask])
    print("校正后完整图像:\n", corrected_img)

运行与验证

运行方式:直接执行脚本(需安装NumPy):

pip install numpy
python dead_pixel_correction.py

预期输出:检测到3个坏点,坐标分别为(1,1)、(4,4)、(7,7)。校正后这三个位置的像素值应接近周围邻域正常水平(约50±3),而非原始异常值(200、0、255)。

通过判定标准:

  1. 坏点掩码准确识别全部3个注入坏点,且无误检(正常像素未被标记);
  2. 校正后坏点处像素值落入邻域正常范围(48~53),图像整体无明显异常突变;
  3. 正常像素值保持不变(校正前后完全一致)。

关键说明

  • 阈值threshold需根据传感器噪声水平调整:暗光下噪声增大时适当提高阈值(如60~80),防止将噪声误判为坏点。
  • 本实现针对稀疏孤立坏点设计。若存在坏点簇(2×2以上连续坏点),需扩大邻域范围(如5×5)或改用线性插值,但会显著增加计算量。
  • 实际ISP流水线中,坏点校正通常在RAW域(Bayer格式)进行,需按通道分别处理,并配合坏点表(静态坏点坐标预存)以降低逐帧检测开销。本案例演示动态检测逻辑,可直接迁移至Bayer各通道。