3. 空间域滤波基础:均值滤波、高斯滤波与中值滤波

各位同学,今天我们正式进入去噪算法的核心地带——空间域滤波。说白了,就是直接在图像像素上做文章,用邻域内的像素值来“修复”当前像素。我做了这么多年安防监控,处理过无数个雨夜、雾霾天的监控画面,可以说空间域滤波是咱们这一行的基本功。今天咱们就把均值、高斯、中值这三种最经典的滤波器讲透。

3.1 均值滤波:最简单的平滑方式

均值滤波的原理,说白了就是“平均主义”。用一个窗口(比如3x3)滑过图像,把窗口内所有像素的灰度值加起来求个平均值,然后把这个平均值赋给窗口中心的像素。

数学表达式

g(x,y) = (1/(m*n)) * Σ f(i,j)  其中 (i,j) ∈ 窗口

嗯,这里要注意:窗口越大,平滑效果越强,但图像也会越模糊。我在项目中遇到过这种情况——为了去掉一个老旧摄像头的雪花噪点,把窗口开到7x7,结果人脸轮廓都糊了。后来我学乖了,一般先用3x3试试。

核心特点

  • 计算简单,速度快
  • 对高斯噪声有一定抑制效果
  • 会模糊边缘,细节丢失严重
  • 对椒盐噪声几乎无效

Python实现

import cv2
import numpy as np

def mean_filter(image, kernel_size=3):
    # 直接用OpenCV的blur函数
    result = cv2.blur(image, (kernel_size, kernel_size))
    return result

# 或者自己手写一个
def mean_filter_manual(image, kernel_size=3):
    h, w = image.shape[:2]
    pad = kernel_size // 2
    # 边界填充,我习惯用复制填充
    padded = cv2.copyMakeBorder(image, pad, pad, pad, pad, cv2.BORDER_REPLICATE)
    result = np.zeros_like(image)
    
    for i in range(h):
        for j in range(w):
            # 提取窗口区域
            window = padded[i:i+kernel_size, j:j+kernel_size]
            result[i, j] = np.mean(window)
    return result

我的小技巧:在安防监控中,如果画面噪点比较均匀(比如老旧CCD传感器),均值滤波3x3就够了。千万别贪大,否则监控画面里人的五官都看不清,那就失去监控的意义了。

3.2 高斯滤波:更自然的平滑

高斯滤波和均值滤波最大的区别在于——它不搞“平均主义”,而是根据距离给每个像素分配不同的权重。离中心越近的像素,权重越大;越远的,权重越小。这个权重分布服从高斯函数(也就是正态分布)。

为什么这样更好? 你想想看,自然图像中,相邻像素的相关性本来就高。离得近的像素,颜色和亮度更接近。高斯滤波正好模拟了这种自然规律,所以平滑效果更自然,边缘保留得也更好。

高斯核的计算

G(x,y) = (1/(2πσ²)) * exp(-(x²+y²)/(2σ²))

其中σ(标准差)控制着权重的分布。σ越大,权重分布越平缓,平滑效果越强。我个人习惯在安防监控中,σ取1.0到1.5之间,效果比较适中。

Python实现

def gaussian_filter(image, kernel_size=3, sigma=1.0):
    # OpenCV一行搞定
    result = cv2.GaussianBlur(image, (kernel_size, kernel_size), sigma)
    return result

# 手写高斯核
def create_gaussian_kernel(kernel_size=3, sigma=1.0):
    k = kernel_size // 2
    kernel = np.zeros((kernel_size, kernel_size), dtype=np.float32)
    for x in range(-k, k+1):
        for y in range(-k, k+1):
            kernel[x+k, y+k] = np.exp(-(x**2 + y**2) / (2*sigma**2))
    # 归一化,让所有权重加起来等于1
    kernel /= np.sum(kernel)
    return kernel

我曾经踩过的坑:有一次处理夜间监控画面,噪点特别多,我把σ设到了3.0,结果画面是平滑了,但车牌上的数字全糊成了一片。后来我意识到,高斯滤波的σ不是越大越好,要根据实际噪点水平来调。对于安防监控,我建议σ不要超过2.0。

3.3 中值滤波:椒盐噪声的克星

中值滤波的思路完全不同——它不计算平均值,而是把窗口内的像素值排序,取中间那个值作为结果。这招对付椒盐噪声(就是那种黑白点噪声)特别有效。

为什么中值滤波对椒盐噪声有效? 椒盐噪声的像素值要么是0(黑点),要么是255(白点),都是极端值。取中值的时候,这些极端值会被排到最前面或最后面,根本选不到它。而正常的像素值因为数量多,中值大概率落在正常范围内。

Python实现

def median_filter(image, kernel_size=3):
    # OpenCV直接调用
    result = cv2.medianBlur(image, kernel_size)
    return result

# 手写实现,加深理解
def median_filter_manual(image, kernel_size=3):
    h, w = image.shape[:2]
    pad = kernel_size // 2
    padded = cv2.copyMakeBorder(image, pad, pad, pad, pad, cv2.BORDER_REPLICATE)
    result = np.zeros_like(image)
    
    for i in range(h):
        for j in range(w):
            window = padded[i:i+kernel_size, j:j+kernel_size]
            # 排序取中值
            result[i, j] = np.median(window)
    return result

三种滤波器的对比

滤波器 适用噪声 边缘保留 计算速度 安防场景推荐
均值滤波 高斯噪声(轻度) 老旧传感器、均匀噪点
高斯滤波 高斯噪声(中重度) 中等 中等 低光照、夜间监控
中值滤波 椒盐噪声 较慢 传输干扰、摄像头故障

3.4 本章知识体系

下面这张图总结了三种空间域滤波的核心逻辑,我画出来方便大家对照理解:

空间域滤波知识体系 空间域滤波 均值滤波 高斯滤波 中值滤波 原理:邻域平均 特点:简单快速 缺点:边缘模糊 原理:加权平均 特点:自然平滑 参数:σ控制权重 原理:排序取中 特点:抗椒盐噪声 优点:边缘保留好 选择建议: 均匀噪点用均值 | 自然噪点用高斯 | 椒盐噪点用中值

实战建议:在安防监控项目中,我通常的做法是——先观察噪点类型。如果是雪花点(均匀分布),用高斯滤波;如果是黑白点(椒盐噪声),用中值滤波。如果实在分不清,那就用中值滤波,它最保险,边缘保留也最好。

好了,今天的内容就到这里。这三种滤波器是空间域去噪的基石,大家一定要亲手跑一遍代码,看看不同参数下的效果差异。下一章我们会聊更高级的滤波方法,到时候你们会发现,今天学的这些基础有多重要。


公众号:蓝海资料掘金营,微信deep3321