Deep Learning Note: 4-1 卷积神经网络:边缘检测
1. 计算机视觉
一些计算机视觉问题有:
- 图像分类(Image Classification):判断图像中物体的分类,如输入一张图像,判断它是否为猫的照片。
- 对象检测(Object Detection):不仅要判断图像中是否有目标物体,还找出各个目标物体的位置,如检测汽车前方路况图像中障碍物的具体位置。
- 神经风格迁移(Neural Style Transfer):使用一张图像的风格迁移到量一张图像上,合成新的图像,如将毕加索抽象画的风格迁移到一张普通照片上,合成带有抽象风格的照片。
计算机视觉问题的一大挑战是输入的图像可能会非常大。例如输入为 1000 * 1000 的 RGB 图像,则总共有 1000 * 1000 * 3 个特征,如果网络的第一个隐藏层有 1000 个节点,则第一层的权重 $W^{[1]}$ 的大小为 $(1000, 3 \times 10^6)$,即第一层总共有 $3 \times 10^9$ 个权重参数,对于如此巨大的参数数量,很难收集到足够的数据来避免网络发生过拟合,而且训练该网络需要的计算量也非常大。卷积神经网络很好地解决了这一问题。
2. 边缘检测
卷积操作是卷积神经网络的基础,下面以边缘检测为例,说明卷积操作的具体步骤。
在边缘检测中,通常会分别检测图片中的垂直边缘和水平边缘,如图 1 所示。
举例来说,式 (1) 中的 $Image$ 表示一个 6 * 6 的灰阶图像:
\begin{equation}
Image =
\begin{bmatrix}
3 & 0 & 1 & 2 & 7 & 4 \\
1 & 5 & 8 & 9 & 3 & 1 \\
2 & 7 & 2 & 5 & 1 & 3 \\
0 & 1 & 3 & 1 & 7 & 8 \\
4 & 2 & 1 & 6 & 2 & 8 \\
2 & 4 & 5 & 2 & 3 & 9
\end{bmatrix} \tag{1}
\end{equation}
要检测 $Image$ 中的垂直边缘,首先构造一个 $3 \times 3$ 的矩阵 $Filter$,如式 (2),这个矩阵称为过滤器(Filter)或核(Kernel)。
\begin{equation}
Filter =
\begin{bmatrix}
1 & 0 & -1 \\
1 & 0 & -1 \\
1 & 0 & -1
\end{bmatrix} \tag{2}
\end{equation}
然后计算 $Image$ 和 $Filter$ 的卷积:
\begin{equation}
Image * Filter =
\begin{bmatrix}
-5 & -4 & 0 & 8 \\
-10 & -2 & 2 & 3 \\
0 & -2 & -4 & -7 \\
-3 & -2 & -3 & -16
\end{bmatrix} \tag{3}
\end{equation}
式 (3) 中第 1 行第 1 列(左上角)的元素为 -5,它是由 $Image$ 中前 3 行和前 3 列所组成的 $3 \times 3$ 的矩阵与 $Filter$ 逐元素相乘,再求和得到的,即:
\begin{equation}
\begin{bmatrix}
3 & 0 & 1 \\
1 & 5 & 8 \\
2 & 7 & 2
\end{bmatrix}
\cdot
\begin{bmatrix}
1 & 0 & -1 \\
1 & 0 & -1 \\
1 & 0 & -1
\end{bmatrix}
=\begin{bmatrix}
3 & 0 & -1 \\
1 & 0 & -8 \\
2 & 0 & -2
\end{bmatrix} \\
\end{equation}
\begin{equation}
3 + 0 – 1 + 1 + 0 – 8 + 2 + 0 – 2 = -5
\end{equation}
同理,式 (3) 中第 1 行第 2 列的元素的计算过程为,使用 $Image$ 中前 3 行和第 2 ~ 4 列所组成的 $3 \times 3$ 的矩阵与 $Filter$ 逐元素相乘再求和:
\begin{equation}
\begin{bmatrix}
0 & 1 & 2 \\
5 & 8 & 9 \\
7 & 2 & 5
\end{bmatrix}
\cdot
\begin{bmatrix}
1 & 0 & -1 \\
1 & 0 & -1 \\
1 & 0 & -1
\end{bmatrix}
=\begin{bmatrix}
0 & 0 & -2 \\
5 & 0 & -9\\
7 & 0 & -5
\end{bmatrix} \\
\end{equation}
\begin{equation}
0 + 0 – 2 + 5 + 0 – 9 + 7 + 0 – 5 = -4
\end{equation}
以此类推,相当于将 $Filter$ 放在 $Image$ 上,从左到右、从上到下地移动过整个 $Image$,分别计算 $Image$ 被 $Filter$ 盖住的部分与 $Filter$ 的逐元素乘积的和,最终得到式 (3) 的结果,$6 \times 6$ 的矩阵卷积一个 $3 \times 3$ 的矩阵得到一个 $4 \times 4$ 的矩阵。以上就是一个简单的边缘检测器。
再看一个列子,一个 $6 \times 6$ 的图像卷积一个如式 (2) 的 $3 \times 3$ 的过滤器,如式 (4):
\begin{equation}
\begin{bmatrix}
10 & 10 & 10 & 0 & 0 & 0 \\
10 & 10 & 10 & 0 & 0 & 0 \\
10 & 10 & 10 & 0 & 0 & 0 \\
10 & 10 & 10 & 0 & 0 & 0 \\
10 & 10 & 10 & 0 & 0 & 0 \\
10 & 10 & 10 & 0 & 0 & 0 \\
\end{bmatrix}
*
\begin{bmatrix}
1 & 0 & -1 \\
1 & 0 & -1 \\
1 & 0 & -1
\end{bmatrix}
=\begin{bmatrix}
0 & 30 & 30 & 0 \\
0 & 30 & 30 & 0 \\
0 & 30 & 30 & 0 \\
0 & 30 & 30 & 0
\end{bmatrix} \\
\end{equation}
在这个 $6 \times 6$ 的图像中,左边一半像素的值全是 10,右边一半像素的值全是 0,中间是一条非常明显的垂直边缘。这个图像与过滤器卷积的结果中,中间两列的值都是 30,两边两列的值都是 0,即检测到了原 $6 \times 6$ 图像中的垂直边缘。以上过程如图 2 所示。
再来看一下式 (2) 所示的过滤器中,其中左边一列全是 1,右边一列全是 -1,中间一列的值全是 0,位于 1 和 -1 之间。这个过滤器本身体现了垂直边缘的特征,即在一段范围内,左边与右边的像素值明显不同。通过将图像与这样的过滤器相卷积,可以发现图像中具有过滤器所描述的特征的部位。
将上面例子中的图像水平翻转,再与式 (2) 的过滤器相卷积,结果如如 3:
图 3 中图像的边缘过度的方向(从暗到亮)与图 2(从亮到暗)相反,图 3 中图像卷积后的结果(-30)也与图 2 中的结果(30)相反;因为过滤器的图样是从亮到暗的,故从亮到暗的边缘检测为正值,从暗到亮的边缘检测为负值。如果不关心边缘过度的方向,可以对卷积结果取绝对值。
将式 (2) 中的过滤器矩阵旋转 90 度,可以得到检测水平边缘的过滤器,即:
\begin{equation}
\begin{bmatrix}
1 & 1 & 1 \\
0 & 0 & 0 \\
-1 & -1 & -1
\end{bmatrix}
\end{equation}
一个例子如图 4 所示:
除了上面用到的两种过滤器,在计算机视觉的发展过程中,出现了很多不同的过滤器。例如 Sobel 过滤器通过在中间一行加入了额外的权重,获得更好的稳定性:
\begin{equation}
\begin{bmatrix}
1 & 0 & -1 \\
2 & 0 & -2 \\
1 & 0 & -1
\end{bmatrix}
\end{equation}
又例如 Scharr 过滤器:
\begin{equation}
\begin{bmatrix}
3 & 0 & -3 \\
10 & 0 & -10 \\
3 & 0 & -3
\end{bmatrix}
\end{equation}
随着深度学习的发展,我们需要检测更复杂的图像中的边缘,与其使用由人手工设计的过滤器,还可以将过滤器中的数值作为参数,通过反向传播来学习得到。算法可以根据实际数据来选择合适的检测目标,无论是检测水平边缘、垂直边缘还是其他角度的边缘,并习得图像的低层特征。