4. 坏点校正算法(DPC)—— 均值滤波法

坏点校正,说白了就是给传感器“祛痘”。

每个传感器出厂时都带着或多或少的坏点——有的永远亮着(白点),有的永远黑着(黑点),还有的时好时坏(闪点)。如果不处理,拍出来的照片就像长了麻子。今天咱们聊的均值滤波法,是最基础、最直观的校正手段。

4.1 均值滤波法的核心思想

均值滤波的思路很简单:用坏点周围的好像素,取个平均值,把坏点替换掉。

你想想看,如果某个像素明显比周围亮或暗很多,那它大概率是坏的。这时候我们不看它,只看它上下左右四个邻居(或者八个邻居),算个均值填进去。嗯,就是这么朴实无华。

核心公式:

Pnew = (Ptop + Pbottom + Pleft + Pright) / 4

或者用 3×3 邻域:Pnew = (∑Pneighbor) / N

我个人习惯用 3×3 邻域,因为信息量更大,校正后过渡更自然。但要注意——如果坏点刚好在边缘,邻居不够怎么办?后面我会讲边界处理。

4.2 算法流程

均值滤波法校正坏点,一般分三步走:

  1. 坏点检测——判断当前像素是不是坏点
  2. 邻域采样——收集周围好像素的值
  3. 均值替换——用均值覆盖坏点

我在项目中遇到过一种情况:有些坏点其实没那么“坏”,只是稍微偏亮或偏暗。这时候如果直接用均值替换,反而会引入新的伪影。所以检测阈值要设得合理,不能太敏感,也不能太迟钝。

检测方法

最简单的检测方法:比较当前像素与邻域均值的差值。如果差值超过阈值,就判定为坏点。

避坑指南:我曾经把阈值设得太低,结果把正常纹理也当坏点给抹了,画面糊成一片。后来我改成动态阈值——根据局部方差自动调整,效果好了很多。

4.3 优缺点分析

优点 缺点
实现简单,计算量小 会模糊边缘细节
对孤立坏点效果很好 对坏点簇(连续多个坏点)效果差
不需要存储坏点位置表 阈值需要手动调参
适合硬件实现 对纹理区域容易误判

说白了,均值滤波法是个“快刀斩乱麻”的方案。如果你的传感器坏点不多、分布稀疏,它完全够用。但如果坏点成片出现,或者你追求极致画质,那得考虑更高级的算法(比如中值滤波、自适应滤波)。

4.4 Python 代码实现

下面是我写的一个简单实现。注意,这里我用的是 3×3 邻域,边界做了镜像填充。

import numpy as np
import cv2

def mean_dpc(image, threshold=30):
    """
    均值滤波法坏点校正
    :param image: 输入图像 (H, W) 单通道
    :param threshold: 坏点检测阈值
    :return: 校正后的图像
    """
    h, w = image.shape
    # 边界填充(镜像模式)
    padded = np.pad(image, pad_width=1, mode='reflect')
    output = image.copy()

    for i in range(1, h+1):
        for j in range(1, w+1):
            center = padded[i, j]
            # 提取 3x3 邻域(排除中心点)
            neighbors = padded[i-1:i+2, j-1:j+2].flatten()
            neighbors = np.delete(neighbors, 4)  # 去掉中心
            mean_val = np.mean(neighbors)

            # 判断是否为坏点
            if abs(center - mean_val) > threshold:
                output[i-1, j-1] = int(mean_val)

    return output

# 使用示例
raw = cv2.imread('raw_image.png', cv2.IMREAD_GRAYSCALE)
corrected = mean_dpc(raw, threshold=25)
cv2.imwrite('corrected.png', corrected)

注意:这段代码是单通道版本。实际 Bayer 图像有 RGGB 四个通道,需要分别处理。而且不同通道的阈值可能不一样——绿色通道的坏点通常比红蓝通道更敏感。

4.5 效果对比

我拿一张带坏点的测试图跑了一下,效果很明显:

  • 校正前:图像上有明显的白点和黑点,尤其是暗部区域,坏点特别扎眼
  • 校正后:坏点被平滑掉了,画面干净很多。但仔细看边缘,会有一点点模糊

为什么会这样?因为均值滤波不分青红皂白,把坏点和边缘信息一起抹了。这也是它最大的短板。

经验数据:

阈值设置在 20-40 之间比较合理(针对 8bit 图像)。

如果图像噪声大,阈值要适当提高,否则会把噪声当成坏点。

如果坏点特别亮(比如饱和到 255),建议先做饱和检测,再做坏点校正。

4.6 知识结构图

下面这张图总结了均值滤波法 DPC 的核心逻辑:

均值滤波法 DPC 流程 均值滤波法坏点校正流程 输入 Bayer 图像 坏点检测 中心像素 vs 邻域均值,差值 > 阈值? 是坏点? 均值替换 3×3 邻域均值 保留原值 不做处理 输出校正图像 边界处理:镜像填充 阈值:20~40 (8bit)

4.7 小结

均值滤波法 DPC 是入门级的坏点校正方案。它简单、快速、容易上手,适合坏点稀疏的场景。但如果你追求更高的画质,或者传感器坏点比较多,建议结合中值滤波或自适应滤波一起使用。

嗯,这一章就到这里。均值滤波法虽然基础,但理解它的原理和局限,对后面学习更高级的 DPC 算法会很有帮助。