一,滤波

图像卷积

图像卷积是一种线性运算,核心是通过一个固定大小的 “卷积核” 在图像上滑动,与对应区域的像素进行加权求和,最终生成新图像的过程。

1、核心概念
要理解图像卷积,需先明确两个基本元素:
1) 卷积核(Kernel)
也叫滤波器、模板,是一个小型矩阵(通常为奇数大小,如 3x3、5x5)。
矩阵中的每个数值称为 “权重”,决定了对应位置像素对输出结果的贡献程度。
卷积核的中心称为 “锚点”,是计算后结果像素的对应位置。
2) 图像(Input Image)
可看作一个由像素灰度值组成的二维矩阵,是卷积运算的处理对象。
2、卷积运算步骤
图像卷积的过程可拆解为 4 个关键步骤,以 3x3 卷积核为例:
滑动对齐:将卷积核的锚点与图像的某个像素对齐,使卷积核完全覆盖图像上的一个 3x3 像素区域。
元素相乘:将卷积核的每个权重与图像对应位置的像素值一一相乘。
求和运算:将所有相乘后的结果相加,得到一个总和。
赋值输出:将这个总和作为新图像对应位置(即卷积核锚点对齐的像素位置)的像素值。
重复以上步骤,让卷积核从图像左上角滑动到右下角(遍历所有像素),即可生成完整的卷积后图像。
3、关键特性
线性运算:满足叠加性和齐次性,多个卷积的叠加等价于卷积的叠加,这是均值滤波、高斯滤波等线性滤波的理论基础。
可分离性:部分卷积核(如高斯核)可拆分为水平和垂直两个 1 维核,先做水平卷积再做垂直卷积,能大幅减少计算量。
边缘处理:当卷积核滑动到图像边缘时,会超出图像范围,需通过 “边缘填充”(如补 0、复制边缘像素等)解决,否则输出图像会缩小。

代码实例

#图像卷积
import cv2
import numpy as np

img = cv2.imread('10.jpg')
kernal = np.ones((5,5),np.float32)/25
#卷积后的输出图像
dst = cv2.filter2D(img,-1,kernal)
cv2.imshow('img',img)
cv2.imshow('dst',dst)
cv2.waitKey(0)

输出结果
在这里插入图片描述

均值滤波

核心原理:
用滤波窗口内所有像素的平均值替代中心像素的值,属于线性滤波。
优点:
算法简单,计算速度快,能有效平滑图像、降低噪声。
缺点:
会破坏图像细节,导致边缘模糊,滤波窗口越大,模糊效果越严重。
适用场景:
适用于噪声较少、对图像细节要求不高的场景,或作为初步去噪步骤。

代码实例:

#均值滤波
import cv2
import numpy as np

img = cv2.imread('lena.png')

dst = cv2.blur(img,(5,5),(5,5))

cv2.imshow('img',img)
cv2.imshow('dst',dst)
cv2.waitKey(0)

输出结果:
在这里插入图片描述

代码注释
函数:

cv2.blur(src, ksize, dst=None, anchor=None, borderType=None)

参数说明:
src:输入图像(可以是单通道/多通道)
ksize:滤波窗口大小,格式为(宽, 高),必须是奇数(如(3,3)、(5,5))
anchor:锚点(窗口中心),默认(-1,-1)表示自动设为窗口中心
borderType:边缘填充方式,默认cv2.BORDER_DEFAULT(推荐保持默认)

高斯滤波

核心原理:
基于高斯函数计算滤波窗口内的权重,窗口中心像素权重最大,向边缘逐渐减小,用加权平均值替代中心像素,属于线性滤波。
优点:
相比均值滤波,在去噪的同时能更好地保留图像细节,边缘模糊程度更低。
缺点:
仍会一定程度模糊边缘,无法完全避免细节损失。
适用场景:
应用最广泛的滤波算法,适用于处理高斯噪声,或作为其他图像处理(如边缘检测)的预处理步骤。

