文章目录
- 滤波
- 滤波实例
- 1. 均值滤波
- 2. 方框滤波
- 设置normalize为0
- 设置normalize为1
- 3. 高斯滤波
- 高通滤波的使用
- 4. 中值滤波
- 5. 双边滤波
- 6. 2D卷积(自定义滤波)
滤波
由于可能会有中值这种操作,所以滑窗或者说卷积的大小一般是奇数。
大致有以下几种滤波:
- 均值滤波;
- 方框滤波;
- 高斯滤波;
- 中值滤波;
- 双边滤波;
- 2D卷积(自定义滤波)
均值滤波 | 方框滤波 | |
函数说明 | def blur(src, ksize, dst=None, anchor=None, borderType=None, /) -> dst | def boxFilter(src, ddepth, ksize, dst=None, anchor=None, normalize=None, borderType=None, /) -> dst |
函数使用 | r=cv2.blur(o,(5,5)) | r=cv2.boxFilter(o,-1,(5,5)) |
ddepth为-1表示与原图像使用同样的深度 ddepth表示处理图像的深度 normalize表示是否使用归一化,归一化的话就和均值滤波一样了 |
滤波实例
1. 均值滤波
设置核大小即可,因为均值主要是对滑动的窗口求均值def blur(src, ksize, dst=None, anchor=None, borderType=None, /) -> dst
,对应到实际使用r=cv2.blur(o,(5,5))
- 将矩阵结果保存到excel中
#导入库文件
import cv2
import pandas as pd
o=cv2.imread("image\\lenaNoise.png",cv2.IMREAD_GRAYSCALE)
#——将读取之后的图片数据保存进文件中
dataframe = pd.DataFrame(data=o)
dataframe.to_excel("文件.xlsx",index=False,header=False)
print("*"*100)
#使用均值滤波
r=cv2.blur(o,(5,5))#实现均值滤波
#获取均值滤波之后的数据,将其保存进excel
dataframe2 = pd.DataFrame(data=r)
dataframe2.to_excel("文件2.xlsx",index=False,header=False)
#显示原始以及滤波之后的图片
cv2.imshow("original",o)
cv2.imshow("result",r)
#销毁相关数据
cv2.waitKey()
cv2.destroyAllWindows()
2. 方框滤波
在方框滤波中,可以自由选择是否对均值滤波的结果进行归一化,即可以自由选择滤波结果是邻域像素值之和的平均值,还是邻域像素值之和。
对应到参数上的不同就是normalize是0还是1,是1表示需要进行归一化,是0表示不需要进行归一化。
设置normalize为0
import cv2
o=cv2.imread("image\\lenaNoise.png")
r=cv2.boxFilter(o,-1,(5,5))
cv2.imshow("original",o)
cv2.imshow("result",r)
cv2.waitKey()
cv2.destroyAllWindows()
设置normalize为1
如果将归一化参数normalize
设置为0,也就是不进行求平均值,那么很有可能就会超过255的值,整个就会变成纯白,如果如下图所示,result变成看纯白
3. 高斯滤波
高斯滤波里面的值是按照正态分布的,
def GaussianBlur(src, ksize, sigmaX, dst=None, sigmaY=None, borderType=None, /) -> dst
在调用高斯滤波函数的时候,我们可以看到实际调用的函数是cv2.getGaussianKernel(ksize, sigma, ktype=None)
:
这个虽然是二维卷积,但是其实是通过一维卷积进行实现,分别在X以及Y方向上进行卷积,其卷积核如下(并且在边缘会有默认的padding操作):
所以其位置的公式计算
这个位置计算
带入公式 | -1 | 0 | 1 | |
坐标位置 | 1 | 2 | 3 | |
计算 | 0-(3-1)/2 | 1-(3-1)/2 | 2-(3-1)/2 | i-(ksize-1)/2 |
这些坐标位置就可以直接带入正态分布(也可以叫做高通分布)中去:
并且换个角度去看,先进行X滤波,再进行Y滤波,就等于下面的滤波器,然后代入到二维正态分布:
高通滤波的使用
函数定义:def GaussianBlur(src, ksize, sigmaX, dst=None, sigmaY=None, borderType=None, /) -> dst
实际调用:r=cv2.GaussianBlur(o,(3,3),0,0)
代码使用:
import cv2
a=cv2.getGaussianKernel(3, 1)
print(a)
o=cv2.imread("image\\lenaNoise.png")
o=cv2.resize(o, (5,5))
r=cv2.GaussianBlur(o,(3,3),0,0)
cv2.imshow("original",o)
cv2.imshow("result",r)
cv2.waitKey()
cv2.destroyAllWindows()
cv2.getGaussianKernel(ksize, sigma, ktype=None)
4. 中值滤波
在一个滑窗范围内,首先进行排序,然后找到排在中间的那个数,将其替代这个位置的像素值
示例:
import cv2
o=cv2.imread("image\\lenaNoise.png")
r=cv2.medianBlur(o,3)
cv2.imshow("original",o)
cv2.imshow("result",r)
cv2.waitKey()
cv2.destroyAllWindows()
5. 双边滤波
由于前面的滤波方式容易在边缘发生模糊的情况,尤其突变的时候,而边缘信息正是突变的地方。尤其是均值滤波这种,将一个滤波范围内的像素就给平均了,于是反而都处于相近的像素,将原本的信息改变了
下面就是经过高斯处理之后的效果,会显得比较模糊:
给距离以及色彩增加权重的考虑,如下图所示,在计算左边区域的时候,给右边的权重少一点,其判断一句是左边的像素值明显比右边大很多,而计算右边的时候,就会将左边的权重给的小很多,其判断
由于参考了空间以及色彩的因素,所以需要有这两个差值的阈值。其函数定义如下:
def bilateralFilter(src, d, sigmaColor, sigmaSpace, dst=None, borderType=None, /) -> dst
- d是在滤波时选取的空间距离参数,这里表示以当前像素点为中心点的直径。推荐为5;
- sigmaColor是滤波处理时选取的颜色差值范围,该值决定了周围哪些像素点能够参与到滤波中来。为255表示指定直径所有的点都可以参与运算。
-
sigmaSpace
是坐标空间中的sigma值。它的值越大,说明有越多的点能够参与到滤波计算中来。当d>0时,无论sigmaSpace的值如何,d都指定邻域大小;否则,d与sigmaSpace的值成比例,也就是淋雨大小通过sigmaSpace计算;
查看滤波效果:
import cv2
o=cv2.imread("image\\lenaNoise.png")
r=cv2.bilateralFilter(o,25,100,100)
cv2.imshow("original",o)
cv2.imshow("result",r)
cv2.waitKey()
cv2.destroyAllWindows()
如果将滤波设计很大:
import cv2
o=cv2.imread("image\\bilTest.bmp")
g=r=cv2.GaussianBlur(o,(55,55),0,0)
b=cv2.bilateralFilter(o,55,100,100)
cv2.imshow("original",o)
cv2.imshow("Gaussian",g)
cv2.imshow("bilateral",b)
cv2.waitKey()
cv2.destroyAllWindows()
双边滤波一般只能比较好进行低频的滤波,常见的就是边缘了。
6. 2D卷积(自定义滤波)
def filter2D(src, ddepth, kernel, dst=None, anchor=None, delta=None, borderType=None, /) -> dst
- ddepth表示图像的深度,如果为-1就表示和原图像一样的深度;
- kernel:为自定义的卷积核
import cv2
import numpy as np
o=cv2.imread("image\\lena.bmp")
kernel = np.ones((9,9),np.float32)/81
r = cv2.filter2D(o,-1,kernel)
cv2.imshow("original",o)
cv2.imshow("Gaussian",r)
cv2.waitKey()
cv2.destroyAllWindows()