深度学习笔记(4):1.1-1.3 边缘检测(edge detection)


第四课开始,我们开始学习卷积神经网络。

1.1 计算机视觉(computer vision)

深度学习在计算机视觉方面的应用非常振奋人心,一方面是该应用使许多不可能变成了可能,另一方面是深度学习在计算机视觉方面的应用能够给深度学习在其他方面的应用带来一些方法的改进和思考,比如语音识别等。

计算机视觉包含哪些问题呢?如下图所示:

比如图片分类,判断一个图片是否是猫;或者目标识别,比如在无人驾驶任务中,识别路上其他的车以及距离,以便无人驾驶能够安全执行;还有就是图片风格转化,比如我们有一个美女的照片(是吴老师的妻子,哈哈)和一个毕加索的绘画,把二者融合起来,就可以得到人像的轮廓和毕加索的风格。

比如在图片分类中,我们使用的图片可能是小图片,比如像素是64*64,加上颜色的三个channel(RGB channels),该图片作为输入是一个64*64*3=12288维的向量,还好。但若是大图片呢?比如一个像素为1000*1000的图片,那该图片作为输入就是3m(3百万)维的向量,假设第一层隐藏节点有1000个,且在完全连接的情况下,第一层的权重矩阵就是1000*3m维的矩阵,相当于第一层有30亿的权重,这时很难有足够多的样本去训练这么多的权重,容易发生过拟合,同时这么多的权重还会对内存有一定要求,而且我们不想仅限于处理小图片。为了解决衍生出来的这么多问题,我们需要使用卷积运算,见下节。

1.2 边缘检测例子(edge detection example)

卷积运算是卷积神经网络最基本的组成部分。这节课我们通过边缘检测例子来学习卷积运算,如下图所示:

在神经网络模型中,前几层神经网络能检测到边界,后几层可能检测到物体小部分,再后面几层可能检测到具体的物体,在这个例子中就是人脸。接下来我们讲如何在图片中识别边界,也就是为何神经网络前几层能够检测到图片中的边界。

假设我们有上图中这样一个照片,我们可以通过垂直边缘检测器和水平边缘检测器分别检测出图片中的垂直和水平边缘,检测器检测出的结果如上图所示。但是这些检测器是如何工作的呢?我们以垂直检测器为例。在介绍垂直检测器之前,我们先介绍一种运算,卷积运算(Convolution operation),如下图所示:

假设我们的图片如上图左侧矩阵所示,这是一个6*6的矩阵,因为我们没有考虑彩色,这仅仅是一个黑白图片,所以不存在RGB通道,这里图片是6*6*1的向量,接下来我们对其作卷积运算。

首先介绍一下中间的3*3矩阵,我们称之为‘核(kernel)’或‘过滤器(filter)’,中间‘*’号表示卷积运算,这与我们在程序中使用方法不同,一般‘*’在程序中都表示乘法,或者说是element-wise的乘法。

那么卷积运算怎么做呢?我曾在深度学习书中看过这样一种比喻,我觉得比较恰当,在这里跟大家分析一下,想象你是一个探险家,在黑暗中找到一幅画卷,为了仔细看清画卷内容,于是你打开手电筒从画的左上角还是扫描直至画的右下角,过滤器做的就是类似手电筒的工作。计算也非常简单,就是element-wise,首先将filter对应于左上角九宫格,然后按上图中红色式子进行计算,就是对这两个3*3矩阵进行element-wise乘法再求和,我们得到-5,写于右侧矩阵的(1,1)位置,就这样从左到右,从上到下,最终得到一个4*4的矩阵,其中最后(4,4)位置对应的-16是由左侧紫色框内矩阵和filter做卷积计算所得。

了解了卷积运算,接下来我们介绍垂直边缘检测器,如下图所示:

同样是做卷积运算,不过我们在这里对filter做了‘手脚’,使其能够检测出图片中的垂直边界,怎么说呢?