代码实例:
由于原图lena.png没有高斯噪音,为对比更明显,所以在原图基础上加了高斯噪音,再进行滤波。

import cv2
import numpy as np

# 读取图像(默认BGR格式)
img = cv2.imread('lena.png')
if img is None:
    raise ValueError("请检查图像路径是否正确!")

# ---------------------- 给图像添加高斯噪声 ----------------------
def add_gaussian_noise(image, mean=0, var=0.001):
    """
    给图像添加高斯噪声
    :param image: 输入图像
    :param mean: 高斯噪声的均值(通常为0)
    :param var: 高斯噪声的方差(控制噪声强度,值越大噪声越明显)
    :return: 带高斯噪声的图像
    """
    # 将图像转为浮点型(避免整数运算溢出)
    image = np.array(image, dtype=np.float32) / 255.0
    # 生成高斯噪声(与图像同尺寸)
    sigma = var ** 0.5  # 标准差=方差开平方
    gauss = np.random.normal(mean, sigma, image.shape)
    # 叠加噪声到图像
    noisy_image = image + gauss
    # 截断到[0,1]范围并转回uint8类型(0-255)
    noisy_image = np.clip(noisy_image, 0, 1)
    noisy_image = np.uint8(noisy_image * 255)
    return noisy_image

# 添加高斯噪声(可调整var参数控制噪声强度)
noisy_img = add_gaussian_noise(img, mean=0, var=0.005)  # var=0.005噪声适中

# ---------------------- 高斯滤波去噪 ----------------------
# 参数:(5,5)为滤波窗口,sigmaX=0表示自动计算标准差
gaussian_dst = cv2.GaussianBlur(noisy_img, (5, 5), 0)

# ---------------------- 显示结果 ----------------------
cv2.imshow('原图', img)
cv2.imshow('加高斯噪声后', noisy_img)
cv2.imshow('高斯滤波后', gaussian_dst)

# 等待按键后关闭窗口
cv2.waitKey(0)
cv2.destroyAllWindows()

输出结果对比;
在这里插入图片描述
代码注释

cv2.GaussianBlur(src, ksize, sigmaX, sigmaY=None, borderType=None)

参数说明:
src:输入图像
ksize:窗口大小(奇数),若为(0,0)则由sigma计算
sigmaX:X方向高斯标准差(控制权重分布,越大越平缓)
sigmaY:Y方向标准差,默认与sigmaX相同;若为0则等于sigmaX
borderType:边缘填充方式(默认即可)

中值滤波

核心原理:
将滤波窗口内所有像素的灰度值排序,用中值替代中心像素的值,属于非线性滤波。
优点:
对椒盐噪声(图像中随机出现的黑白噪点)抑制效果极佳,能有效保留图像边缘和细节,不会产生明显模糊。
缺点:
计算速度比均值滤波慢,对高斯噪声的抑制效果不如高斯滤波;窗口尺寸选择不当可能导致图像失真。
适用场景:
主要用于去除椒盐噪声,或需要保留边缘细节的图像去噪场景。

代码实例:
由于原图lena.png没有椒盐噪声,为对比更明显,所以在原图基础上加了高斯噪音,再进行滤波。


import cv2
import numpy as np

# 读取图像
img = cv2.imread('lena.png')
if img is None:
    raise ValueError("请检查图像路径是否正确!")


# ---------------------- 添加椒盐噪声 ----------------------
def add_salt_pepper_noise(image, prob=0.05):
    """
    给图像添加椒盐噪声
    :param image: 输入图像
    :param prob: 噪声概率(0-1之间,值越大噪声越多)
    :return: 带椒盐噪声的图像
    """
    output = np.copy(image)  # 复制原图,避免修改原图
    # 计算椒盐噪声的像素数量
    thres = 1 - prob  # 非噪声像素的阈值

    # 遍历每个像素(针对彩色图的三通道)
    for i in range(output.shape[0]):
        for j in range(output.shape[1]):
            rdn = np.random.random()  # 生成0-1之间的随机数
            if rdn < prob:
                output[i][j] = 0  # 椒噪声(黑色点)
            elif rdn > thres:
                output[i][j] = 255  # 盐噪声(白色点)
            # 否则保持原图像素值
    return output


