什么是图像平滑处理
图像平滑处理 (Image Smoothing)是一种核心的预处理技术,也被称为图像模糊处理 ,其本质是抑制图像中的噪声、弱化高频细节(如边缘纹理的毛刺),同时保留图像整体结构与主要特征的过程。
下面是常用的一些滤波器:
1、均值滤波(Blur)
2、方框滤波(BoxFilter)
3、高斯滤波(GaussianBlur)
4、中值滤波(MedianBlur)
给图片添加椒盐噪声
准备一个含有噪声点的图像来方便后面的演示,所以我们先来学习给图片添加椒盐噪声
椒盐噪声又称脉冲噪声,是一种常见的图像噪声类型,其本质是图像像素值被随机替换为最大值(255,白色,盐噪声)或最小值(0,黑色,椒噪声)。这种噪声模拟了图像传输、采集过程中产生的信号干扰,会严重破坏图像的视觉连续性。
代码如下:
python
import cv2
import numpy as np
def add_peppersalt_noise(image, n=10000):#n: 噪声点的数量,默认值为10000
result = image.copy() # 复制原始图像,避免直接修改原图
h, w = image.shape[:2]#获取图片的高和宽
for i in range(n):#生成n个椒盐噪声
x = np.random.randint(0, h)
y = np.random.randint(0, w)
if np.random.randint(0,2) == 0:
result[x, y] = 0
else:
result[x,y] = 255
return result
image = cv2.imread(r"C:\Users\LEGION\Desktop\OIP-C.webp",)
cv2.imshow('yntu',image)
cv2.waitKey(0)
noise = add_peppersalt_noise(image)
cv2.imshow('noise',noise)
cv2.waitKey(0)
运行结果:

图像平滑处理
图像平滑处理的本质是通过卷积运算,用邻域像素的统计特征(均值、中值、高斯加权值等)替换当前像素值,从而削弱噪声的影响。以下介绍四种常用的平滑算法:
1、均值滤波(Blur)
均值滤波是最基础的平滑算法,核心逻辑是用卷积核内所有像素的平均值替换中心像素值
代码如下:
python
# 3x3卷积核均值滤波(轻度平滑)
blur_1 = cv2.blur(noise, (3,3))
cv2.imshow( 'blur_1',blur_1)
cv2.waitKey(0)
# 63x63卷积核均值滤波(重度模糊)
blur_2 = cv2.blur(noise,(63,63))
cv2.imshow( 'blur_2',blur_2)
cv2.waitKey(0)
均值滤波能模糊噪声点,但会同时模糊图像的边缘和细节
卷积核越大,模糊效果越明显
对椒盐噪声的去除效果较差 ,因为黑白噪声点会拉高 / 拉低邻域均值,导致噪声扩散。
运行结果:

2、方框滤波(BoxFilter)
方框滤波是均值滤波的变种,通过normalize参数控制是否归一化:
-
normalize=True:等价于均值滤波; -
normalize=False:直接求和,像素值易溢出(超过 255),表现为大面积白色。
代码如下:
python
# 归一化方框滤波(等价于均值滤波)
boxFilter_1 = cv2.boxFilter(noise,-1, (3,3),normalize = True)
cv2.imshow('boxFilter_1',boxFilter_1)
cv2.waitKey(0)
# 非归一化方框滤波
boxFilter_2 = cv2.boxFilter(noise,-1,(3,3),normalize = False)
cv2.imshow('boxFilter_2',boxFilter_2)
cv2.waitKey(0)
仅归一化模式有实际应用价值,非归一化模式因像素值溢出几乎无实用场景
整体效果与均值滤波一致,无法有效去除椒盐噪声。
运行结果:

3、高斯滤波(GaussianBlur)
高斯滤波是一种加权均值滤波,核心是对邻域像素按高斯分布(正态分布)赋予权重,中心像素权重最高,越远权重越低
代码如下:
python
#3x3卷积核,标准差1的高斯滤波
GaussianB = cv2.GaussianBlur(noise,(3,3),1) #标准正太分布
cv2.imshow('GaussianBlur',GaussianB)
cv2.waitKey(0)
高斯滤波能较好保留图像边缘细节,对高斯噪声去除效果优异
对椒盐噪声的处理效果仍不理想 ,因为椒盐噪声的极值像素会影响加权均值,无法完全消除。
运行结果:

