☰
四种滤波算法揭秘:图像平滑处理全解析
2026/10/13 3:14:57 网站建设 项目流程

这篇文稿的核心议题是围绕着怎样去开展调用操作来达成图像的平滑处理这个目标, 在这一过程中总共涉及了四种具体的算法, 这四种算法分别就是所谓的均值滤波、方框滤波、高斯滤波以及中值滤波, 整篇文章所涵盖的所有内容都属于非常基础的知识层面, 希望能够对您产生一些帮助作用, 具体需要掌握的知识点内容罗列如下。

1.把图像进行处理, 让它变平稳。

2.均值滤波

3.方框滤波

4.高斯滤波

5.中值滤波

PS: 这篇文章主要介绍了图像平滑, 目的是希望大家先直观地看看图像处理的效果, 后面还有可能会补充一些基础知识来帮助大家学习。本文参考了作者本人的博客, 以及网易云课堂李大洋老师的讲解内容。在此强烈推荐大家进行学习。

对那幅图像进行平滑操作。

1.图像增强

图像增强是进行图像处理的一种操作, 目的是让处理之后的图像, 比原始的那种图像, 更适合特定的那些应用场合, 这一过程需要和实际的应用场景紧密地结合到一起。

对于像边缘、轮廓、对比度这样的图像的某些具体特征来说嘛, 图像增强的方式就是去强调它们, 或者把它们变得锐利一些, 这样子做的原因, 是为了让后续的观看显示更方便, 或者是为了观察起来更轻松, 又或者是为了让进一步的分析和处理更容易执行。

总而言之, 图像增强所使用的具体方法, 是要根据不同的应用环境而有所区别的, 这里所包含的研究内容包括: (参考课件和左飞的《数字图像处理》)。

2.图像平滑

图像平滑是增强区域的一种算法, 这里面包含邻域平均法、中指滤波、边界保持类滤波等等这些方法。

在图像的生成阶段、传输过程还有复制环节里, 经常会受到很多因素的影响, 从而导致噪声干扰或是出现数据丢失的情况, 这样一来, 图像的质量就被降低了, 至于某一像素点如果和它周边的像素点比起来有着明显不一样的地方, 那么这个像素点就认为是被噪声给感染。

这就需要采取一定措施对图像实施增强处理, 以此来降低上述那些缺陷所造成的不利影响。

简单平滑-邻域平均法

3.邻域平均法

所谓“图像简单平滑”, 指的就是用一种叫做“邻域简单平均”的方法, 对图像进行那种叫“平滑处理”的操作。这一招儿能够在一定程度上消除掉原始图像里的噪声, 同时也起到降低原始图像对比度的作用。

具体的做法是利用卷积运算, 拿图像里那个邻居区域的像素灰度去算个平均值。目的就是要减小图像中噪声产生的影响, 并且降低图像的对比度。

但是这个邻域平均值的方法有主要的缺点, 它会在降低噪声的这个过程中的时候让图像变得模糊, 尤其是在边缘和细节的那些地方的, 并且呢这个邻域的大小越大之后, 在去噪能力增强的这个过程之中, 那个模糊的程度也就越严重的。

接下来我们先去提供一下那段用于给图像增添噪声的代码内容。

# -*- coding:utf-8 -*-import cv2import numpy as np#读取图片img = cv2.imread("test.jpg", cv2.IMREAD_UNCHANGED)rows, cols, chn = img.shape#加噪声for i in range(5000):x = np.random.randint(0, rows)y = np.random.randint(0, cols)img[x,y,:] = 255cv2.imshow("noise", img)#等待显示cv2.waitKey(0)cv2.destroyAllWindows

显示出来的最终成果是这样的。

均值滤波

1.原理

所谓的均值滤波, 其实是指任意一个给定的点的像素值, 它那个值, 都是由周围那些个N乘以M个点的像素值的平均值所决定的。举个例子, 就比如说在现在展示的这个图里面, 我们可以看到那个红色的点, 它的像素值, 实际上就是等于那个蓝色的背景区域里面所有的像素值的总和, 然后这个总和再除以二十五。

对于红色区域, 其像素值的计算过程是先做均值滤波处理, 具体做法是先将数值相加, 然后再除以二十五, 这里的数字包括第一组的三百八十三、二百七十二、八百六十九、七百四十九和四百零二, 然后对这些数求和后再除以二十五个样本点。

其中那个尺寸是5行乘以5列的矩阵, 它这个名字叫做核。针对在原始图像里面存在的每一个像素点, 采用这个核来进行处理操作, 最终所得到的结果图像。

提取1/25可以将核转换为如下形式:

2.代码

具体的调用情况是, 实现均值滤波的这个核心函数被调用了。

= cv2.blur(原始图像,核大小)

在这些内容里, 核大小是由宽度以及高度所组成的一个元组来进行表示的。对于大家来说, 常见的类型包含了核大小为3以及3的那一种, 并且还包含了核大小为5以及5的这一种。

