3、空间域滤波去噪:均值滤波、中径滤波、高斯滤波原理与Python实现
各位同学,今天我们来聊聊遥感图像去噪里最基础、也最实用的三个滤波器。说实话,我刚开始做遥感图像处理那会儿,拿到一张满是椒盐噪声的卫星图,第一反应就是直接上均值滤波。结果呢?噪声是淡了,但地物边缘也糊成了一片。后来才明白——滤波这事儿,没有银弹,只有对症下药。
核心观点:空间域滤波的本质,就是用邻域像素的某种统计值来替换中心像素值。你选什么统计方式,就决定了滤波器的性格。
3.1 均值滤波:简单但代价明显
均值滤波的原理,说白了就是取一个窗口(比如3×3),把窗口内所有像素的灰度值加起来求平均,然后用这个平均值去替换窗口中心的像素值。
数学表达:
g(x,y) = (1/(m×n)) × Σ f(i,j) 其中(i,j)属于窗口W
我在项目中遇到过一件事:处理某地区的Landsat影像时,用3×3均值滤波去噪,结果把一条很细的公路给滤没了。为什么?因为公路在影像上只有1-2个像素宽,均值滤波一平均,它就和周围农田混在一起了。
避坑指南:我曾经用5×5均值滤波处理高分辨率遥感影像,结果建筑物边缘全部模糊,后续的建筑物提取完全没法用。均值滤波的窗口越大,模糊越严重,这是它的硬伤。
Python实现:
import cv2
import numpy as np
# 读取遥感图像
img = cv2.imread('remote_sensing.tif', 0) # 灰度图
# 均值滤波
mean_blur = cv2.blur(img, (3, 3)) # 3×3窗口
mean_blur_5 = cv2.blur(img, (5, 5)) # 5×5窗口
# 或者用卷积核手动实现
kernel = np.ones((3,3), np.float32) / 9
mean_manual = cv2.filter2D(img, -1, kernel)
3.2 中值滤波:椒盐噪声的克星
中值滤波的思路完全不同——它不取平均,而是取窗口内所有像素的中位数。你想想看,如果窗口里有个像素值是255(亮点噪声),其他都是正常值,中位数大概率还是正常值,噪声就被剔除了。
我个人习惯在处理椒盐噪声时首选3×3中值滤波。为什么?因为椒盐噪声是孤立的亮点或暗点,中值滤波天然对这类噪声免疫。
经验之谈:我在处理某次台风前后的SAR影像时,图像上全是斑点噪声(类似椒盐噪声),均值滤波效果很差,但中值滤波一次就干净了。记住:中值滤波保边缘、去椒盐,但计算量比均值滤波大。
Python实现:
# 中值滤波
median_blur = cv2.medianBlur(img, 3) # 3×3窗口
median_blur_5 = cv2.medianBlur(img, 5) # 5×5窗口
# 手动实现中值滤波(理解原理)
def median_filter(img, kernel_size=3):
pad = kernel_size // 2
padded = cv2.copyMakeBorder(img, pad, pad, pad, pad, cv2.BORDER_REFLECT)
result = np.zeros_like(img)
for i in range(img.shape[0]):
for j in range(img.shape[1]):
window = padded[i:i+kernel_size, j:j+kernel_size]
result[i,j] = np.median(window)
return result
3.3 高斯滤波:更自然的平滑
高斯滤波和均值滤波有点像,但它不是简单平均,而是加权平均——离中心像素越近的像素,权重越大。这个权重由高斯函数决定。
高斯核公式:
G(x,y) = (1/(2πσ²)) × exp(-(x²+y²)/(2σ²))
σ(sigma)控制了权重的分布。σ越大,中心像素的权重越小,平滑效果越强。我建议你记住:σ=0.8到1.2之间,是遥感图像去噪的黄金区间。
为什么用高斯滤波?因为自然图像(包括遥感影像)中的噪声往往服从高斯分布,用高斯滤波去噪,理论上是最匹配的。而且它比均值滤波更保边缘——虽然还是会模糊,但没那么生硬。
Python实现:
# 高斯滤波
gaussian_blur = cv2.GaussianBlur(img, (3, 3), sigmaX=1.0) # σ=1.0
gaussian_blur_2 = cv2.GaussianBlur(img, (5, 5), sigmaX=1.5) # 更大窗口
# 手动生成高斯核
def gaussian_kernel(size=3, sigma=1.0):
kernel = np.zeros((size, size))
center = size // 2
for i in range(size):
for j in range(size):
x, y = i - center, j - center
kernel[i,j] = np.exp(-(x**2 + y**2) / (2 * sigma**2))
kernel /= kernel.sum() # 归一化
return kernel
kernel_3x3 = gaussian_kernel(3, sigma=1.0)
gaussian_manual = cv2.filter2D(img, -1, kernel_3x3)
3.4 三种滤波器的对比与选择
| 滤波器 | 原理 | 适用噪声 | 保边缘能力 | 计算速度 |
|---|---|---|---|---|
| 均值滤波 | 邻域平均 | 高斯噪声 | 差 | 快 |
| 中值滤波 | 邻域中位数 | 椒盐噪声 | 好 | 中等 |
| 高斯滤波 | 加权平均 | 高斯噪声 | 中等 | 快 |
嗯,这里要注意:没有哪个滤波器是万能的。我在实际项目中,经常是先用中值滤波去椒盐噪声,再用高斯滤波做一次平滑。两步走,效果比单用任何一个都好。
我的建议:拿到一张遥感影像,先看噪声类型。如果是黑白点(椒盐),用中值滤波;如果是整体灰蒙蒙(高斯噪声),用高斯滤波;如果只是随便看看,均值滤波也能凑合——但别指望它保边缘。
3.5 本章知识体系
下面这张图,是我自己总结的三种滤波器的核心逻辑。你看一眼,就能明白它们之间的区别和联系。
最后说一句:滤波器的选择,取决于你的后续任务。如果要做地物分类,保边缘比去噪更重要,那就优先选中值滤波或高斯滤波。如果只是做可视化,均值滤波也能用——但别用太大窗口,3×3就够了。
一句话总结:均值滤波求平均,中值滤波取中位,高斯滤波加权平均。三种方法,三种性格,选对了,事半功倍。