概念
何为噪点?
噪点:指图像收到的一些干扰因素,通常是由图像采集设备、传输信道等因素造成的,表现为图像中随机的亮度,也可以理解为有那么一些点的像素值与周围的像素值格格不入。
常见的噪声类型
- 高斯噪声:一种分布符合正态分布的噪声,会使图像变得模糊或有噪点。
- 椒盐噪声:一些黑白色的像素值分布在原图像中
左侧为高斯噪声 上面为原图 右侧为椒盐噪声
如何消除噪点
滤波器
使用滤波器,其主要功能是去除信号中的噪声或干扰,从而提高信号的信噪比。根据同频率区域中噪声信号和真实信号所在频率段的不同,将噪音所在的频率段进行屏蔽或改变其幅值。
下面我们来了解一下滤波器是如何工作的
滤波器:也可以叫做卷积核,与自适应二值化中的核一样,本身是一个小的区域,有着特定的核值,并且工作原理也是在原图上进行滑动并计算中心像素点的像素值。
- 滤波器可分为线性滤波和非线性滤波
- 线性滤波对邻域中的像素进行线性运算,如在核的范围内进行加权求和。
- 常见的线性滤波器有均值滤波 、方框滤波 和高斯滤波等。
- 非线性滤波则是利用原始图像与模板之间的一种逻辑关系得到结果。
- 常见的非线性滤波器有中值滤波器、双边滤波器等。
滤波与模糊在图像处理上有一定的联系与区别:
- 它们都属于卷积,不同滤波方法之间只是卷积核不同(对线性滤波而言)
- 低通滤波器是模糊,高通滤波器是锐化
- 低通滤波器就是允许低频信号通过,在图像中边缘和噪点都相当于高频部分,所以低通滤波器用于去除噪点、平滑和模糊图像。
- 高通滤波器则反之,用来增强图像边缘,进行锐化处理。
注意:椒盐噪声可以理解为斑点,随机出现在图像中的黑点或白点;高斯噪声可以理解为拍摄图片时由于光照等原因造成的噪声。
上面介绍了5种常见的滤波方式,现在我们来学习一下
线性滤波(模糊)方式
1. 均值滤波
均值滤波是一种最简单的滤波处理,它取的是卷积核区域内元素的均值,如3×3的卷积核:
比如有一张4*4的图片,现在使用一个3*3的卷积核进行均值滤波时,其过程如下所示:
对于边界的像素点,则会进行边界填充 ,以确保卷积核的中心能够对准边界的像素点进行滤波操作。默认使用BORDER_REFLECT_101的方式进行填充。
通过卷积核在原图上从左上角滑动计算到右下角,从而得到新的4*4的图像的像素值。
卷积核的中心点(3*3的中间像素点)会依次滑过1,2,3......,并计算出对应值
cv2.blur()函数
功能:用于对图像进行均值滤波(也称为平滑或模糊处理)的函数。均值滤波是一种简单的图像平滑技术,它通过替换图像中每个像素的值为其邻域像素值的平均值来减少图像噪声和细节。
参数:
- src: 输入图像,即你想要进行模糊处理的源图像。
- ksize: 核大小,用于指定均值滤波器的尺寸。它是一个元组 (width, height),表示滤波器在水平和垂直方向上的大小。通常,width 和 height 应该是奇数,以确保滤波器有一个中心像素。
- dst: 输出图像,这是一个可选参数。
- anchor: 锚点,这是一个可选参数,表示滤波器在源图像中应用的起始位置。默认值是 (-1, -1),这意味着锚点位于滤波器的中心。在大多数情况下,你不需要改变这个参数。
- borderType: 边界类型,这是一个可选参数,用于指定边界像素的外推方法。当滤波器应用到图像边缘时,需要一些额外的像素来计算边界像素的邻域平均值。OpenCV 提供了多种边界类型,如 cv2.BORDER_DEFAULT(默认)、cv2.BORDER_CONSTANT(用常数填充)、cv2.BORDER_REFLECT(反射边界)等。在大多数情况下,默认边界类型就足够了。
2. 方框滤波
方框滤波跟均值滤波很像,如3×3的滤波核如下:
比如有一张4*4的图片,现在使用一个3*3的卷积核进行均值滤波时,其过程如下所示:
对于边界的像素点,默认使用BORDER_REFLECT_101的方式进行填充。
其滤波的过程与均值滤波一模一样,都采用卷积核从图像左上角开始,逐个计算对应位置的像素值,并从左至右、从上至下滑动卷积核,并计算出对应值,直至到达图像右下角,唯一的区别就是核值可能会不同。
cv2.boxFilter()函数
**功能:**用于对图像进行盒式滤波(也称为均值滤波或平均滤波)的函数。这个函数使用一个矩形窗口对图像进行卷积,窗口内所有像素值的平均值将替代锚点位置的像素值。
参数:
- src: 输入图像,它可以是多通道的。
- ddepth: 输出图像的所需深度。当参数值为 -1 时,表示输出图像与输入图像有相同的深度。
- ksize: 核的大小。它是一个元组,表示滤波窗口的宽度和高度(如 (3, 3) 表示一个 3x3 的窗口)。核的大小必须是正奇数。
- dst: 输出图像,它应该与输入图像有相同的大小和类型。这是一个可选参数。
- anchor: 表示核的锚点(即核的中心点)在窗口中的位置。默认值是 (-1, -1),这意味着锚点位于窗口的中心。
- normalize: 一个标志,指示在滤波时是否对窗口内的像素值进行归一化。如果设置为 True(默认值),则会对窗口内的像素值求和并除以窗口的面积,从而得到平均值。如果设置为 False,则直接对窗口内的像素值求和,不进行除法运算。
- borderType: 边界类型,用于指定图像边界外像素的外推方法。这个参数在需要处理图像边界时很有用。它可以是诸如 cv2.BORDER_CONSTANT、cv2.BORDER_REFLECT 等的边界类型之一。当不指定时,默认使用 cv2.BORDER_DEFAULT。
注意:当normalize设置为Ture时,那么均值滤波与方框滤波就毫无差别
3. 高斯滤波
前面两种滤波方式,卷积核内的每个值都一样,也就是说图像区域中每个像素的权重也就一样。高斯滤波的卷积核权重并不相同:中间像素点权重最高,越远离中心的像素权重越小。
还记得我们在自适应二值化里是怎么生成高斯核的吗?这里跟自适应二值化里生成高斯核的步骤是一样的,都是以核的中心位置为坐标原点,然后计算周围点的坐标,然后带入下面的高斯公式中。
下面公式看看就行,只需关注最后的卷积核:
比如有一张4*4的图片,现在使用一个3*3的卷积核进行均值滤波时,其过程如下所示:
对于边界的像素点,则会进行边界填充 ,以确保卷积核的中心能够对准边界的像素点进行滤波操作。默认使用BORDER_REFLECT_101的方式进行填充。
其滤波过程与上面两种滤波方式的滤波过程一样,都是用卷积核从图像左上角开始,逐个计算对应位置的像素值,并从左至右、从上至下滑动卷积核,直至到达图像右下角,唯一的区别就是核值不同。
cv2.GaussianBlur() 函数
**功能:**用于对图像进行高斯模糊处理的函数。该函数通过高斯核对图像进行卷积操作,从而达到模糊图像的效果。
参数:
- src:输入图像,可以是灰度图像或彩色图像。它应该是一个 NumPy 数组,通常是通过 OpenCV 读取图像函数(如 cv2.imread())获得的。
- ksize:高斯核的大小。它应该是一个正奇数,表示高斯核的宽和高。例如,(3, 3) 或 (5, 5)。通常,核大小越大,模糊效果越明显。
- sigmaX:高斯核函数在 X 方向的标准偏差。这个参数控制着模糊的程度。标准偏差越大,模糊效果越强。通常,sigmaX 的值会设置为一个正数。
- sigmaY:(可选)高斯核函数在 Y 方向的标准偏差。如果 sigmaY 为 0,则函数会根据 sigmaX 的值来计算 Y 方向的标准偏差,即 sigmaY = sigmaX。如果提供了 sigmaY,则它会独立地控制 Y 方向的模糊程度。
- dst:(可选)输出图像。
- borderType:(可选)边界类型。
效果对比
非线性滤波方式
1. 中值滤波
中值又叫中位数,是所有数排序后取中间的值。中值滤波没有核值,而是在原图中从左上角开始,将卷积核区域内的像素值进行排序,并选取中值作为卷积核的中点的像素值。
比如有一张4*4的图片,现在使用一个3*3的卷积核进行均值滤波时,其过程如下所示:
对于边界的像素点,则会进行边界填充 ,以确保卷积核的中心能够对准边界的像素点进行滤波操作。中值滤波使用的是BORDER_REPLICATE进行填充
通过卷积核在原图上从左上角滑动计算到右下角,从而得到新的4*4的图像的像素值。
cv2.medianBlur()函数
**功能:**用于对图像进行中值滤波的函数。中值滤波是一种非线性的滤波方法,它用像素点邻域内的中值替代该像素点的值,从而起到平滑图像、去除噪声的作用,特别是对于去除椒盐噪声(即图像中随机出现的黑色或白色像素点)非常有效。
参数:
- src: 输入图像,可以是单通道、三通道等任意通道数的图像。图像的数据类型应该是 uint8、uint16 或 float32 之一。
- ksize: 滤波器的大小(即邻域的大小),必须是一个大于 1 的奇数。例如,3、5、7 等。这个参数决定了在进行中值计算时考虑的像素范围。
- dst:(可选)输出图像。
2. 双边滤波
模糊操作(低通滤波器)基本都会损失掉图像细节信息,尤其前面介绍的线性滤波器,图像的边缘信息很难保留下来。然而,边缘(edge)信息是图像中很重要的一个特征,所以这才有了双边滤波。
换而言之,双边滤波器可以保留更多 线性滤波器 无法保留的 边缘信息
双边滤波的基本思路是同时考虑将要被滤波的像素点的空域信息(周围像素点的位置的权重)和值域信息(周围像素点的像素值的权重)。为什么要添加值域信息呢?是因为假设图像在空间中是缓慢变化的话,那么临近的像素点会更相近,但是这个假设在图像的边缘处会不成立,因为图像的边缘处的像素点必不会相近。因此在边缘处如果只是使用空域信息来进行滤波的话,得到的结果必然是边缘被模糊了,这样我们就丢掉了边缘信息,因此添加了值域信息。
双边滤波采用了两个高斯滤波 的结合,一个负责计算空间邻近度的权值(也就是空域信息 ),也就是上面的高斯滤波器,另一个负责计算像素值相似度的权值(也就是值域信息),也是一个高斯滤波器。其公式如下所示:
看不懂没关系,这些公式我们不需要关心,我贴着玩的,能看就看,看不了拉倒,嘿嘿~。
采用两个高斯滤波器,边缘像素填充时自然使用的是BORDER_REFLECT_101进行填充
cv2.bilateralFilter()函数
**功能:**用于图像去噪的一个函数,它能够在保留边缘特征的同时去除噪声。这个函数实现了双边滤波,这是一种非线性的、边缘保留的、降噪的滤波器。双边滤波器的关键思想是在空域上进行邻域加权平均,同时考虑像素之间的空间邻近关系和颜色(或强度)相似性,从而避免模糊边缘。
参数:
- src (InputArray): 输入图像,可以是灰度图像或彩色图像。
- d (int): 邻域直径。如果它是非正数,则会被计算为 (sigmaSpace*2)。这个参数决定了滤波过程中每个像素的邻域大小。邻域是一个圆形区域,其半径等于 d/2(当 d 为奇数时)或 (d-1)/2(当 d 为偶数时,向下取整)。
- sigmaColor (double): 颜色空间滤波器的 sigma 值。这个参数决定了滤波函数在颜色(或强度)空间上的标准差。较大的 sigmaColor 值意味着更宽的颜色范围将被视为相似,从而增强去噪效果,但也可能导致边缘模糊。参数越大,临近像素将会在越远的地方mix。
- sigmaSpace (double): 坐标空间滤波器的 sigma 值。这个参数决定了滤波函数在空间(或位置)上的标准差。较大的 sigmaSpace 值意味着更远的像素将被纳入加权平均,从而增强平滑效果,但也可能导致边缘模糊。如果 d > 0,则 sigmaSpace 会根据 d 的值自动计算(尽管用户可以覆盖这个默认值)。参数越大,那些颜色足够相近的的颜色的影响越大。
- dst (OutputArray): 输出图像,与输入图像具有相同的尺寸和类型。
- borderType (int, optional): 边界像素的插值方法。
关于参数的选取:
- 关于2个sigma参数:
- 简单起见,可以令2个sigma的值相等;
- 如果他们很小(小于10),那么滤波器几乎没有什么效果;
- 如果他们很大(大于150),那么滤波器的效果会很强,使图像显得非常卡通化。
- 关于参数d:
- 过大的滤波器(d>5)执行效率低。
- 对于实时应用,建议取d=5;
- 对于需要过滤严重噪声的离线应用,可取d=9;
对比总结
-
在不知道用什么滤波器好的时候,优先高斯滤波 ,然后均值滤波。
-
斑点和椒盐噪声优先使用中值滤波 。
- 比如下面这张斑点噪声图,用中值滤波显然更好:
-
要去除噪点的同时尽可能保留更多的边缘信息,使用双边滤波。
-
线性滤波方式(速度相对快):均值滤波、方框滤波、高斯滤波。
-
非线性滤波方式(速度相对慢):中值滤波、双边滤波。
-
在OpenCV中,除了中值滤波使用的是BORDER_REPLICATE 进行填充之外,其他的滤波方法默认的是使用BORDER_REFLECT_101的方式进行填充。