代码如下所示:

#encoding:utf-8import cv2import numpy as npimport matplotlib.pyplot as plt#读取图片img = cv2.imread('test01.png')source = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)#均值滤波result = cv2.blur(source, (5,5))#显示图形titles = ['Source Image', 'Blur Image']images = [source, result]for i in xrange(2):plt.subplot(1,2,i+1), plt.imshow(images[i], 'gray')plt.title(titles[i])plt.xticks([]),plt.yticks([])plt.show

所展现出来的最终结果, 就是如下面这张图里面所显示的那样。

将核的设置调整为(10, 10)以及(20, 20), 这种做法会导致最终的图像呈现出一种更为严重的模糊效果。

倘若将其设定为<1, 1>, 那么最终得到的处理结果就和原先的那张图像是一模一样的。在这个阶段, 核心部分里面的每一个权重数值全都保持着完全相同的状态, 这种现象在专业领域通常被叫做平均数。

方框滤波

方框滤波与均值滤波所使用的核在基本构造上是一致的, 它们之间的主要区别在于, 在处理过程中是否需要执行均一化的操作。为了实现方框滤波这一功能, 我们需要借助专门的软件调用函数来进行完成。具体的函数实现代码展示如下:

= cv2.(原始图像, 目标图像深度, 核大小, 属性)

这里面, 目标图像的深度是一个整数类型, 大家通常会用负一去, 意思是说它和原始的图像是一样的。然后, 核的大小主要包含了括号三更括号的三和括号五更括号的五这两个数值, 具体情况可以看下面的展示。

这个属性是用来表示要不要对目标的图片进行归一化处理的。如果是true的话, 就要去做均值化处理。如果是false的话, 就不做均值化处理。实际上就是去计算周围各个像素的那个和。如果出现了溢出的情况, 就会变成白色。这时候对应的像素值就是255。

在进行图像的简单平滑处理时, 算法会使用一个卷积模板, 然后对图像里每一个像素都逐一进行扫描和处理。我们可以把整个操作过程, 形象地比喻成对原始图像中存在的每个像素点, 去进行一遍接一遍的过滤还有整理工作。

在有关图像处理的专业领域里面, 对于那些涉及把邻域像素逐一处理的算法流程, 大家都统一把它称为滤波器。至于说平滑线性滤波器到底是怎么运行的, 它主要的工作方式是依托于所用到的模板, 去对位于邻域内部的那些像素点的灰度数值执行加权平均的操作。因为这个缘故, 这种技术有时候也被称为均值滤波器。

代码如下所示:

#encoding:utf-8import cv2import numpy as npimport matplotlib.pyplot as plt#读取图片img = cv2.imread('test01.png')source = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)#方框滤波result = cv2.boxFilter(source, -1, (5,5), normalize=1)#显示图形titles = ['Source Image', 'BoxFilter Image']images = [source, result]for i in xrange(2):plt.subplot(1,2,i+1), plt.imshow(images[i], 'gray')plt.title(titles[i])plt.xticks([]),plt.yticks([])plt.show

在代码的编写过程之中, 使用的是5*5的这种大小的核, 当等于1的时候, 表示进行归一化处理的操作, 这个时候的结果是和均值滤波是相同的, 输出的结果如下图所示:

下面就是那幅图像的左上方在处理工作完成之前以及之后, 各个像素点的数值变化情况。

print(source[0:3, 0:3, 0])#[[115 180 106]# [ 83 152 72]# [ 55 58 55]]print(result[0:3, 0:3, 0])#[[92 90 78]# [92 89 77]# [82 80 72]]

要是省略了参数, 那就默认要做归一化处理。如果设定成 =0 的话, 就不做归一化处理, 像素值等于周围所有像素的总和, 这样一来图像看着就更偏向白色。

#encoding:utf-8import cv2import numpy as npimport matplotlib.pyplot as plt#读取图片img = cv2.imread('test01.png')source = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)#方框滤波result = cv2.boxFilter(source, -1, (5,5), normalize=0)#显示图形titles = ['Source Image', 'BoxFilter Image']images = [source, result]for i in xrange(2):plt.subplot(1,2,i+1), plt.imshow(images[i], 'gray')plt.title(titles[i])plt.xticks([]),plt.yticks([])plt.show

所展现出来的最终结果, 就是如下面这张图里面所显示的那样。

在上面的那幅图中的大量像素点都是白色的, 这是因为对图像进行求和处理之后得到的结果大部分都接近于255这个数值。假如我们在这里设置成使用一个规格为2乘2的矩阵来运算的话, 仅仅是截取并处理其中包含的那四个像素点所对应的数据, 这样做出来的最终效果肯定会更好一些, 更有成效一些。

= cv2.(, -1, (2,2), =0)

高斯滤波

