1.1.卷积运算法则
在计算机视觉领域,卷积运算撑起了半边天,因此在学习计算机视觉前,首先来了解一下卷积运算是如何运算的。
假设正在进行边缘检测,垂直边缘检测会把图片中接近垂直的边缘提取出来,即人的侧边、栏杆等。而水平边缘检测会把图片中接近水平的边缘提取出来,即横杆、自行车轮的上侧等。现在以垂直边缘检测为例,解释一下卷积运算是如何进行的?
卷积运算用*符号表示,一张图片表示的矩阵*一个过滤器(或被称为核,在图像处理领域又被称为滤波器)=新的图片表示的矩阵。
进行上图所示的卷积运算,得到是4*4的矩阵表示的图片,其中新矩阵的(0,0)元素是将过滤器放置6*6矩阵的左上角,如下所示:
然后把矩阵所盖住的区域和过滤器各个位置对应的元素相乘,得到新的3*3矩阵,如下所示:
最后把矩阵的各元素累加,得到(0,0)位置的元素:
当计算(0,1)位置的元素时,把过滤器右移一个单位,然后再次进行上述的运算,即如下:
直到本行计算结束,得到如下结果:
当计算(1,0)位置的元素时,把(0,0)下标时过滤器所在的位置下移一个步长,依次按照上述计算方式计算各个位置的元素,最终得到:
相信对于学习过图像处理的朋友们,这里并不陌生,而对于没有学过图像处理的同学,一定会好奇这样操作为什么就会检测出垂直边缘,下面再通过一个例子了解一下其中的原理:
把正数定义为白色块,0定义为灰色块,负数定义为黑色块,则进行垂直边缘检测得到的4*4矩阵如上图,可以发现中间两列是白色条带,边缘两列是灰色条带。这是由于当图像中出现边缘时,边缘两侧的颜色通常差别较大,因此若过滤器完全覆盖边缘的一侧(这一侧颜色一般接近,因此矩阵的数值也接近),则计算后结果接近0,也就是定义的灰色。若过滤器覆盖在边缘上,则计算后结果要么是很大的正数,要么是很大的负数,也就是白色或黑色,这和非边缘的数值差别很大,所以就凸显了垂直边缘。如果想要垂直边缘检测后的图像边缘较细,就需要用到维度更小的过滤器,从而精细处理。
上图需要检测的图片的边缘是由亮变暗,那么如果图片是由暗变亮,是否还能使用相同的垂直过滤器检测出来?
如上图所示,检测结果将边缘变成了黑边,原来的30变成了-30,表明图片是由暗向亮过渡。如果不在意两者的区别,只是为了检测出区别,对卷积后的矩阵取绝对值即可。
上述的例子都是垂直过滤器,很容易猜到,水平过滤器是中间一行为0,上下行为正负数的样子。如下所示:
即水平过滤器检测到了水平边缘,右图左侧两列是正边(边界为整数),所以原图对应由亮变暗;右侧两列是负边(边界为负数),所以原图由暗变亮。细心的可以发现,在边界处出现了(30)->(10)和(-10)->(-30)的过滤带,这是由于过滤器太大而图片太小的原因,如果选择较大的图片和较小的过滤器,就不会出现过滤带了。
1.2.其他卷积核(过滤器)
(1)Sobel过滤器
增加了中间一行元素的权重,使结果的鲁棒性更好。旋转90度变成对应的水平过滤器。
(2)Scharr过滤器
Sobel过滤器的缺点是,当结构较小时,精确度不高,而Scharr算子具有更高的精度。旋转90度变成对应的水平过滤器。
(3)可学习的过滤器
把过滤器的每个元素都作为参数,参与神经网络的学习,利用反向传播算法进行学习,从而学习到的过滤器可以检测任意角度的边缘,捕捉到任意数据特征。
1.3.Padding
在了解Padding前,首先来看看没有进行Padding操作的卷积结果,6*6的图片经过3*3的过滤器,结果是4*4的新图片,那么经过多次卷积操作后,图片最终变为1*1,此时图片已经损失了大量的特征,因此神经网络的识别效果就很差。这其中的维度变化规律如下:假设原图片是n*n的大小,过滤器是f*f的大小,则卷积后的结果是(n-f+1)*(n-f+1)。
第二个缺点是,对于图片边缘的像素点,过滤器只覆盖了一次,而对于图片中间的像素点,过滤器覆盖了多次,因此边缘的像素点蕴含的特征信息也损失了很多。
那如果可以进行填充,比如在原图像周围填充一定的像素,那么过滤器就可以对原边界进行多次覆盖,从而减少边缘损失的信息。并且图片变大,卷积后结果不会变小太多,从而保证图片不会一直变小。
假设p是填充的圈数,p=1时,如上图所示,6*6的图片变为8*8,再通过3*3的过滤器后,卷积后的图片变为(6+2*1-3+1)*(6+2*1-3+1)=6*6,即图片大小不变,没有被缩小。这里很容易总结出卷积维度变化公式:
当然,p也可以为其他数,比如p=2,填充结果如下:
填充的像素值通常是0,填充的像素个数有两种选择,一种是Valid卷积,一种是Same卷积。
(1)Valid卷积
这种方式p=0,也就是不填充,n*n的图片经过f*f的卷积核结果为(n-f+1)*(n-f+1)。
(2)Same卷积
这种方式从字面意思来看就是保持相同,实际也是这样的意思,通过填充一定的像素使原图片和卷积后的图片大小保持不变,类似上面p=1时,卷积后图片还是6*6。
事实上,利用Padding操作的维度变化公式:(n+2p-f+1)*(n+2p-f+1),让变化前后的图片相等,即n=n+2p-f+1,可以解得:
也就是,为了让卷积前后的图片相等,填充的像素p只和过滤器的大小有关,例如3*3的过滤器,只有p=1时,才能保证相等。
也许有人已经发现,过滤器大小通常是奇数,比如3*3、5*5等。如果是偶数,就会出现两种情况:第一种,填充的p为小数,这样就会造成填充的一侧为多,一侧为少,出现不对称。第二种,过滤器没有中心,这样就会造成很多不便,比如难以定位过滤器的位置。
1.4.卷积步长
前面关于卷积的讨论都是默认步长为1,即过滤器一次只移动一个单位,如果步长为2呢?如下图所示:
此时(0,1)位置的元素应该对应如下:
同样的,在列方向过滤器的移动也是步长为2,纠错:下图中结果(0,2)的下标实际是88:
相信步长这点不难懂,这里不再赘述。总结一下,假设图片是n*n,过滤器是f*f,padding填充为p,步长为s,则卷积后的图片大小为:
如果计算出来是整数,则无需做任何处理。如果不是整数,那就向下取整,此时就说明选择的步长可能会造成部分边缘无法被覆盖,即蓝色区域一部分在图像中,一部分超出图像,此时不再计算该位置即可。其实可以选择合理的步长、填充p和过滤器大小f避免向下取整,也可以直接取整,效果都差不多。