一、图像滤波
1、滤波的定义
作用:一幅图像经过滤波器得到另一幅图像;原始图像和小矩阵的乘积
其中滤波器也称为卷积核,滤波的过程称为卷积;
卷积核的大小:一般为奇数,3*3,也有5*5、7*7;为什么是奇数呢?一方面是因为padding的原因,为了输出的大小和输入保存一致;另一方面是由于锚点的原因,防止位置发生偏移;具体可以看网上资料;
卷积核越大,看到的信息越多,提取的特征越好,同时计算量越大;
锚点:卷积核的正中心就是锚点,为了防止信息的偏差;
边界扩充,卷积的结果一般比输入小,这时候我们就要用到边界扩充,使输入输出大小相等。比如5*5的原图边界扩充成7*7的然后和3*3的卷积核相乘输出5*5的图片。
步长:跨多大距离进行卷积操作;如下图表示步长为2时的卷积操作(一般为1)
以上计算公式如下:
2、低通滤波
低通滤波:波低于某一阈值可以通过,效果是去除噪音或平滑图像,比如磨皮特效
高通滤波:波高于某一阈值可以通过,效果是可以帮助查找图像的边缘。
(1)filter2D(src , ddepth, kernel, anchor, delta, borderType)
图像卷积的API
ddepth卷积之后图像的位深,一般设置为-1(表示和原图位深一样)
kernel卷积核:选择使用的卷积核。
anchor锚点,选择卷积核的中心点。默认是-1(根据你核的内容来找中心点)
delta滤波后加一个δ值,一般默认为0
borderType边界的类型,一般不做设置;前三个是关键。
简单的使用API均值滤波例子:
import cv2
import numpy as np
img = cv2.imread("F:\\tupian\\chinacar.jpeg")
kernel = np.ones((5,5),np.float32)/25
dst = cv2.filter2D(img, -1, kernel)
cv2.imshow('dst',dst)
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
(2)方盒滤波
其中a的参数如下,当normakiz=true时,方盒滤波等于均值滤波:
方盒滤波API:boxFilter( src , ddepth, ksize, anchor, normalize, borderType)
均值滤波API:blur( src, ksize , anchor, borderType )
import cv2
import numpy as np
img = cv2.imread("F:\\tupian\\chinacar.jpeg")
# kernel = np.ones((5,5),np.float32)/25
# dst = cv2.filter2D(img, -1, kernel)
dst = cv2.blur(img, (5,5))
cv2.imshow('dst',dst)
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
(3)高斯滤波
高斯滤波的特征时中间高两边低,其卷积核中间比重高,边缘比重低:高斯滤波主要解决高斯噪点;
高斯滤波API:GaussianBlur(img, ksize, sigmaX, sigmaY,....)
其中sigmaX和sigmaY时x和y到中心的延展或者到中心的误差;
(4)中值滤波
中值滤波的定义,假如有一个数组【1556789】,取其中的中间值6作为卷积的结果;
中值滤波可以对胡椒噪音有很好的效果
中值滤波API:medianBlur(img, ksize) ![](https://i-blog.csdnimg.cn/blog_migrate/974dcc85d13af145f97f7ad5d963c3cc.png)
(5)双边滤波
双边滤波的定义:可以保留边缘;同时可以对边缘内的区域进行平滑处理;简而言之就是美颜功能;
双边滤波API:bilateralFilter(img , d, sigmaColor, sigmaSpace, ....)
d:过滤期间使用的每个像素邻域的直径。如果它是非正的,则从sigmaSpace计算。
另外两个可以看手册;
import cv2
import numpy as np
img = cv2.imread("F:\\tupian\\lena.jpeg")
# kernel = np.ones((5,5),np.float32)/25
# dst = cv2.filter2D(img, -1, kernel)
# dst = cv2.blur(img, (5,5))
# dst = cv2.GaussianBlur(img , (5,5), sigmaX=1,)
# dst = cv2.medianBlur(img, 5)
dst = cv2.bilateralFilter(img , 7, 20, 50)
cv2.imshow('dst',dst)
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
3、高通滤波
Sobel高通滤波(索贝尔)(高斯)和Scharr(沙尔)时常见的两种高通滤波,一般可以使用索贝尔API代替沙尔,laplacian(拉普拉斯)也是常见高通滤波。
(1)Sobel算子
通过先求X方向求导(边缘);然后再向在Y轴方向求导(边缘),最终:
索贝尔API:Sobel(src , ddepth, dx ,dy, ksize= 3, ....)
当ksize=-1时相当于沙尔算子;如果直接求两个方向的边缘结果不理想;所以我们采用两个方向分别求边缘最后相加结果的方法。
import cv2
import numpy as np
img = cv2.imread("F:\\tupian\\chess.jpeg")
#y方向边缘
d1 = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=5)
#x方向的边缘
d2 = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=5)
#合并dst和dst2
# dst = d1 + d2
dst = cv2.add(d1,d2 )
cv2.imshow('img',img)
cv2.imshow('d1',d1)
cv2.imshow('d2',d2)
cv2.imshow('dst',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
(2)Scharr算子
与Sobel类似,只不过使用的kernel值不同;Scharr只能求X方向或Y方向的边缘,
Scharr算子API:Scharr(src , ddepth , dx ,dy, .....)
(3)laplacian(拉普拉斯)算子
可以同时求两个方向的边缘;对噪音比较敏感, 一般需要先进行去噪再调用拉普拉斯;
laplacian(拉普拉斯)算子API:Laplacian(img, ddepth, ksize , ....)
(4)Canny
Canny称为边缘检测的终极大法,比前三种高通滤波更加简单,细节化;
首先使用5*5的高斯滤波消除噪声;再计算图像梯度方向(0/45/90/135°)四个方向进行;
再在四个方向上取局部最大值;阈值计算。
Canny的API:Canny(img, minVal, maxVal,......)
import cv2
import numpy as np
img = cv2.imread("F:\\tupian\\lena.jpeg")
dst = cv2.Canny(img, 100,200)
dst2 = cv2.Canny(img, 50,220)
dst3 = cv2.Canny(img, 150,151)
cv2.imshow('img',img)
cv2.imshow('dst',dst)
cv2.imshow('dst2',dst2)
cv2.imshow('dst3',dst3)
cv2.waitKey(0)
cv2.destroyAllWindows()