为了克服简单局部平均法的弊端, 也就是图像模糊的情况, 目前已经提出许多能够保持边缘和细节的局部平滑算法。这些算法的出发点都集中在如何选择合适的邻域大小、形状以及方向上, 同时也包括对邻域各个站点使用参数进行加平均操作时, 如何确定各个权重系数等问题。

图像高斯平滑也是采取邻域平均的思想对图像进行平滑的一种方法, 在图像高斯平滑这里, 对图像进行平均的时候, 不同位置的像素都被赋予了不同的权重, 高斯平滑与简单平滑是完全不同的, 它在对邻域内的像素进行平均时, 给不同位置的像素分配了不同的权值, 下图中所示的为 3 * 3 和 5 * 5 领域的高斯模板。

高斯滤波这个方法, 是让那些离得近的像素点, 拥有更高的一个重要程度, 然后针对四周的那些像素点, 去计算它们的加权平均值呢, 其中那个比较近的像素点, 就是对应着有一个比较大的一个权重值。正如下图所示那样, 中心的那个位置, 它的权重是最高的, 具体数值达到了0.4。

在中, 主要调用了函数, 具体来说:

dst = cv2.(src, ksize, )

其中, src是指原始图像, ksize是指核的大小, 还有那个部分是指X方向上的方差。需要注意一点是, 核大小(N, N)这玩意儿必须得是奇数才行, 而X方向上的这个方差主要是用来控制权重的。

代码如下:

#encoding:utf-8import cv2import numpy as npimport matplotlib.pyplot as plt#读取图片img = cv2.imread('test01.png')source = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)#高斯滤波result = cv2.GaussianBlur(source, (3,3), 0)#显示图形titles = ['Source Image', 'GaussianBlur Image']images = [source, result]for i in xrange(2):plt.subplot(1,2,i+1), plt.imshow(images[i], 'gray')plt.title(titles[i])plt.xticks([]),plt.yticks([])plt.show

显示出来的最终成果是这样的。

如果使用的是大小为15乘以15的核, 那么生成的图形将会变得更加模糊。

中值滤波

1.概念

人们在使用把邻域平均值当作去噪方法的时候, 图像里的边界就变得模糊不清了。中值滤波这种图像处理方法并不属于非线性处理范畴不对的, 它是在进行去噪操作的同时, 能够让边界的详细信息保持完好。我们需要去选取一个包含了奇数个点的窗口W, 让这个窗口在整个图像上移动扫描。

对于该窗口范围内部的像素点, 需要把它们按照灰度等级的上升顺序或者下降顺序来进行排列, 最后提取出来处在中间位置的那个灰度数值, 用它来替代原先那个点对应的灰度数值。比如说, 选择用于进行滤波操作的窗口情况如下所示。

这里提到的是一维情况的窗口结构。需要被处理的那个像素点所对应的灰度数值, 是取取自这个模板里头所有灰度数值当中的中间那一个值作为其最终结果的。那么具体的这种滤波是怎么去操作的呢, 流程步骤具体如下:

如下图所示, 把临近的像素按照大小进行排序, 然后取出排在中间位置的那一个数值, 把这个数值当成是中值滤波操作之后所应该得到的像素值。

2.代码

在主要调用函数来实现中值滤波的处理过程中可以发现, 在对于图像进行平滑处理这个方面来说, 中值滤波所能够到达的效果实际上是相当好的。

dst = cv2.(src, ksize)

在这其中, src所代表的是那个源文件,而ksize则是在说明核的大小, 这里需要注意的一个点是, 这个核必须得要是一个比1还要大的奇数才行, 比如说像3、5还有7这样的数字。

代码如下所示:

#encoding:utf-8import cv2import numpy as npimport matplotlib.pyplot as plt#读取图片img = cv2.imread('test01.png')#高斯滤波result = cv2.medianBlur(img, 3)#显示图像cv2.imshow("source img", img)cv2.imshow("medianBlur", result)#等待显示cv2.waitKey(0)cv2.destroyAllWindows

所展现出来的最终结果, 就是如下面这张图里面所显示的那样。

我们通常会用到方形、十字形、圆形和环形这些常用的窗口。因为不同形状的窗口会产生不同的滤波效果, 所以对于外轮廓线比较长的物体图像, 大家更适合使用方形或者圆形的窗口来进行处理, 而十字形的窗口对于那些有尖顶角状的图像来说, 效果是比较好的。

另外, 中值滤波这种方法对于消除孤立点和线性信号的干扰是非常有用的, 特别是在面对二进噪声的时候表现很好, 但是如果要对付高斯噪声的话, 那么它的效果就不算太好了。在一些细节成分比较丰富的复杂图像的场合下, 大家能够反复地去采用那些不相同的中值滤波的方式。

真心地期盼这篇文章能够为各位带来一点帮助, 假如在阅读过程中发现了存在错误或不够完善的地方, 还恳请大家能够予以谅解与包容。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询