文章目录
所有相关接口验证demo以上传至仓库
代码地址:https://gitee.com/norep/learn-opencv
卷积
图像卷积
图像卷积是计算机视觉和图像处理中的一种基本技术,它通过将一个小的、固定大小的核(或滤波器)与图像进行重叠,并逐像素地相乘,然后将结果求和,来提取图像中的特征。
图像卷积就是卷积核在图像上按照滑动遍历像素时不断的相乘求和的过程。
图像卷积的常见应用:
-
边缘检测:使用如 Sobel 滤波器或 Canny 边缘检测器来识别图像中的边缘。
-
模糊和锐化:通过使用高斯滤波器来模糊图像,或者使用锐化滤波器来增强图像的细节。
-
特征提取:如使用 Haar 特征、SIFT(尺度不变特征变换)、SURF(加速稳健特征)等方法来提取图像的显著特征。
-
图像去噪:通过使用均值滤波器或中值滤波器来减少图像中的噪声。
卷积步长
步长就是卷积核在图像上移动的步幅,上面的图片中,卷积核的步长为1,每次移动一个像素进行卷积。
当步长为2时,扫描图像的结果如下图
为了充分扫描图片,一般步长为1
卷积填充(padding)
卷积操作会使图片尺寸变小,为了使图片尺寸不变,需要在图片周围填充0。
padding就是指填充0的圈数。
计算需要填充的圈数
输入体积大小:H1 x W1 x D1 (图片高度 x 宽度 x 通道数)
卷积参数:
卷积核数量:K
卷积核大小:F
卷积步长:S
零填充大小:P
输出大小:H2 x W2 x D2
H2 = (H1 - F + 2P) / S + 1
W2 = (W1 - F + 2P) / S + 1
D2 = K
如果要保持卷积后图片大小不变,计算公式为
P = (F - 1) / 2
常用卷积核
卷积核大小 | 长宽缩减 | 维持原尺寸padding数量 |
---|---|---|
3x3卷积核 | 减少2像素 | 1 |
5x5卷积核 | 减少4像素 | 2 |
7x7卷积核 | 减少6像素 | 3 |
创建卷积核
不同的卷积核具有不同的图像处理效果,比如图像的平滑、锐化、边缘检测等
卷积核必须为float32类型
# 创建5x5的全为1的卷积核,常用于均值滤波
kernel = np.ones((5, 5), np.float32) / 25
#创建3x3的卷积核,指定卷积核的大小与权重,比如Sober滤波器,用于边缘检测
kernel_x = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]], dtype=np.float32)
kernel_y = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]], dtype=np.float32)
低通滤波
低通滤波器允许低频信号(如图像的缓慢变化)通过,同时抑制高频信号(如图像的细节和噪声)。常见的方法包括高斯滤波、均值滤波和中值滤波。
低通滤波可以平滑图像,减少噪声,但可能会使图像变得模糊,因为高频细节被抑制了。
适用于图像去噪、模糊和预处理,特别是在需要减少细节以增强特定特征时。
二维滤波: filter2D
这个函数可以实现图像卷积,即用一个核(或滤波器)与图像进行逐像素的乘法操作,并将结果相加,从而实现图像的平滑、锐化、边缘检测等效果。
dst = cv2.filter2D(src, ddepth, kernel, dst=None, anchor=None, delta=0, borderType=cv2.BORDER_DEFAULT)
# img = cv2.filter2D(pic1, -1, kernel)
参数说明:
-
src:一个 NumPy 数组,表示要进行滤波的源图像。
-
ddepth:一个整数,表示输出图像的深度。这个值通常设置为 -1,表示输出图像的深度与源图像相同。
-
kernel:一个二维 NumPy 数组,表示滤波核或滤波器。这个核的大小应该是 (kH, kW),其中 kH 和 kW 是核的行数和列数。
-
dst:一个可选的 NumPy 数组,用于存储滤波后的图像。如果提供了这个参数,函数将返回 dst 而不是创建一个新数组。
-
anchor:一个可选的元组 (x, y),表示核的中心点。如果未指定,默认中心点位于核的中心。
-
delta:一个可选的浮点数,表示滤波操作的偏移量。这个值通常设置为 0。
-
borderType:一个整数,表示边界类型。常见的边界类型包括 cv2.BORDER_CONSTANT、cv2.BORDER_REPLICATE 等。
返回值:
- 如果指定了 dst 参数,函数将返回 dst 数组;否则,函数将返回滤波后的图像数组。
使用卷积核完成均值滤波
#!/bin/env python
import cv2
import numpy as np
pic_path = "../resource/pic/img_003.jpg"
windowName = pic_path
pic1 = cv2.imread(pic_path)
pic1_h, pic1_w, pic1_chn = pic1.shape
# 创建卷积核
kernel = np.ones((5, 5), np.float32) / 25
# 对图片卷积操作
img = cv2.filter2D(pic1, -1, kernel)
cv2.namedWindow(windowName, cv2.WINDOW_NORMAL)
cv2.resizeWindow(windowName, pic1_w * 3 * 2, pic1_h * 3)
cv2.imshow(windowName, np.hstack((pic1, img)))
while True:
if cv2.waitKey(0) == ord('q'):
break
print('销毁窗口')
cv2.destroyAllWindows()
均值滤波: blur
OpenCV中有专用的均值滤波的API,无需手动创建均值滤波的卷积核。用于对图像进行模糊处理。卷积核越大,越模糊。
dst = cv2.blur(src, ksize, sigmaX, sigmaY, borderType)
# img2 = cv2.blur(pic1, (5, 5))
参数说明:
-
src:一个 NumPy 数组,表示要进行模糊处理的源图像。
-
ksize:一个元组 (ksize_x, ksize_y) 或一个整数,表示模糊核的大小。如果 ksize 是一个整数,那么核在 x 和 y 方向上都是方形的,大小为 ksize x ksize。
-
sigmaX 和 sigmaY:两个可选的浮点数,分别表示核在 x 和 y 方向上的标准差。如果指定了这两个参数,它们将覆盖 ksize 参数。
-
borderType:一个整数,表示边界类型。常见的边界类型包括 cv2.BORDER_CONSTANT、cv2.BORDER_REPLICATE 等。
返回值:
- dst:一个 NumPy 数组,表示模糊处理后的结果图像。
高斯滤波: GaussianBlur
高斯滤波就是使用符合高斯分布的卷积核对图片进行卷积操作,所以高斯滤波的重点就是计算符合高斯分布的卷积核,即高斯模板。
假定中心点的坐标是(0,0),那么取距离他最近的8个点的坐标,设定Sigma的值为1.5,则模糊半径为1像素的高斯模板如下。
高斯函数数学原理
高斯函数是在符合高斯分布的数据的概率密度函数。高斯分布又叫正态分布。
如上图中,mean为均值,sigma^2为方差, 高斯函数在均值mean时的概率最高,sigma^2越小,数据越靠近均值mean附近,反之数据越离散。
一维高斯分布
二维高斯分布
高斯滤波API
dst = cv2.GaussianBlur(src, ksize, sigmaX, sigmaY, borderType)
# img3 = cv2.GaussianBlur(pic1, (5, 5), sigmaX=1.5)
参数说明:
-
src:一个 NumPy 数组,表示要进行高斯模糊处理的源图像。
-
ksize:一个元组 (ksize_x, ksize_y) 或一个整数,表示模糊核的大小。如果 ksize 是一个整数,那么核在 x 和 y 方向上都是方形的,大小为 ksize x ksize。
-
sigmaX:表示核在 x方向上的标准差,如果没有指定sigma值,则会分别从ksize的长宽中计算sigma。
-
sigmaY:可选的浮点数,表示核在 y方向上的标准差,默认为0,这是sigmaY = sigmaX。
-
borderType:可选的一个整数,表示边界类型。常见的边界类型包括 cv2.BORDER_CONSTANT、cv2.BORDER_REPLICATE 等。
返回值:
- dst:一个 NumPy 数组,表示高斯模糊处理后的结果图像。
注意:不同的sigma值会得到不同的平滑效果。sigma越大平滑效果越明显
中值滤波: medianBlur
用于对图像进行中值模糊处理。这个函数通过用一个固定大小的高斯核替换每个像素值,来减少图像中的噪声,特别是椒盐噪声。
dst = cv2.medianBlur(src, ksize)
# img4 = cv2.medianBlur(pic1, 5)
参数说明:
-
src:一个 NumPy 数组,表示要进行中值模糊处理的源图像。
-
ksize:一个整数,表示中值模糊核的大小。核的大小必须是奇数,通常在 3 到 7 之间。
返回值:
- dst:一个 NumPy 数组,表示中值模糊处理后的结果图像。
双边滤波: bilateralFilter
对于图像的边缘信息能够更好的保留,在去噪的同时能够保持边缘的清晰度,因为它同时考虑了空间邻近度和像素值相似度,原理为一个与空间距离相关的高斯函数与一个灰度距离相关的高斯函数相乘。
双边滤波能够保留边缘,同时对边缘内的区域进行平滑处理。
dst = cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace, borderType)
# img4 = cv2.bilateralFilter(pic1, 5)
参数说明:
-
src:一个 NumPy 数组,表示要进行双边滤波的源图像。
-
d:一个整数,表示滤波核的大小,一般设置为5,9, 11等。
-
sigmaColor:一个浮点数,表示颜色空间滤波的标准差。这个值决定了像素值相似度的范围。
-
sigmaSpace:一个浮点数,表示空间滤波的标准差。这个值决定了空间邻近度的范围。
-
borderType:一个可选的整数,表示边界类型。常见的边界类型包括 cv2.BORDER_CONSTANT、cv2.BORDER_REPLICATE 等。
返回值:
- dst:一个 NumPy 数组,表示双边滤波处理后的结果图像。
各滤波算法的特点与作用
算法 | 特点与作用 |
---|---|
均值滤波 | 平滑效果好,有效去除噪声,但会减少图像细节,适合去除小颗粒噪声 |
高斯滤波 | 平滑图像,减少噪声,同时保留边缘,适合消除细小的噪点,不适合椒盐噪声 |
中值滤波 | 有效去除椒盐噪声,对图像细节破坏小 |
双边滤波 | 既能去除噪声,又能保留边缘信息,对椒盐噪声无效,可用于美颜。 |