在原图中,也就是左矩阵中,我们用0来表示灰色(或者你认为黑色都可以),10来表示白色,即数值越大颜色越亮,我们想检测出白色和灰色中间那条边界,怎么做呢?我们使用了一个3*3的filter,它的第一列都为1,第二列为0,第三列为-1,经过卷积运算我们得到了一个4*4的矩阵,中间两列值都为30,两边为0,即我们清晰地找出了边界。

首先为什么能够找出边界,背后的思想我们可以这样认为,边界两侧的数值肯定是有很大差异的,不是边界的数值差异不大,所以kernel这样取值就能使数值差异不大的地方通过卷积运算得出来的值近似为0,而当数值有很大差异时,使用该kernel就无法抵消,这样就可以找出边界,当然这里要注意我们设置kernel的维度要注意原图的维度以及边界的宽度,比如这里最后的出来的边界看起来很宽,那是因为原图太小了,仅仅是6*6,如果是1000*1000,边界效果就会很好了。

1.3 更多边缘检测内容(more edge detection)

这小节我们将学习更多边缘检测的内容,比如学会如何区分正边和反边,也就是区分由亮到暗和由暗到亮的区别,如下图所示:

还是之前那个例子,假设我们将图片左右翻转一下,现在左侧是暗的,右侧是亮的,但是我们还使用同一个filter,所以自然会得到一个相反的数值,如上图所示,表示边界的值由30变为-30,这里数值的变化就就能够告知我们一些准确的信息,比如30告诉我们这个边界是正边,即颜色是由亮到暗,而-30就告诉我们这个边界是负边,及颜色是由暗到亮,当然如果你不care正边还是负边可以直接对卷积计算结果取绝对值,即只确定边界并不考虑其颜色是如何变化的。

除了垂直边缘检测,我们还可以进行水平边缘检测,如下图所示:

思想很简单,将垂直边缘检测的kernel作转置我们就可以得到水平边缘检测的kernel了。套用在例子中如上图所示,假设我们现在有一个这样的6*6矩阵,其对应图片为左下部和右上部偏暗,显然这个图片既存在水平边缘也存在垂直边缘,现在我们使用水平边缘检测的kernel去检测水平边缘,结果如上图所示,10和-10的出现在这里是因为垂直边缘的影响,同样,因为我们这里举例子的图片太小(6*6),所以这里显得10和-10占了很大比重,如果我们是1000*1000的图片,结果就可以不考虑10和-10的影响了。

对于kernel中的数值选取,很多学者在文献中公平地讨论过该如何搭配数据才是合理的,如下图所示:

除了第一列都是1,第三列都是-1这种filter,我们还可以对数据做其他改变,比如第二行都乘上2,我们称之为sobel filter,相当于在原来基础上进行了加权,它的优点在于增加了中间一行的权重,也就是处在中间的像素,这样可以增加结果的鲁棒性(robust),还有另一种filter,将第一行和第三行都乘上3,第二行乘上10,我们称之为scharr filter,这样改变也会改进一些性能。

但实际中,我们一般将这九个值设为九个参数,然后通过神经网络的反向传播去学习,为啥呢么这样做呢?首先是之前的filter过于简单,针对的仅仅是垂直或水平边缘的情况,即90度,且数值是实验前已经设定好的,不一定适合每个问题,而实际问题要复杂得多,比如上图中所示的情况,所以我们希望filter中的数值能够作为参数从数据集中学习而得到,这样一方面是准确,一方面是我们可以应对任何复杂的情况,不论是45度、70度或是73度的边缘我们都可以检测出来。

通过反向传播去学习kernel中的参数已经成为计算机视觉中最有效的思想之一。接下来我们会学习如何使用反向出传播去学习这九个参数,但在此之前,我们会先学习一下有关卷积运算的基础知识,详见下节。

 

版权声明:尊重博主原创文章,转载请注明出处https://blog.csdn.net/kkkkkiko/article/details/81812841