一 卷积简介
假设你的老板命令你干活,你却偷偷上班划水摸鱼,后来被老板发现,他非常气愤,扇了你一巴掌(注意,这就是输入信号,脉冲),于是你的脸上会渐渐地鼓起来一个包,你的脸就是一个系统,而鼓起来的包就是你的脸对巴掌的响应,好,这样就和信号系统建立起来意义对应的联系。下面还需要一些假设来保证论证的严谨:假定你的脸是线性时不变系统,也就是说,无论什么时候老板打你一巴掌,由于老板的力度掌控的不那么好,脸上的包一开始肿的程度也不一样(输入信号不恒定),并且假定以鼓起来的包的大小作为系统输出。好了,那么,下面可以进入核心内容——卷积了
如果你每天在摸鱼,那么老板每天都要扇你一巴掌,不过当老板打你一巴掌后,你5分钟就消肿了(包消肿程度的速度曲线假设相同),所以时间长了,你甚至就适应这种生活了……
终于有一天,老板忍无可忍了,以0.5秒的间隔开始不间断的扇你的过程,这样问题就来了,第一次扇你鼓起来的包还没消肿,第二个巴掌就来了,你脸上的包就可能鼓起来两倍高,老板不断扇你,脉冲不断作用在你脸上,包鼓起的程度就在不断叠加了,这样这些效果就可以求和了,如果老板扇你的频率越来越高以至于你感受不到了时间的流逝,那么求和就可以变成积分了。这个积分(实际上是一条函数),就是卷积。
总之,要想有卷积,每一时刻的输入信号在接下来的一段时间都要对系统有持续地影响。
参考资料
二 2D卷积
- 单通道卷积
1.首先定义一个滤波器(卷积核),如下图
2.然后依次从左往右,从上往下,在矩阵中移动卷积核(默认步长为1,可自定义步长
3.将滤波器中的元素与对应的矩阵上的元素相乘,最后再相加,每次滑动一个步长,就会得到一个元素
4.注意:在CV中传统的卷积操作是提前定义好的,可用来去噪,或平滑图像。在神经网络中,卷积核的参数是需要网络自己学到的
注意事项
1.卷积核的大小一般是奇数,这样的话它是按照中间的像素点中心对称的,所以卷积核一般都是33、55、7*7。有中心了,也有了半径的称呼,例如5×5大小的核的半径就是2.
2.卷积核所有的元素之和一般要等于1,这是为了原始图像的能量(亮度)守恒。如果所有元素之和大于1,那么滤波后的图像就会比原图像更亮,反之,如果小于1,得到的图像就会变暗。如果和为0,图像不会变暗,但也会非常暗。
3.对于滤波后的结构,可能会出现负数或者大于255的数值。对这种情况,我们直接将它们截断到0到255之间即可。
- 多通道卷积
与本文内容无关,可当扩展学习
2D卷积的作用
一个噪音白点周围都是黑色,通过卷积,周围像素相加求平均,可以使得该点变黑,达到去噪作用。但卷积次数多会使得图片变模糊了,所以卷积次数需要调试。
参考资料
三 卷积的程序实现
OpenCV提供了一个函数cv.filter2D来将内核与图像进行卷积。例如,我们将尝试对图像进行平均滤波。5x5平均滤波器内核如下所示
保持这个内核在一个像素上,将所有低于这个内核的25个像素(因为是1)相加,取其平均值,然后用新的平均值替换中心像素。它将对图像中的所有像素继续此操作
查看下面的示例演示,
import cv2 import numpy as np from matplotlib import pyplot as plt img = cv2.imread('homework.jpg') kernel = np.ones((5,5),np.float32)/25 dst = cv2.filter2D(img,-1,kernel) plt.subplot(121),plt.imshow(img),plt.title('Original') plt.xticks([]),plt.yticks([]) plt.subplot(122),plt.imshow(dst),plt.title('Blurred') plt.xticks([]),plt.yticks([]) plt.show()
np.ones()函数
功能:返回一个矩阵
输入参数:
1.矩阵的大小
2.矩阵的数据类型(例如‘ numpy . int 8 ’、‘np.float32’。默认值是‘ num py . float 64 ’)
cv2.filter2D()函数
功能:对图像进行2D卷积
输入参数:
1.图像名
2.图像的深度(-1表示跟原图像的深度一样)
3.卷积核kernel
图像深度
指像素深度中实际用于存储图像的灰度或色彩所需要的比特位数。 假定图像的像素深度为16bit,但用于表示图像的 灰度 或色彩的位数只有15位,则图像的图像深度为15。 图像深度决定了图像的每个像素可能的颜色数,或可能的灰度级数。
效果对比