OpenCV(Python3)_12(图像平滑)

目标

学会:

  • 用各种不同的低通滤波器对图像进行模糊
  • 将自定义的滤波器对图像进行卷积

二维卷积(图像滤波)

与一维信号一样,我们也可以对图像进行低通滤波器(LPF),高通滤波器(HPF)。LPF有助于消除噪声,模糊图像等。HPF滤波器则有助于找到图片的边缘。OpenCV提供了一个函数cv.filter2D()来将一个内核与一个图像进行卷积。下面我们将尝试对图像使用平均滤波器。一个5x5的平均滤波器内核如下所示:

ķ= 1251111111111111111111111111

操作如下:将该内核放在一个像素之上,然后将求与核对应的25个像素的和,最后取其平均值替换中心像素。对图像中的所有像素进行此操作。

程序:

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt

img = cv.imread('lena.jpg')
kernel = np.ones((5,5),np.float32)/25
dst = cv.filter2D(img,-1,kernel)
#当ddepth = -1时,输出图像将具有与源相同的深度。
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(dst),plt.title('Averaging')
plt.xticks([]), plt.yticks([])
plt.show()

结果:

                                                

图像模糊(图像平滑)

通过将图像与低通滤波器内核进行卷积可以实现图像模糊的目的,这对于消除噪音很有用。它实际上从图像中去除高频分量(例如:噪声,边界)。所以在这个操作中边界会模糊一点。(好吧,有些模糊的技术并不会模糊掉图像的边缘)。OpenCV主要提供四种模糊技术。

1.平均

这是通过将图像与归一化的盒子滤波器进行卷积来完成的。它只取内核区域内覆盖的所有像素,并用其平均值并替换中心元素。这由函数cv.blur()cv.boxFilter()完成查看文档以获取有关内核的更多详细信息。我们应该指定内核的宽度和高度。一个3x3归一化盒子滤波器如下图所示:

ķ= 19111111111
注意
如果您不想使用归一化的盒子滤波器,请使用 cv.boxFilter() 将参数normalize = False传递给该函数。

使用5x5大小的内核检查下面的示例演示:

扫描二维码关注公众号,回复: 2894987 查看本文章

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

img = cv.imread('opencv-logo-white.png')
blur = cv.blur(img,(5,5))
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(blur),plt.title('Blurred')
plt.xticks([]), plt.yticks([])

plt.show()

结果:

                                                          

2.高斯模糊

现在把卷积核换成高斯核(简单来说,方框不变,将原来每个方框的值是相等的,现在里面的值是符合高斯分布的,方框中心的值最大,其余方框根据距离中心元素的距离递减,构成一个高斯小山包。原来的求平均数现在变成求加权平均数,全就是方框里的值)。实现的函数是 cv2.GaussianBlur()。我们需要指定高斯核的宽和高(必须是奇数)。以及高斯函数沿 X,Y 方向的标准差。如果我们只指定了 X 方向的的标准差,Y 方向也会取相同值。如果两个标准差都是 0,那么函数会根据核函数的大小自己计算。

高斯滤波可以有效的从图像中去除高斯噪音。

如果你愿意的话,你也可以使用函数 cv2.getGaussianKernel() 自己构建一个高斯核。

如果要使用高斯模糊的话,上边的代码应该写成:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

img = cv.imread('opencv-logo-white.png')
blur = cv.GaussianBlur(img,(5,5),0)
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(blur),plt.title('Blurred')
plt.xticks([]), plt.yticks([])
plt.show()

结果:

                                                      

3.中值模糊

顾名思义就是用与卷积框对应像素的中值来替代中心像素的值。这个滤波器经常用来去除椒盐噪声(一维信号中的脉冲噪声)。前面的滤波器都是用计算得到的一个新值来取代中心像素的值,而中值滤波是用中心像素周围(也可以使他本身)的值来取代他。中值模糊能有效的去除噪声。卷积核的大小也应该是一个奇数。

在这个例子中,我们给原始图像加上 50% 的噪声然后再使用中值模糊。在这个演示中,我为原始图像添加了50%的噪点并应用了中值模糊。

程序:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

img = cv.imread('opencv-logo-white.png')
median = cv.medianBlur(img,5)
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(median),plt.title('Blurred')

plt.xticks([]), plt.yticks([])

plt.show()

结果:

                                                               

4.双边滤波

函数cv.bilateralFilter()在保持边缘锐利的同时,也可以非常有效地去除噪音。但与其他过滤器相比,处理的速度较慢。我们已经看到了高斯滤波器是求取中心点附近区域像素的高斯加权平均值。因而这个高斯滤波器仅仅是空间的函数,也就是在滤波时考虑了中心点与附近的像素的空间关系。它没有考虑像素值之间的关系。它不考虑像素是否具有几乎相同的强度。它不考虑像素是否是边缘像素。因而边缘部分通常会被模糊掉,而这正不是我们想要的。

双边滤波在同时使用空间高斯权重和灰度值相似性高斯权重。空间高斯函数确保只有邻近区域的像素对中心点有影响,灰度值相似性高斯函数确保只有与中心像素灰度值相近的才会被用来做模糊运算。所以这种方法会确保边界不会被模糊掉,因为边界处的灰度值变化比较大。

更详细的解释:

双边滤波是非线性滤波方式的一种,可以有效地保存边缘信息。现在针对其函数公式,对其作用做出分析首先是计算公式:

其中w(i,j,k,l)的计算方法如下:

d函数是根据像素距离选择权重,距离越近权重越大,这一点和方框滤波,高斯滤波方式相同。而r函数则是根据像素的差异来分配权值。如果两个像素值越接近,即使相距较远,也比差异大而距离近的像素点权重大。正是r函数的作用,使得边缘,即相距近但差异大的像素点的特性得以保留。

以下示例显示使用双边过滤器(有关参数的详细信息,请访问文档)。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

img = cv.imread('opencv-logo-white.png')
#image,d像素的直径,sigmaColor,sigmaSpace    
blur = cv.bilateralFilter(img,9,75,75)
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(blur),plt.title('Blurred')
plt.xticks([]), plt.yticks([])
plt.show()

结果:

                                        

猜你喜欢

转载自blog.csdn.net/qq_27806947/article/details/80757612