08. 滤波(卷积、均值、高斯、中值、双边滤波)
滤波
1. 卷积滤波
filter2D(src, ddepth, kernel, dst[, anchor[, delta[, borderType]]])
- ddepth是卷积之后图片的位深,即卷积之后图片的数据类型,一般设为-1,表示和原图类型一致;
- kernel是卷积核大小,用元组或ndarray表示,要求数据类型必须是float(np.float32)
- anchor锚点,即卷积核的中心点,可选参数,默认是(-1, -1)
- delta可选参数,表示卷积之后额外加的一个值,相当于线性方程中的偏差,默认是0
- borderType边界类型,一般不设
import cv2
import cv2 as cv
import numpy as np
# 卷积
bg = cv.imread('./images/dog.jpg')
cv.namedWindow('image', cv.WINDOW_NORMAL)
cv.resizeWindow('image', 800, 300)
# kernel必须是float型,这种卷积核是轮廓,这里将8改为9得到的效果就会保留背景
kernel = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]], dtype=np.float32)
# kernel = np.ones((5, 5), np.float32) / 25 # 这种卷积核就是模糊效果
# ddepth=-1表示图片的数据类型不变,这里有一个参数dst不设置的话,输出和输入的维度就是相同的
bg2 = cv2.filter2D(bg, -1, kernel)
cv.imshow('image', np.hstack((bg, bg2)))
print(bg.shape)
print(bg2.shape)
cv.waitKey(0)
cv.destroyAllWindows()
2. 方盒滤波与均值滤波
boxFilter(src, ddepth, ksize[, dst[, anchor[, normalize[, borderType]]]]
方盒滤波
- 方盒滤波的卷积核是固定的 a * np.ones(num * num)
- normalize=True时,a=1/(W*H)滤波器的宽高
- normalize=False时,a=1
- 一般情况下,我们都使用normalize=True的情况,这时,方盒滤波等价于 均值滤波
- 在代码的时候,不需要创建卷积核,只需要告诉方盒滤波,卷积核的大小是多少,如ksize=(5, 5)
blur(src, ksize[, dst[, anchor[, borderType]]])
均值滤波
3. 高斯滤波
GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType]]])
高斯滤波
- ksize 高斯核的大小,示例(5, 5)
- sigmaY, Y轴的标准差,默认为0,这是sigmaY = sigmaX
- 如果没有指定xigma值,会分别冲ksize的宽度核高度中计算sigma;
选择不同的sigma值会得到不同的平滑效果,sigma越大,平滑效果越明显。高斯滤波最常用的用法是去噪;但是会让图片变得模糊;
4. 中值滤波
中值滤波原理,假设有一个数组, 取该数组中间值(即中位数)作为卷积后的结果值,中值滤波对胡椒噪音(椒盐噪音)效果明显
import cv2
import numpy as np
img = cv2.imread('./papper.png')
# 注意:这里的ksize是一个数字
dst = cv2.medianBlur(img, 5)
cv2.imshow('image', np.hstack(img, dst))
cv2.waitKey()
cv2.destroyAllWindows()
5. 双边滤波
双边滤波对于图像的边缘信息能够更好的保存,其原理为一个与空间距离相关的高斯函数与一个灰度距离相关的高斯函数相乘。美颜、磨皮效果;双边滤波对椒盐噪声基本没效果
bilateralFilter(src, d, sigmaColor, sigmaSpace[, dst[, borderType]])
双边滤波
- sigmaColor 是计算像素信息使用的sigma
- sigmaSpace 是计算空间信息使用的sigma
- d 是kernel的大小,是一个数字,一般卷积核大一点好,d=7表示(7, 7)
img_new = cv2.bilateralFilter(img, 7, sigmaColor=10, sigmaSpace=20)