# 添加椒盐噪声(prob=0.05表示5%的像素被污染)
noisy_img = add_salt_pepper_noise(img, prob=0.05)

# ---------------------- 中值滤波去噪 ----------------------
# 参数:5表示5x5的滤波窗口(必须是奇数)
median_dst = cv2.medianBlur(noisy_img, 5)

# ---------------------- 显示结果 ----------------------
cv2.imshow('img', img)
cv2.imshow('result1', noisy_img)
cv2.imshow('result2', median_dst)

# 等待按键后关闭所有窗口
cv2.waitKey(0)
cv2.destroyAllWindows()

输出结果对比:
在这里插入图片描述
代码注释

cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace, dst=None, borderType=None)

参数说明:
src:输入图像(8位或浮点型,彩色图需是BGR格式,这里已转RGB不影响)
d:邻域直径,若为-1则由sigmaSpace计算(推荐设为5-9)
sigmaColor:灰度相似度标准差(值越大,允许更多灰度差异的像素参与,边缘易模糊)
sigmaSpace:空间距离标准差(值越大,影响范围越广,模糊越强)
borderType:边缘填充方式(默认即可)

双边滤波

核心原理:
同时考虑空间距离和像素灰度相似度来计算权重,空间距离越近、灰度越相似的像素权重越大,属于非线性滤波。
优点:
在去噪的同时能很好地保留图像边缘,解决了传统线性滤波(如高斯滤波)模糊边缘的问题。同时可以对边缘内的区域进行平滑处理。作用,进行美颜
缺点:
算法复杂度高,计算速度慢;参数(空间标准差、灰度标准差)调整较为复杂,对不同图像需针对性优化。
适用场景:
适用于需要保留边缘细节的去噪场景,如图像美颜、文物修复、医学图像处理等。

代码实例

#双边滤波
import cv2
import numpy as np
#可以输入一张有椒盐噪声的图,输出结果对比更加明显
img = cv2.imread('lena.png')

dst = cv2.bilateralFilter(img,9,75,75)
cv2.imshow('img',img)
cv2.imshow('dst',dst)
cv2.waitKey(0)

输出结果:
在这里插入图片描述
代码注释:

cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace, dst=None, borderType=None)

参数说明:
src:输入图像(8位或浮点型,彩色图需是BGR格式,这里已转RGB不影响)
d:邻域直径,若为-1则由sigmaSpace计算(推荐设为5-9)
sigmaColor:灰度相似度标准差(值越大,允许更多灰度差异的像素参与,边缘易模糊)
sigmaSpace:空间距离标准差(值越大,影响范围越广,模糊越强)
borderType:边缘填充方式(默认即可)

二,高通滤波

sobel(索贝尔)算子

Sobel 算子是基于一阶导数的边缘检测算法,通过分别计算 X、Y 方向的梯度,再融合得到整体边缘,通常会结合高斯滤波预处理以降低噪声干扰。
核心原理
采用两个 3x3 卷积核(分别对应 X、Y 方向),与图像卷积后得到两个方向的梯度图Gx(水平边缘,检测垂直方向灰度变化)和Gy(垂直边缘,检测水平方向灰度变化)。
整体梯度强度通过公式计算:G = sqrt(Gx² + Gy²),为简化计算也可使用近似公式:G = |Gx| + |Gy|。
关键特性
优点:结合了高斯平滑和微分运算,对噪声有一定抑制能力;计算速度较快,可分别获取水平 / 垂直边缘。
缺点:3x3 窗口对边缘的定位精度一般,当图像边缘较细时检测效果易受影响。
适用场景:对边缘定位精度要求不高、需快速检测的场景,如视频监控中的目标轮廓提取。

代码实例:

#索贝而算子
import cv2
import numpy as np
img = cv2.imread('lena.png')

