转自:Python下opencv使用笔记(五)(图像的平滑与滤波)_python opencv cv2.filter2d-CSDN博客
对于图形的平滑与滤波,但从滤波角度来讲,一般主要的目的都是为了实现对图像噪声的消除,增强图像的效果。
首先介绍二维卷积运算,图像的滤波可以看成是滤波模板与原始图像对应部分的的卷积运算。关于卷积运算,找到几篇相关的博客:
图像处理:基础(模板、卷积运算)
图像处理-模板、卷积的整理
对于2D图像可以进行低通或者高通滤波操作,低通滤波(LPF)有利于去噪,模糊图像,高通滤波(HPF)有利于找到图像边界。
1.统一的2D滤波器cv2.filter2D
Opencv提供的一个通用的2D滤波函数为cv2.filter2D(),滤波函数的使用需要一个核模板,对图像的滤波操作过程为:将和模板放在图像的一个像素A上,求与之对应的图像上的每个像素点的和,核不同,得到的结果不同,而滤波的使用核心也是对于这个核模板的使用,需要注意的是,该滤波函数是单通道运算的,也就是说对于彩色图像的滤波,需要将彩色图像的各个通道提取出来,对各个通道分别滤波才行。
这里说一个与matlab相似的情况,matlab中也有一个类似的滤波函数imfilter,对于滤波函数的应用其实不只在于滤波,对于许多图像的整体处理上,其实都可以用滤波函数来组合实现,得到更快的效果,相关的介绍间下面这个博客:
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('flower.jpg',0) #直接读为灰度图像
img1 = np.float32(img) #转化数值类型
kernel = np.ones((5,5),np.float32)/25
dst = cv2.filter2D(img1,-1,kernel)
#cv2.filter2D(src,dst,kernel,auchor=(-1,-1))函数:
#输出图像与输入图像大小相同
#中间的数为-1,输出数值格式的相同plt.figure()
plt.subplot(1,2,1),plt.imshow(img1,'gray')#默认彩色,另一种彩色bgr
plt.subplot(1,2,2),plt.imshow(dst,'gray')
下面介绍的几种滤波部分可能是将函数cv2.filter2D()具体化,重新规定一个名字而已,贴一个好的博客参考:
2.均值滤波
上述生成的5*5核模板其实就是一个均值滤波。而opencv有一个专门的平均滤波模板供使用–归一化卷积模板,所有的滤波模板都是使卷积框覆盖区域所有像素点与模板相乘后得到的值作为中心像素的值。Opencv中均值模板可以用cv2.blur和cv2.boxFilter,比如一个3*3的模板其实就可以如下表示:
模板大小是m*n是可以设置的。如果你不想要前面的1/9,可以使用非归一化的模板cv2.boxFilter。一个实例如下:
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('flower.jpg',0) #直接读为灰度图像
blur = cv2.blur(img,(3,5))#模板大小3*5
plt.subplot(1,2,1),plt.imshow(img,'gray')#默认彩色,另一种彩色bgr
plt.subplot(1,2,2),plt.imshow(blur,'gray')
然而,均值滤波对于一些特定类型的噪声(如周期性噪声)可能效果不佳,因为这些噪声会在图像中形成特定的模式,而均值滤波只能模糊图像,无法针对特定模式的噪声进行处理。总的来说,均值滤波是一种简单而有效的去噪方法,适用于大多数情况下的随机噪声去除。但在特定情况下,可能需要考虑其他类型的滤波器或去噪技术。卷积核越大,参与到均值运算中的像素就会越多,即当前计算的算的是更多点的像素值的平均值,去噪效果越好,当然花费的计算时间也会越长,同时让图像失真越严重。因此在实际处理中,要在失真和去噪效果之间取得平衡,选取合适大小的卷积核。
3.高斯模糊模板
现在把卷积模板中的值换一下,不是全1了,换成一组符合高斯分布的数值放在模板里面,比如这时中间的数值最大,往两边走越来越小,构造一个小的高斯包。实现的函数为cv2.GaussianBlur()。对于高斯模板,我们需要制定的是高斯核的高和宽(奇数),沿x与y方向的标准差(如果只给x,y=x,如果都给0,那么函数会自己计算)。高斯核可以有效的出去图像的高斯噪声。当然也可以自己构造高斯核,相关函数:cv2.GaussianKernel().
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('flower.jpg',0) #直接读为灰度图像
for i in range(2000): #添加点噪声
temp_x = np.random.randint(0,img.shape[0])
temp_y = np.random.randint(0,img.shape[1])
img[temp_x][temp_y] = 255
blur = cv2.GaussianBlur(img,(5,5),0)
plt.subplot(1,2,1),plt.imshow(img,'gray')#默认彩色,另一种彩色bgr
plt.subplot(1,2,2),plt.imshow(blur,'gray')
高斯滤波主要用于去除图像中的高频噪声,使图像变得更加平滑,同时也可以用于图像模糊或降低图像的细节信息。高斯滤波对高斯噪声的去除效果非常显著,可以有效地使图像变得更加平滑
4.中值滤波模板
中值滤波模板就是用卷积框中像素的中值代替中心值,达到去噪声的目的。这个模板一般用于去除椒盐噪声。前面的滤波器都是用计算得到的一个新值来取代中心像素的值,而中值滤波是用中心像素周围(也可以使他本身)的值来取代他,卷积核的大小也是个奇数。
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('flower.jpg',0) #直接读为灰度图像
for i in range(2000): #添加点噪声
temp_x = np.random.randint(0,img.shape[0])
temp_y = np.random.randint(0,img.shape[1])
img[temp_x][temp_y] = 255
blur = cv2.medianBlur(img,5)
plt.subplot(1,2,1),plt.imshow(img,'gray')#默认彩色,另一种彩色bgr
plt.subplot(1,2,2),plt.imshow(blur,'gray')
可以看到中值滤波对于这些白点噪声的去除是非常的好的。
然而,中值滤波也有一些局限性,比如在保留图像细节的同时也会模糊图像,卷积核选择和均值滤波算法存在一样的问题,卷积核越大,参与到均值运算中的像素就会越多,即当前计算的算的是更多点的像素值的平均值,去噪效果越好,当然花费的计算时间也会越长,同时让图像失真越严重
5.双边滤波
原理和功能
空间距离权重:除了像素值之间的相似性,双边滤波还考虑了像素之间的空间距离。这意味着附近的像素对于滤波的影响更大,而远离的像素对滤波的影响更小。
相似性权重:双边滤波器使用高斯函数来度量像素值之间的相似性。如果两个像素的值非常相似,它们的权重较大。如果它们的值差异很大,它们的权重较小。
保留边缘信息:相比于一般的平滑滤波器,双边滤波器可以保留图像的边缘信息。这是因为它会考虑到边缘处像素的相似性。
双边滤波函数为cv2.bilateralFilter()。该滤波器可以在保证边界清晰的情况下有效的去掉噪声。它的构造比较复杂,即考虑了图像的空间关系,也考虑图像的灰度关系。双边滤波同时使用了空间高斯权重和灰度相似性高斯权重,确保了边界不会被模糊掉。有一个介绍专门介绍双边滤波的博客:
cv2.bilateralFilter(img,d,’p1’,’p2’)函数有四个参数需要,d是领域的直径,后面两个参数是空间高斯函数标准差和灰度值相似性高斯函数标准差。一个实例如下:
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('flower.jpg',0) #直接读为灰度图像
for i in range(2000): #添加点噪声
temp_x = np.random.randint(0,img.shape[0])
temp_y = np.random.randint(0,img.shape[1])
img[temp_x][temp_y] = 255
#9---滤波领域直径
#后面两个数字:空间高斯函数标准差,灰度值相似性标准差
blur = cv2.bilateralFilter(img,9,75,75)
plt.subplot(1,2,1),plt.imshow(img,'gray')#默认彩色,另一种彩色bgr
plt.subplot(1,2,2),plt.imshow(blur,'gray')
6.NL-Means(Non-Local Means)
NL-Means(Non-Local Means)是一种图像去噪算法,它通过利用图像中相似区域的信息来降低噪声水平,而不会损失图像的细节信息。NL-Means算法不仅可以处理高斯噪声,还可以有效地处理泊松噪声等其他类型的噪声。
NL-Means算法的基本思想是,对于图像中的每一个像素,通过计算该像素周围区域与其他像素区域的相似性来进行去噪。相似性计算可以基于像素强度的差异,也可以使用特征向量来进行。NL-Means算法的基本原理如下:
- 相似性比较: 对于图像中的每一个像素,NL-Means算法首先会在图像的局部区域内搜索与该像素相似的区域。相似性的度量可以基于像素强度的差异,也可以使用特征向量来进行。
- 权重计算: 对于每一个相似区域,算法会计算一个权重值,该权重值表示了该相似区域与目标像素的相似性。相似性越高,权重值越大。
- 加权平均: 使用计算得到的权重值,NL-Means算法对所有相似区域的像素值进行加权平均,得到目标像素的估计值。
- 重复处理: 以上步骤对图像中的每一个像素都进行处理,以达到整体去噪的效果。
通过这种方式,NL-Means算法能够保留图像的细节信息,并在降低噪声水平的同时,避免了模糊效果:
def denoise_nl_means(image, h=10, hForColor=10, templateWindowSize=7, searchWindowSize=21):
denoised_image = cv2.fastNlMeansDenoisingColored(image, None, h, hForColor, templateWindowSize, searchWindowSize)
return denoised_image
噪音图片:
NL-Means去噪后图片: