1.概念介绍
低通滤波:低通滤波可以去除图像的噪音或平滑图像。
高通滤波:可以帮助查找图像的边缘。
噪音:即对一幅图像的产生负面效果,过暗或过亮的部分,一幅图像中,低于或高于某个像素点的值,都可以认为是噪音。
卷积核:即用来滤波的矩阵,卷积核一般为奇数,如3×3、5×5、7×7等;
锚点:卷积核最中间的坐标点。
卷积核越大,卷积的效果越好,但是计算量随之也会增大。
边界扩充:当卷积核大于1,并且不进行边界扩充,输出尺寸相应缩小、当卷积核一标准方式进行边界扩充,则输出的空间尺寸与输入相等。
下面的为原图像,上面为输出图像,灰色为卷积核,虚线为图像扩充
2. 图像卷积
filter2D()
dst = cv2.filter2D(src, ddepth, kernel, anchor, delta, borderType)
src:原图像
ddepth:输出图像的尺寸,默认为-1
kernel:卷积核(是一个矩阵)
anchor:锚点,默认随卷积核变化
delta:卷积后加一个值,默认为0
borderType:有映射类型,加一个黑边,默认不设置
kernel:是一个矩阵
import cv2 import numpy as np img = cv2.imread('./image/lena.jpg') # 创建一个5*5的卷积核 kernel = np.ones((5, 5), np.float32) / 25 img2 = cv2.filter2D(img, -1, kernel) # 展示图像 cv2.imshow('img', img) cv2.imshow('img2', img2) cv2.waitKey(0)
经过图像处理后,看着变模糊了,更平滑了
3. 低通滤波器
filter2D接口需要我们自己定义卷积核,如何设置一个适合的卷积核,也成为了一个难题,为此OpenCV提供了一系列的滤波器,每个滤波器都有自己的专用卷积核,这样d大大减轻了使用人员的负担。
3.1 方盒滤波和均值滤波
boxFilter()
dst = cv2.boxFilter(src, ddepth, ksize , anchor, normalize, borderType)
src:输入图像
ddepth:输出图像的尺寸,默认为-1
kernel:卷积核大小(x, y)
anchor:锚点,默认随卷积核变化
normalize:布尔类型默认为True;True:a为1/W*H(均值滤波),false:a=1
borderType:有映射类型,加一个黑边,默认不设置
import cv2 import numpy as np img = cv2.imread('./image/lena.jpg') # 方盒滤波(当为True时)变成均值滤波,当为False时,就只加和不变化,超过255的结果设置为255 img2 = cv2.boxFilter(img, -1, (5, 5), normalize=True) img3 = cv2.boxFilter(img, -1, (5, 5), normalize=False) # 展示图像 cv2.imshow('img', img) cv2.imshow('img2', img2) cv2.imshow('img3', img3) cv2.waitKey(0)
blur()
方盒滤波的参数为True时,就是均值滤波,所以这个API用的不多。
dst = cv2.blur(scr, ksize, anchor, borderType)
scr:源图像
kernel:卷积核大小(x,y)
anchor:锚点
borderType:有映射类型,加一个黑边,默认不设置
3.2 高斯滤波(高斯噪音)
适用于有高斯噪点的图片
dst = cv2.GaussianBlur(img, ksize, sigmaX, sigmaY, …)
img:输入的图像
ksize:卷积核大小
sigmaX:表示高斯核函数在X方向的的标准偏差。
sigmaY:表示高斯核函数在Y方向的的标准偏差。
一般只需要看前三个参数
import cv2 import numpy as np img = cv2.imread('./image/Gaussian.png') # 高斯去噪 img2 = cv2.GaussianBlur(img, (3, 3), 0) # 展示图像 cv2.imshow('img', img) cv2.imshow('img2', img2) cv2.waitKey(0)
3.3 中值滤波(胡椒噪音)
对胡椒噪音去噪明显,取中间的值作为卷积结果
dst = cv2.medianBlur(img, ksize)
img:输入图像
ksize:卷积核大小一个数字
import cv2 import numpy as np img = cv2.imread('./image/median.png') # 胡椒噪声 img2 = cv2.medianBlur(img, 5) # 展示图像 cv2.imshow('img', img) cv2.imshow('img2', img2) cv2.waitKey(0)
3.4 双边滤波
双边滤波的主要应用场景是视频美颜
cv2.bilateralFilter(img, d, sigmaColor, sigmaSpace, …)
img:输入图像
d:直径,与卷积核中心点的距离,一般取5
sigmaColor:颜色空间滤波器的sigma值。这个参数的值越大,就表明该像素邻域内有更宽广的颜色会被混合到一起,产生较大的半相等颜色区域。
sigmaSpace:sigmaSpace坐标空间中滤波器的sigma值,坐标空间的标注方差。他的数值越大,意味着越远的像素会相互影响,从而使更大的区域足够相似的颜色获取相同的颜色。当d>0,d指定了邻域大小且与sigmaSpace无关。否则,d正比于sigmaSpace。
双边滤波的作用::图像去噪保边,对相关分析的结果有较大的影响,对于裂缝比较强,噪声比较少的图像来说,可以将去噪的程度放大,对以后的相关分析的结果就会有更少的噪声。对于噪声不是很集中的图像,并有较多细节的图像,增加保边的效果,让相关分析及后续进行进一步的结构处理,去噪。
import cv2 import numpy as np img = cv2.imread('./image/lena.jpg') # 双边滤波 img2 = cv2.bilateralFilter(img, 5, 20, 50) # 展示图像 cv2.imshow('img', img) cv2.imshow('img2', img2) cv2.waitKey(0)
4. 高通滤波器
允许高于某个值的通过而阻断低于该值的滤波器。主要是有保留边缘的功能。常见的高通滤波器有Sobel(索贝尔)、Scharr(沙尔)、Laplacian(拉普拉斯)。
4.1Sobel(索贝尔)(高斯)
只能一次在x方向上或者y方向上求导,然后把结果相加。
dst1 = cv2.Sobel(src, ddepth, dx, dy, ksize = 3, scale = 1, delta = 0, borderType = BORDER_DEFAULT )
src:输入原图像
ddepth:位深,默认为-1
dx,dy:只能选择一个方向上要么0、1,要么1、0
ksize:卷积核大小,默认为3,当-1时为沙尔
scale:缩放大小,一般就用默认值
delta:偏移量,一般就用默认值
borderType:边界扩充类型,一般就用默认值
可以改变卷积核大小
import cv2 import numpy as np img = cv2.imread('./image/lena.jpg') # 索贝尔 dx = cv2.Sobel(img, -1, 1, 0, ksize=3) dy = cv2.Sobel(img, -1, 0, 1, ksize=3) # dst = dx+dy dst = cv2.add(dx,dy) # 展示图像 cv2.imshow('img', img) cv2.imshow('dx', dx) cv2.imshow('dy', dy) cv2.imshow('dst', dst) cv2.waitKey(0)
一幅图的边缘被很好的分割出来。
4.2 Scharr(沙尔)
与Sobel类似,只不过使用的ksize值不同,Scharr不能改变卷积核的大小,只能是3*3的。同样只能求一个方向上的边缘。
cv2.Scharr(src, ddepth, dx, dy, scale = 1, delta = 0, borderType = BORDER_DEFAULT).
src:输入原图像
ddepth:位深,默认为-1
dx,dy:只能选择一个方向上要么0、1,要么1、0
scale:缩放大小,一般就用默认值
delta:偏移量,一般就用默认值
borderType:边界扩充类型,一般就用默认值
import cv2 import numpy as np img = cv2.imread('./image/lena.jpg') # # 索贝尔,当ksize=-1时,就是沙尔 # dx = cv2.Sobel(img, -1, 1, 0, ksize=-1) # dy = cv2.Sobel(img, -1, 0, 1, ksize=-1) dx = cv2.Scharr(img, -1, 1, 0) dy = cv2.Scharr(img, -1, 0, 1) # dst = dx+dy dst = cv2.add(dx,dy) # 展示图像 cv2.imshow('img', img) cv2.imshow('dx', dx) cv2.imshow('dy', dy) cv2.imshow('dst', dst) cv2.waitKey(0)
4.3 Laplacian(拉普拉斯)
Laplacian可以同时求两个方向上的边缘,但是对噪音比较敏感,一般需要先进行去噪再调用Laplacian。
dst = cv2.Laplacian(src, ddepth, ksize = 1 ,scale = 1, borderType = BORDER_DEFAULT)
src:输入原图像
ddepth:位深,默认为-1
ksize:卷积核大小,默认为1
scale:缩放大小,一般就用默认值
delta:偏移量,一般就用默认值
borderType:边界扩充类型,一般就用默认值
卷积核大小为5*5的结果
import cv2 import numpy as np img = cv2.imread('./image/lena.jpg') # # 索贝尔,当ksize=-1时,就是沙尔 # dx = cv2.Sobel(img, -1, 1, 0, ksize=-1) # dy = cv2.Sobel(img, -1, 0, 1, ksize=-1) # dx = cv2.Scharr(img, -1, 1, 0) # dy = cv2.Scharr(img, -1, 0, 1) dst = cv2.Laplacian(img, -1, ksize = 5) # dst = dx+dy # dst = cv2.add(dx,dy) # 展示图像 cv2.imshow('img', img) # cv2.imshow('dx', dx) # cv2.imshow('dy', dy) cv2.imshow('dst', dst) cv2.waitKey(0)
4.4 Canny
使用5*5高斯滤波消除噪声,可以计算图像的四个方向上的边缘(0,45,90,135),取局部的最大值,多了一个阈值计算。高于阈值我们认为是边缘,低于阈值就不是边缘,显然A为边缘,如果,但是B和C介于最大值最小值之间,BC既不是边缘也是边缘,但是C与A在一条直线上,所以C也是边缘。
dst = cv2.Canny(img, minVal, maxVal)
img:原图像
minVal:最小阈值
maxVal:最大阈值
低于最小阈值就不是边缘,高于最大阈值是边缘。
import cv2 import numpy as np img = cv2.imread('./image/lena.jpg') # canny dst = cv2.Canny(img, 100, 200) cv2.imshow('img',img) cv2.imshow('dst',dst) cv2.waitKey(0)
以上就是关于滤波器的基本介绍,详细信息还需读者去自己学习,大家有问题欢迎在评论区讨论。