OpenCV学习笔记(8)——图像平滑
- 使用不同的低筒滤波器对图像进行模糊
- 使用自定义的率弄起对图像进行卷积(2D卷积)
2D卷积
与信号一样,我们也可以对2D图像实施低通滤波,高通滤波等。LPF帮助我们去除噪声,模糊图像。而HPF帮助我们找到图像边缘。
OpenCV提供的函数cv2.filter2D()可以让我们对一幅图像进行卷积操作。比如下面我们将对一幅图像使用平均滤波器,如一个5*5的平均滤波器核:
操作如下:将核放在图像的一个像素A上,求与核对应的图像上的25个像素的和,再取平均数,用这个平均数代替像素A的值。重复以上操作直到将图像的每一个像素值都更新一边。例程如下:
# -*- coding:utf-8 -*-
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('2.jpg')
kernel = np.ones((5,5),np.float32)/25
#cv2.filter2D(src,depth,kernel,...)
#那个depth暂时没看出有啥用,试了几个值都没区别
dst = cv2.filter2D(img,-1,kernel)
cv2.imshow('ori',img)
cv2.imshow('avr',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
--->
图像模糊(图像平滑)
使用低通滤波器可以达到图像模糊的目的。这对去除噪声很有帮助。其实就是去掉图像中的高频部分(比如:噪声,边界)。所以边界也会被模糊一点(当然也存在一些不会模糊掉边界的技术)。OpenCV中提供了四种模糊技术。
1.平均
其实和前面是一样的,但是实现方法不一样,他是用卷积框覆盖区域所有像素的平均值来代替中心元素。可以使用cv2.blur() 和 cv2.boxFilter()来完成。我们需要设定卷积框的宽和高。如下面一个3*3的归一化卷积框:
# -*- coding:utf-8 -*-
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('2.jpg')
blur = cv2.blur(img,(3,3))如果改为5*5应该会得到和前面一样的效果
#如果不想用归一化卷积框,可以用blur = cv2.boxFilter(src,depth,size,...)并传入参数normalize=False
#由于用plt读入BGR图会出问题,所以改用cv2
cv2.imshow('ori',img)
cv2.imshow('avr',blur)
cv2.waitKey(0)
cv2.destroyAllWindows()
2.高斯模糊
现在把卷积核换成高斯核(简单来说,方框不变,原来每个方框里的值是相等的,现在变成高斯分布的,方框中心的值最大,其余方框根据距离中心元素的距离递减,构成一个高斯小山包。这样原来的求平均变成了加权平均,权值就是框里的值)。实现的函数是cv2.GaussianBlur()。我们需要制定高斯核的宽和高(必须是奇数)。以及高斯函数眼X,Y方向的标准差。如果我们只指定了X方向的标准差,Y方向也会取相同值。如果两个标准差均为0,那么函数会根据核函数的大小自己计算。高斯滤波可以有效的从图像中去除高斯噪声。
也可以用cv2.getGaussianKernel()自己构建一个高斯核。
可以将高斯模糊应用于开始的例子中:
# -*- coding:utf-8 -*-
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('2.jpg')
blur = cv2.GaussianBlur(img,(5,5),0)
#由于用plt读入BGR图会出问题,所以改用cv2
cv2.imshow('ori',img)
cv2.imshow('avr',blur)
cv2.waitKey(0)
cv2.destroyAllWindows()
效果如下
--->
3.中值模糊
顾名思义就是用与卷积框对应像素的中值来替代中心像素的值。这个滤波器经常用来去除椒盐噪声。前面的滤波器都是用计算得到的一个新值来取代中心像素的值,而中值滤波是用中心像素周围的值来取代他。他能有效的去除噪声,卷积核的大小也必须是一个奇数(否则哪来的中心)
我们可以在原图上加上50%的噪声在使用中值模糊。
# -*- coding:utf-8 -*-
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('6.jpg')
blur = cv2.medianBlur(img,5)
#由于用plt读入BGR图会出问题,所以改用cv2
cv2.imshow('ori',img)
cv2.imshow('avr',blur)
cv2.waitKey(0)
cv2.destroyAllWindows()
--->
4.双边滤波
cv2.bilateralFilter()能在保持边界清晰的情况下有效的去除噪声。但是这种操作与其他滤波器相比会比较慢。双边滤波和前述的滤波不同,他同时使用空间高斯权重和灰度值相似性高斯权重。空间高斯函数确保只有邻近区域的像素对中心点有影响,灰度值相似性高斯函数确保只有与中心像素灰度值相近的才会被用来模糊运算。所以这种方法会确保边界不会被模糊掉,因为边界处的灰度值变化比较大。
进行双边滤波的代码如下:
# -*- coding:utf-8 -*-
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('2.jpg')
#cv2.bilateralFilter(src,d,sigmaColor,sigmaSpace),d是邻域直径,两个75分别し空间高斯函数标准差,灰度值相似性高斯函数标准差
blur = cv2.bilateralFilter(img,9,75,75)
#由于用plt读入BGR图会出问题,所以改用cv2
cv2.imshow('ori',img)
cv2.imshow('avr',blur)
cv2.waitKey(0)
cv2.destroyAllWindows()
效果如下:
--->