🌈 个人主页:十二月的猫-CSDN博客
🔥 系列专栏: 🏀深度学习_十二月的猫的博客-CSDN博客💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光
目录
1. 前言
2. 常用的图像卷积核
2.1 低通滤波器
2.1.1 均值滤波
2.1.2 高斯滤波
2.2 高通滤波器(典型就是边缘提取器)
2.2.1 锐化滤波器
2.2.2 一阶微分算子
2.2.3 二阶微分算子
3. 算法实现
3.1 Sobel算子实现
3.2 Laplacian算子实现
1. 前言
卷积是一种数学操作。
目的是为了处理信号,其特点是:翻转+乘积相加。
具体内容可以看我的另一篇文章:【深度学习基础】深入理解 卷积与卷积核-CSDN博客
在深度学习中,同样存在卷积操作。
深度学习中的卷积仅仅是乘积相加,不包含翻转。
卷积核就是执行卷积的实体。
乘积相加:特征提取、降维、图像变化
2. 常用的图像卷积核
卷积核也叫滤波器
1)滤波器的大小应该是奇数,这样它才有一个中心,例如3x3,5x5或者7x7。有中心了,也有了半径的称呼,例如5x5大小的核的半径就是2。
2)滤波器矩阵所有的元素之和应该要等于1,这是为了保证滤波前后图像的亮度保持不变。当然了,这不是硬性要求了。
3)如果滤波器矩阵所有元素之和大于1,那么滤波后的图像就会比原图像更亮,反之,如果小于1,那么得到的图像就会变暗。如果和为0,图像不会变黑,但也会非常暗。
4)对于滤波后的结构,可能会出现负数或者大于255的数值。对这种情况,我们将他们直接截断到0和255之间即可。对于负数,也可以取绝对值。
5)滤波实际上就是Same模式的卷积操作,也就是说滤波后图像的大小不变,各种滤镜和照片的风格化就是使用不同的滤波器对图像进行操作。因此卷积核、滤波器本质上都是一个东西;
前景知识:
1、卷积核也叫滤波器:对图片信息进行过滤(特征提取)(Same模式的卷积)。
2、大小奇数。
3、滤波器所有元素和大于1则图像变亮,否则图像变暗。
2.1 低通滤波器
表示仅允许图像中低频部分(即图片中变化较平缓的部分)通过,对高频部分进行一定的阻断。常常用于图像的模糊/平滑处理。常见的有均值卷积核、高斯卷积核等。
2.1.1 均值滤波
特点:滤波器中元素之和为1,输出亮度与输入基本一致;
为低通滤波器,主要用于图像模糊/平滑处理、消除噪点;
核越大,模糊程度越大;
其中均值滤波器从名字就可以看出,每个元素值都一样,是卷积核元素个数的倒数,这样每个输出像素就是其周围像素的均值。一个3 × 3 的均值滤波器如下所示:
一个例子:
2.1.2 高斯滤波
特点:滤波器中元素之和为1,输出亮度与输入基本一致;
为低通滤波器,主要用于图像模糊/平滑处理、消除噪点;
核越大,模糊程度越大;
高斯滤波器虽然元素总和也为1,但每个位置的权重不一样,权重在行和列上的分布均服从高斯分布,故称高斯滤波器。高斯分布的标准差越大,则模糊程度越大。一个3 × 3 标准差为1的高斯滤波器如下所示:
一个例子:
2.2 高通滤波器(典型就是边缘提取器)
表示仅允许图像中高频部分(即图片中变化较剧烈的部分)通过,扩大高频部分的信息,对低频信息不敏感。常见有锐化卷积核、边缘提取器等。
高通滤波器中最典型的就是边缘提取器,提取出物体的边缘对我们非常有用
高通滤波器过滤出图片中变化最剧烈的部分,本质也就是提取出物体的边缘
2.2.1 锐化滤波器
锐化卷积核从名字就可以看出,主要作用就是对图片进行锐化操作,也就是让图像的边缘更加锐利。图像的边缘往往就是变化较大的地方,也就是图像的高频部分,因此锐化卷积核就是一种高通滤波器。一个3 × 3的锐化卷积核如下所示:
可见该卷积核就是计算中心位置像素与周围像素的差值,差值越大则表示该元素附近的变化越大(频率越大),输出值也就越大,因此是高频滤波器的一种。锐化卷积核元素总和如果是0,则有提取图像边缘信息的效果。
锐化卷积核实质:计算中心位置像素和周围像素的差值
一个例子:
2.2.2 一阶微分算子
一阶微分算子计算原理:
如果我们将图像看作一个二维函数,则图像像素值的变化率就可以使用导数(梯度)表示,而边缘的梯度幅值会比较大。如下面的图像表示:
我们可以看到,对于经过图像边缘的一条线,我们可以将其看作为一条关于像素值的函数f(x),表达式图像如上图中间曲线所示。我们可以看出,边缘所处位置即为函数f(x)一阶导数的极值点。我们可以将其扩展到图像(二维离散函数),边缘就是梯度幅值M的局部极值点。
在图像中,图像的梯度与x方向和y方向上的偏导数有关,图像梯度定义为:
图像在各方向上的导数如下图所示:
我们可以看到,图像梯度是具有方向和大小的,其方向指向了像素值变化率最大的方向,一般用角度θ来表达;而梯度大小表示了图像边缘的强弱程度,用梯度幅值M表达。梯度方向和梯度幅值的公式为:
在数字图像处理领域,通常将梯度幅值M(x,y)称为梯度。而在一阶微分算子检测边缘的方法中就是通过一阶微分算子计算得到图像在x方向和y方向的偏导数,再进一步的计算得到梯度幅值M,二值化M后得到图像边缘的。
假设在图像中用f(x,y)表示在点(x,y)处的像素值,则图像在x方向和y方向的一阶微分算子应该计算为:
由于图像是离散的二维函数,ε不能无限小,图像按照像素来离散,最小的ε就是1像素,因此上式就变成了如下的形式(ε=1):
我们可以从这里看到,图像的偏导数就是2个相邻像素之间差值。我们通过gx和gy便可以进一步计算得到梯度幅值M。在实际中,我们常用一个小区域的模板卷积来近似偏导计算。对gx和gy各采用一个模板,并将这两个模板组合起来构成一个梯度算子。根据模板的大小,和模板中系数值的不同,可以提出很多不同的检查算子。下面就列举了一个采用差分近似提出的一种梯度算子计算模板:
怎么理解一阶微分算子 :
图像中物体的边缘往往就是变化较为剧烈的部分(高频部分),对于一个函数来说,变化越剧烈的地方,对应的导数的绝对值也就越大。图像就是一种二元函数,f ( x , y )表示( x , y ))处像素的值,因此导数除了大小,还有方向。那么求图像在某方向上的一阶导数(或称图像的梯度),也就可以反映出图像在该处的变化程度,变化程度越快,在该方向的垂直方向可能就存在物体的边缘。
一阶微分算子可以计算出某个方向上物体的边缘。
但往往对噪声较为敏感,且边缘检测敏感度依赖于物体的大小。
Prewitt算子
Prewitt算子就是对图像进行差分来近似对图像的某个部分求一阶导数。Prewitt算子适合用来识别噪声较多、灰度渐变的图像
具体计算如下:
Sobel算子
Sobel算子则是Prewitt算子的改进版,对中间的元素适当进行了加权,Sobel算子与Prewitt算子类似。Sobel算子包含两组3×3的滤波器,分别对水平及垂直方向上的边缘敏感。
让两个方向模板分别沿着x轴、y轴与图像做卷积,方向是从上到下和从左到右。将模板的中 心和图像上的某个像素重合,并将该像素周围的点 与模板上对应的系数相乘,如图所示,其 中Gx及Gy分别代表经横向及纵向边缘检测的图像梯度值。
图像上每个像素点的横向及纵向梯度值通过如 下式结合,来计算该点梯度值G的大小:
为了减少运算时间,提高运算效率,可以使用绝 对值求和近似的方法代替开平方:
由于Sobel算 子对于象素的位置的影响做了加权,可以降低边缘 模糊程度,与Prewitt算子、Roberts算子相比效果更好。
2.2.3 二阶微分算子
拉普拉斯算子(Laplace):
图像的边缘不仅可以通过一阶导数进行表述,还可以通过二阶导数进行寻找。边缘是一阶导数的极大值点,对应二阶导数的过零点,求出图像的二阶导数的过零点就能精确地找到图像的边缘点,如下面的图像显示:
在上面一节我们已经得到了图像在(x,y)点处x方向和y方向上的一阶偏导数:
因此二阶微分卷积核为:
卷积核和数学推导的关系:
1、卷积核就是通过卷积的方式实现数据按照数学推导要求进行变换
通过模板可以发现,当邻域内像素灰度相同时,模板的卷积运算结果为0;
当中心像素灰度高于邻域内其他像素的平均灰度时,模板的卷积运算结果为正数;
当中心像素的灰度低于邻域内其他像素的平均灰度时,模板的卷积的负数。
对卷积运算的结果用适当的衰弱因子处理并加在原中心像素上,就可以实现图像的锐化处理。
如下图:
3. 算法实现
3.1 Sobel算子实现
Sobel算子函数模板:
cv2.Sobel(src, # 参数是需要处理的图像;
ddepth, # 图像的深度,-1表示采用的是与原图像相同的深度。目标图像的深度必须大于等于原图像的深度
dx, # dx和dy表示的是求导的阶数,0表示这个方向上没有求导,一般为0、1、2。
dy[,
dst[, #输出图片
ksize[,#Sobel算子的大小,必须为1、3、5、7。
scale[, #缩放导数的比例常数,默认情况下没有伸缩系数;
delta[, #可选的增量,将会加到最终的dst中,同样,默认情况下没有额外的值加到dst中;
borderType #判断图像边界的模式。这个参数默认值为cv2.BORDER_DEFAULT。
]]]]])
完整代码:
import numpy as np
import maplotlib.pyplot as plt
import cv2
img_gray = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
# sobel算子计算
sobel_x = cv2.Sobel(img_gray, cv2.CV_64F, 1, 0, ksize=5)
sobel_y = cv2.Sobel(img_gray, cv2.CV_64F, 0, 1, ksize=5)
# 梯度幅值
sobel_M = np.sqrt(sobel_x**2 + sobel_y**2)
# image show
plt.figure('image')
plt.subplot(221), plt.imshow(img_gray, cmap='gray'), plt.title('original')
plt.subplot(222), plt.imshow(sobel_x, cmap='gray'), plt.title('sobel x')
plt.subplot(223), plt.imshow(sobel_y, cmap='gray'), plt.title('sobel y')
plt.subplot(224), plt.imshow(sobel_M, cmap='gray'), plt.title('sobel M')
plt.show()
3.2 Laplacian算子实现
使用cv2.Laplacian()函数实现拉普拉斯算子。
dst = cv2.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]])
第一个参数是需要处理的图像;
第二个参数是图像的深度,-1表示采用的是与原图像相同的深度。目标图像的深度必须大于等于原图像的深度;
其后是可选的参数:
dst不用解释了;
ksize是算子的大小,必须为1、3、5、7。默认为1。
scale是缩放导数的比例常数,默认情况下没有伸缩系数;
delta是一个可选的增量,将会加到最终的dst中,同样,默认情况下没有额外的值加到dst中;
borderType是判断图像边界的模式。这个参数默认值为cv2.BORDER_DEFAULT。
完整代码:
import numpy as np
import maplotlib.pyplot as plt
import cv2
img_gray = cv2.imread('image.jpg', cv2.IMREAD_GRAYSCALE)
laplacian = cv2.Laplacian(img_gray, cv2.CV_64F, ksize=5)
plt.figure('laplacian')
plt.subplot(121), plt.imshow(img_gray, cmap='gray'), plt.title('original')
plt.subplot(122), plt.imshow(laplacian, cmap='gray'), plt.title('laplacian')
plt.show()
如果想要学习更多深度学习知识,大家可以点个关注并订阅,持续学习、天天进步
你的点赞就是我更新的动力,如果觉得对你有帮助,辛苦友友点个赞,收个藏呀~~~