计算机视觉——Opencv(图像平滑处理)

什么是图像平滑处理

图像平滑处理 (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()

运行结果:

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

相关推荐
NAGNIP8 小时前
一文搞懂深度学习中的通用逼近定理!
人工智能·算法·面试
冬奇Lab9 小时前
一天一个开源项目(第36篇):EverMemOS - 跨 LLM 与平台的长时记忆 OS,让 Agent 会记忆更会推理
人工智能·开源·资讯
冬奇Lab9 小时前
OpenClaw 源码深度解析(一):Gateway——为什么需要一个"中枢"
人工智能·开源·源码阅读
AngelPP13 小时前
OpenClaw 架构深度解析:如何把 AI 助手搬到你的个人设备上
人工智能
宅小年13 小时前
Claude Code 换成了Kimi K2.5后,我再也回不去了
人工智能·ai编程·claude
九狼13 小时前
Flutter URL Scheme 跨平台跳转
人工智能·flutter·github
ZFSS13 小时前
Kimi Chat Completion API 申请及使用
前端·人工智能
天翼云开发者社区14 小时前
春节复工福利就位!天翼云息壤2500万Tokens免费送,全品类大模型一键畅玩!
人工智能·算力服务·息壤
知识浅谈14 小时前
教你如何用 Gemini 将课本图片一键转为精美 PPT
人工智能
Ray Liang15 小时前
被低估的量化版模型,小身材也能干大事
人工智能·ai·ai助手·mindx