1 卷积
2 方盒滤波与均值滤波
3 高斯滤波
4 中值滤波
5 双边滤波
6 索贝尔(sobel)算子
7 沙尔(Scharr)算子
8 拉普拉斯算子
9 边缘检测Canny(重要)
1 卷积
1.1 什么是图片卷积
图像卷积就是卷积核在图像上按行滑动遍历像素时不断的相乘求和的过程
1.2 步长
**步长就是卷积核在图像上移动的步幅.**上面例子中卷积核每次移动一个像素步长的结果, 如果将这个步长修改为2, 结果会如何?
为了充分扫描图片, 步长一般设为1.
1.3 padding
从上面例子中我们发现, 卷积之后图片的长宽会变小. 如果要保持图片大小不变, 我们需要在图片周围填充0. padding指的就是填充的0的圈数.
我们可以通过公式计算出需要填充的0的圈数.
如果要保持卷积之后图片大小不变, 可以得出等式: ( N + 2 P − F + 1 ) = N (N + 2P - F + 1) = N (N+2P−F+1)=N从而可以推导出 P = F − 1 2 P = \frac{F -1}{2} P=2F−1
1.4 卷积核的大小
图片卷积中, 卷积核一般为奇数, 比如 3 * 3, 5 * 5, 7 * 7.为什么一般是奇数呢, 出于以下两个方面的考虑:
- 根据上面padding的计算公式, 如果要保持图片大小不变, 采用偶数卷积核的话, 比如4 * 4, 将会出现填充1.5圈零的情况.
- 奇数维度的过滤器有中心,便于指出过滤器的位置, 即OpenCV卷积中的锚点.
1.5 卷积案例
- filter2D(src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]])
- ddepth是卷积之后图片的位深, 即卷积之后图片的数据类型, 一般设为-1, 表示和原图类型一致.
- kernel是卷积核大小, 用元组或者ndarray表示, 要求数据类型必须是float型.
- anchor 锚点, 即卷积核的中心点, 是可选参数, 默认是(-1,-1)
- delta 可选参数, 表示卷积之后额外加的一个值, 相当于线性方程中的偏差, 默认是0.
- borderType 边界类型.一般不设.
import cv2
import numpy as np
img = cv2.imread('./dog.jpeg')
# 将彩色图像转换为灰度图像
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
# kernel是卷积核大小, 用元组或者ndarray表示, 要求数据类型必须是float型.
# 相当于原始图片中的每个点都被平均了一下, 所以图像变模糊了.
# kernel = np.ones((5, 5), np.float32) / 25
# 尝试其他的卷积操作,突出轮廓
# kernel = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]])
# 浮雕效果
# kernel = np.array([[-2, 1, 0], [-1, 1, -1], [0, 1, 2]])
# 锐化
kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])
# 卷积操作
# 使用自定义卷积核对灰度图像进行二维滤波
# gray_img 是输入的灰度图像
# -1 表示输出图像的深度与输入图像相同
# kernel 是自定义的卷积核,用于对图像进行滤波
# 该函数通过卷积操作应用滤波器,输出图像存储在 dst 变量中
dst = cv2.filter2D(gray_img, -1, kernel)
# 显示一幅并排展示的图像
# np.hstack((gray_img, dst)) 将 gray_img 和 dst 水平堆叠成一幅图像
# gray_img 是原始灰度图像,dst 是经过滤波处理后的图像
# 'img' 是窗口的名称
# cv2.imshow 用于显示图像,窗口中将并排显示原图和滤波后的图像
cv2.imshow('img', np.hstack((gray_img, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
2 方盒滤波与均值滤波
-
boxFilter(src, ddepth, ksize[, dst[, anchor[, normalize[, borderType]]]]) 方盒滤波.
-
方盒滤波的卷积核的形式如下:
-
normalize = True时, a = 1 / (W * H) 滤波器的宽高
-
normalize = False是. a = 1
-
一般情况我们都使用normalize = True的情况. 这时 方盒滤波 等价于 均值滤波
-
-
blur(src, ksize[, dst[, anchor[, borderType]]]) 均值滤波.
方盒滤波
# 方盒滤波
import cv2
import numpy as np
# 读取输入图像 'dog.jpeg'
# img 是读取的彩色图像(默认使用 BGR 色彩格式)
img = cv2.imread('./dog.jpeg')
# 使用方盒滤波对图像进行平滑处理
# cv2.boxFilter() 函数进行方盒滤波,不需要手动创建卷积核
# -1 表示输出图像的深度与输入图像相同
# (5, 5) 是方盒滤波的卷积核大小(5x5 的核)
# normalize=True 表示进行归一化处理(卷积核的每个元素都除以核的元素总数,使得滤波的结果平均化)
dst = cv2.boxFilter(img, -1, (5, 5), normalize=True)
# 使用 np.hstack() 将原始图像和经过方盒滤波处理的图像在水平方向上并排拼接
# 并通过 cv2.imshow() 显示拼接后的图像
# 'img' 是显示窗口的名称
cv2.imshow('img', np.hstack((img, dst)))
# 等待用户按任意键继续,0 表示无限等待
cv2.waitKey(0)
# 销毁所有窗口,释放资源
cv2.destroyAllWindows()
均值滤波
# 均值滤波
import cv2
import numpy as np
# 读取输入图像 'dog.jpeg'
# img 是读取的彩色图像(默认使用 BGR 色彩格式)
img = cv2.imread('./dog.jpeg')
# 使用平均滤波器对图像进行平滑处理
# img 是输入的原始图像
# (5, 5) 是滤波器的卷积核大小(5x5 的矩形区域)
# cv2.blur() 函数通过对该区域内像素进行平均值计算,从而减小噪声,实现图像平滑
# 结果存储在 dst 中,dst 是滤波后的图像
dst = cv2.blur(img, (5, 5))
# 使用 np.hstack() 将原始图像和经过方盒滤波处理的图像在水平方向上并排拼接
# 并通过 cv2.imshow() 显示拼接后的图像
# 'img' 是显示窗口的名称
cv2.imshow('img', np.hstack((img, dst)))
# 等待用户按任意键继续,0 表示无限等待
cv2.waitKey(0)
# 销毁所有窗口,释放资源
cv2.destroyAllWindows()
3 高斯滤波
高斯滤波的核心思想是让临近的像素具有更高的重要度. 对周围像素计算加权平均值, 较近的像素具有较大的权重值.
要理解高斯滤波首先要知道什么是高斯函数.高斯函数在是符合高斯分布(也叫正态分布)的数据的概率密度函数.画出来长这样子:
高斯函数的特点是以x轴某一点(这一点称为均值)为对称轴, 越靠近中心数据发生的概率越高, 最终形成一个两边平缓, 中间陡峭的钟型(有的地方也叫帽子)图形.
高斯函数的一般形式为:
高斯滤波就是使用符合高斯分布的卷积核对图片进行卷积操作. 所以高斯滤波的重点就是如何计算符合高斯分布的卷积核, 即高斯模板.
假定中心点的坐标是(0,0),那么取距离它最近的8个点坐标,为了计算,需要设定σ的值。假定σ=1.5,则模糊半径为1的高斯模板就算如下:
- 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
我们可以观察到越靠近中心, 数值越大, 越边缘的数值越小.符合高斯分布的特点.
通过高斯函数计算出来的是概率密度函数, 所以我们还要确保这九个点加起来为1,这9个点的权重总和等于0.4787147,因此上面9个值还要分别除以0.4787147,得到最终的高斯模板。
注: 有些整数高斯模板是在归一化后的高斯模板的基础上每个数除上左上角的值, 然后取整.
有了卷积核, 计算高斯滤波就简单了.假设现有9个像素点,灰度值(0-255)的高斯滤波计算如下:
将这9个值加起来,就是中心点的高斯滤波的值。对所有点重复这个过程,就得到了高斯模糊后的图像。
-
GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType]]])
- kernel 高斯核的大小.
- sigmaX, X轴的标准差
- sigmaY, Y轴的标准差, 默认为0, 这时sigmaY = sigmaX
- 如果没有指定sigma值, 会分别从ksize的宽度和高度中计算sigma.
-
选择不同的sigma值会得到不同的平滑效果, sigma越大, 平滑效果越明显.
# 选择不同的sigma值会得到不同的平滑效果, sigma越大, 平滑效果越明显.
import cv2
import numpy