系列所有代码,复制粘贴即可运行。
希望有能力的朋友还是拿C++运行一下。
本节讨论图像的低通滤波(卷积,方盒,中值双边,高斯),高通滤波(Sobel,Scharr,Laplace,canny)
用卷积核对每个像素做线性运算,最终得到的小图像称作convolved Feature卷积特征
步长:卷积核扫描一次移动的像素单位
padding: 对图像做卷积之后,长宽都会变小,padding就是在外围补充0的圈数,结构上类似于HTML中的padding,可以通过公式计算出需要填充0的圈数
卷积核的大小一般都是奇数,padding不好补,另外这种卷积核有中心
卷积核案例:
cv2.filter2D
import cv2
import numpy as np
cat = cv2.imread('cat.jpeg')
#均为1 每个点都被周围25个平均 变模糊 必须是float型
#模糊卷积核
#kernel = np.ones((5,5), np.float32) /25
#轮廓卷积核
#kernel = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]])
#浮雕卷积核
kernel = np.array([[0, -1, -1], [1, 0, -1], [1, 1, 0]])
#锐化卷积核
#kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])
#-1 与原图数据类型一致
dst = cv2.filter2D(cat, -1, kernel)
cv2.imshow('cat', np.vstack((cat, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
滤波实际是去除噪点变模糊的过程,方盒滤波,卷积核内数值全为1,卷积核外乘一系数a。
cat = cv2.imread('cat.jpeg')
#方盒滤波 指定normalize
#dst = cv2.boxFilter(cat, -1, (5,5), normalize=True)
#均值滤波,没有参数位深和normalize
dst = cv2.blur(cat, (5,5))
符合正态分布的概率密度函数,md高斯分布二维的数学公式:
G ( x , y ) = 1 2 π σ 2 e − x 2 + y 2 2 σ 2 G(x,y) = \frac{1}{2 \pi \sigma^2}e^{-\frac{x^2+y^2}{2\sigma ^2}} G(x,y)=2πσ21e−2σ2x2+y2
高斯滤波就是用符合高斯分布的卷积核对图片进行卷积操作,重点是计算该卷积核(高斯模板)
例3X3卷积核,中间为x,y,上为x,y+1 左为x-1, y(其中x=0, y=0,因为在高斯中心)
**归一化:**通过高斯函数算出来的值,还要保证加起来值为1,需要除以它们的和,才是最终的高斯模板
有些高斯模板归一化的方法是,卷积核内的值均除以左上角的值,然后取整
GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType]]])
dst = cv2.GaussianBlur(cat, (5,5), sigmaX=10)
适合胡椒噪音/椒盐噪声的去除,假设有一个数组,取中位数作为卷积之后的结果即可。
#这里的ksize确是一个数字
dst = cv2.medianBlur(cat,5)
可实现美颜,磨皮效果,是考虑了灰度距离和空间距离的两个高斯函数相乘,保留边缘信息。
dst = cv2.bilateralFilter(cat, 7, sigmaColor=20, sigmaSpace=50)
用来找边界,特征提取,对象检测,模式识别等
边缘:像素值发生跃迁的地方。
#X方向 获取垂直边缘
#Sobel要分别计算x,y的梯度
#dx = cv2.Sobel(cat, cv2.CV_64F, 1, 0, ksize=3)
dx = cv2.Sobel(cat, -1, dx=1, dy=0, ksize=3)
#dy = cv2.Sobel(cat, cv2.CV_64F, 0, 1, ksize=3)
dy = cv2.Sobel(cat, -1, dx=0, dy=1, ksize=3)
#dx只有垂直的边缘
#dy只有水平的边缘轮廓
dst = cv2.add(dx, dy)
cv2.imshow('cat_ori', cat)
cv2.imshow('cat_merge', dst)
cv2.imshow('cat', np.vstack((dx, dy)))
dx = cv2.Scharr(cat, -1, 1, 0)
dy = cv2.Scharr(cat, -1, 0, 1)
#dx只有垂直的边缘
#dy只有水平的边缘轮廓
dst = cv2.add(dx, dy)
cv2.imshow('cat_ori', cat)
cv2.imshow('cat_merge', dst)
cv2.imshow('cat', np.vstack((dx, dy)))
拉普拉斯算子是求二阶导,对于边缘变化的反应更加敏锐。有的无意义的地方数值为0,需要去噪
dst = cv2.Laplacian(cat, -1, ksize=3)
被人认为是最有边缘检测算法,多级边缘检测算法
#设定阈值大小,值小,边缘比较丰富
#值越大,边缘越少
dst = cv2.Canny(cat, 100, 200)
dst2 = cv2.Canny(cat, 64, 128)