#索贝尔算子y方向边缘
d1 = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
#索贝尔算子x方向边缘
#参数:图像、输出深度、x方向导数阶数、y方向导数阶数、卷积核尺寸
d2 = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
d3 = cv2.Sobel(img,cv2.CV_64F,1,1,ksize=3)
dst = d1 +d2
#dst = cv2.add(d1,d2)
#结果对比
cv2.imshow('img',img)
cv2.imshow('d1',d1)
cv2.imshow('d2',d2)
cv2.imshow('d3',d3)
cv2.imshow('dst',dst)

cv2.waitKey(0)

输出结果对比;
在这里插入图片描述
在这里插入图片描述

Scharr 算子(沙尔算子)

Scharr 算子是Sobel 算子的改进版本,同样基于一阶导数,针对 Sobel 算子 3x3 窗口定位精度不足的问题优化了卷积核权重。
核心原理
同样计算 X、Y 方向梯度,卷积核尺寸仍为 3x3,但权重绝对值更大,增强了对边缘的敏感性。
梯度强度计算方式与 Sobel 算子完全一致。
关键特性
优点:对边缘的检测灵敏度更高,定位精度优于 Sobel 算子;同样可分别获取水平 / 垂直边缘。
缺点:对噪声的抑制能力略弱于 Sobel 算子;计算量与 Sobel 相当。
适用场景:对边缘定位精度要求较高的场景,如医学图像(CT、MRI)的边缘提取。

代码示例:

#沙尔算子
import cv2
import numpy as np
img = cv2.imread('lena.png')

#算子y方向边缘
d1 = cv2.Scharr(img,cv2.CV_64F,1,0)
#算子x方向边缘
d2 = cv2.Sobel(img,cv2.CV_64F,0,1,)

dst = d1 +d2
#dst = cv2.add(d1,d2)
#结果对比
cv2.imshow('img',img)
cv2.imshow('d1',d1)
cv2.imshow('d2',d2)

cv2.imshow('dst',dst)

cv2.waitKey(0)

输出结果:
在这里插入图片描述

Laplacian 算子(拉普拉斯算子)

Laplacian 算子是基于二阶导数的边缘检测算法,通过计算灰度值的二阶导数变化来定位边缘,对噪声极为敏感,因此必须先进行降噪预处理(如高斯滤波)。
核心原理
无需区分方向,采用单一卷积核(常用 3x3),通过卷积计算图像的二阶导数。当二阶导数由正变负或由负变正时,零点位置即为边缘。
关键特性
优点:对边缘的检测更全面,可同时响应所有方向的边缘;无需分方向计算,逻辑简单。
缺点:对噪声极度敏感,未降噪时会产生大量伪边缘;易丢失边缘细节,对孤立点和细线也较为敏感。
适用场景:需突出所有方向边缘、且可提前有效降噪的场景,如图像锐化增强、工业检测中的缺陷边缘定位。

import cv2
import numpy as np
img = cv2.imread('lena.png')

dst = cv2.Laplacian(img, 3)
#结果对比
cv2.imshow('img',img)

cv2.imshow('dst',dst)

cv2.waitKey(0)

三,边缘检测

边缘检测是图像处理中提取图像轮廓的核心技术,通过捕捉像素灰度值的剧烈变化来定位边缘;而 Canny 边缘检测是其中最经典、性能最优的算法之一,通过多步骤优化实现了低误检、高定位精度和单像素边缘的检测效果。
Canny 边缘检测由 John F. Canny 于 1986 年提出,是一种多阶段的非线性边缘检测算法,通过严谨的步骤设计,解决了传统算法边缘模糊、误检多的问题,成为工业界和学术界的 “标准边缘检测算法”。

import cv2
import numpy as np

img = cv2.imread('lena.png')
dst = cv2.Canny(img, 50, 200)
cv2.imshow('img', img)
cv2.imshow('dst', dst)
cv2.waitKey(0)

输出结果:
在这里插入图片描述

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