4、中值滤波(MedianBlur)
中值滤波是一种非线性滤波,核心逻辑是用卷积核内像素值的中值替换中心像素值。
由于椒盐噪声的像素值为 0 或 255(极值),在排序后会被排除在中值之外,因此对椒盐噪声有特效。
代码如下:
python
# 3x3卷积核中值滤波
medianB = cv2.medianBlur(noise, 3)
cv2.imshow( 'medianBlur',medianB)
cv2.waitKey(0)
cv2.destroyAllWindows()
中值滤波能在去除椒盐噪声的同时,最大程度保留图像的边缘和细节,是处理椒盐噪声的最优选择。
运行结果:

5、算法效果对比与选型建议
| 算法类型 | 核心原理 | 椒盐噪声去除效果 | 细节保留效果 | 适用场景 |
|---|---|---|---|---|
| 均值滤波 | 邻域均值替换 | 差 | 差 | 无噪声场景的轻度模糊 |
| 方框滤波 | 邻域求和 / 均值替换 | 差 | 差 | 同均值滤波 |
| 高斯滤波 | 高斯加权均值替换 | 中 | 优 | 高斯噪声去除、图像模糊平滑 |
| 中值滤波 | 邻域中值替换 | 优 | 良 | 椒盐噪声去除(首选) |
给视频添加椒盐噪声
视频本质是连续的帧序列,为保证每帧噪声分布的随机性且不破坏原视频帧,需要对噪声生成函数做优化:限制噪声点数量不超过图像总像素(避免低分辨率视频报错),并将盐、椒噪声数量均分,保证噪声分布均衡
代码如下:
python
def add_10000_salt_pepper_noise(image):
"""
给单帧图像添加固定10000个黑白椒盐噪声点
:param image: 输入BGR格式单帧图像(OpenCV默认读取格式)
:return: 添加椒盐噪声后的图像(不修改原图像)
"""
# 复制原图像,避免破坏原帧数据,保证原视频展示纯净性
noisy_image = np.copy(image)
height, width = noisy_image.shape[:2]
total_pixel_count = height * width
# 限制噪声点数量不超过图像总像素,防止分辨率过低时报错
noise_count = min(10000, total_pixel_count)
# 生成盐噪声(白色点,BGR=(255,255,255)):约5000个
salt_num = noise_count // 2
salt_y = np.random.randint(0, height, salt_num)
salt_x = np.random.randint(0, width, salt_num)
noisy_image[salt_y, salt_x] = (255, 255, 255)
# 生成椒噪声(黑色点,BGR=(0,0,0)):剩余约5000个,总计10000个
pepper_num = noise_count - salt_num
pepper_y = np.random.randint(0, height, pepper_num)
pepper_x = np.random.randint(0, width, pepper_num)
noisy_image[pepper_y, pepper_x] = (0, 0, 0)
return noisy_image
视频的平滑处理
python
def video_processing_pipeline(video_path=r"E:\xwechat_files\wxid_qi43v1w2nqcb12_e432\msg\file\2026-01\test.avi"):
"""
视频处理主流程:读取帧→加噪声→去噪→多窗口展示
"""
# 1. 打开视频文件
video_capture = cv2.VideoCapture(video_path)
if not video_capture.isOpened():
raise Exception("无法打开视频文件!请确认test.avi存在于当前目录,且格式有效。")
# 2. 循环处理每一帧视频
while True:
# 读取单帧图像
ret, original_frame = video_capture.read()
# 读取失败(视频结束或帧损坏),退出循环
if not ret:
break
# 3. 给当前帧添加10000个椒盐噪声点
noisy_frame = add_10000_salt_pepper_noise(original_frame)
# 4. 选择最优平滑方法:中值滤波(针对椒盐噪声,兼顾去噪与清晰度)
# 5x5滤波核为去噪效果与画面细节的最优平衡
smoothed_frame = cv2.medianBlur(noisy_frame, ksize=5)
# 5. 创建并配置三个可调整大小的展示窗口
cv2.namedWindow("原视频", cv2.WINDOW_NORMAL)
cv2.namedWindow("含10000个椒盐噪声的视频", cv2.WINDOW_NORMAL)
cv2.namedWindow("平滑处理后视频", cv2.WINDOW_NORMAL)
# 6. 同步展示三类视频帧
cv2.imshow("原视频", original_frame)
cv2.imshow("含10000个椒盐噪声的视频", noisy_frame)
cv2.imshow("平滑处理后视频", smoothed_frame)
# 7. 按键控制:按'q'键退出播放,每帧延迟30ms适配常规视频帧率
if cv2.waitKey(30) & 0xFF == ord('q'):
break
# 8. 释放所有资源,避免内存泄露
video_capture.release()
cv2.destroyAllWindows()
# 主程序入口
if __name__ == "__main__":
video_processing_pipeline()
运行结果:

从左到右依次为原视频,添加噪声的视频,平滑处理后的视频