吴恩达深度学习笔记-11(目标检测)
目标检测
目标定位
之前学的是利用CNN进行图像分类。接下来将继续深入介绍目标定位和目标检测(包含多目标检测)。

图片分类任务我们已经熟悉了,就是算法遍历图片,判断其中的对象是不是汽车,这就是图片分类。
另一个问题是定位分类问题。这意味着,我们不仅要用算法判断图片中是不是一辆汽车,还要在图片中标记出它的位置,用边框或红色方框把汽车圈起来,这就是定位分类问题。
第三幅图是一个检测问题,在图片中检测需要检测的对象并确定位置。
标准的CNN分类模型我们已经很熟悉了,如下所示:

原始图片经过CONV卷积层后,Softmax层输出4 x 1向量,分别是:

上述四个向量分别对应pedestrain,car,motorcycle和background四类。
对于目标定位和目标检测问题,其模型如下所示:

原始图片经过CONV卷积层后,Softmax层输出8 x 1向量。除了包含上述一般CNN分类3 x 1向量(class label)之外,还包含了(bx, by),表示目标中心位置坐标;还包含了bh和bw,表示目标所在矩形区域的高和宽;还包含了Pc,表示矩形区域是目标的概率,数值在0~1之间,且越大概率越大。一般设定图片左上角为原点(0, 0),右下角为(1, 1)。在模型训练时,bx、by、bh、bw都由人为确定其数值。例如上图中,可得bx=0.5,by=0.7,bh=0.3,bw=0.4。
输入样本的标签可表示为:
Pc=1时,\(\left [
\begin{matrix}
1 \\
bx \\
by \\
bh \\
bw \\
c1 \\
c2 \\
c3
\end{matrix}
\right ]\)
Pc=2时,\(\left [
\begin{matrix}
0 \\
? \\
? \\
? \\
? \\
? \\
? \\
?
\end{matrix}
\right ]\)
若Pc=0,表示没有检测到目标,则输出label后面的7个参数都可以忽略。
相应地,对于损失函数Loss function,若使用平方误差形式,有两种情况:
- Pc=1,即\(y_1=1\):$$L(\hat y,y)=(\hat y_1-y_1)^2+(\hat y_2-y_2)^2+\cdots+(\hat y_8-y_8)^2$$
- Pc=0,即\(y_1=0\):$$L(\hat y,y)=(\hat y_1-y_1)^2$$
当然,除了使用平方误差之外,还可以逻辑回归损失函数,类标签\(c_1,c_2,c_3\)也可以通过softmax输出。比较而言,平方误差已经能够取得比较好的效果。
标志检测
除了使用矩形区域检测目标类别和位置外,我们还可以仅对目标的关键特征点坐标进行定位,这些关键点被称为landmarks。
上节课,我们讲了如何利用神经网络进行对象定位,即通过输出四个参数值\(b_x、b_y、b_h\)和\(b_w\)给出图片中对象的边界框。更概括地说,神经网络可以通过输出图片上标志点\((x,y)\)的坐标来实现对目标标志的识别,我们看几个例子。
例如人脸识别,可以对人脸部分特征点坐标进行定位检测,并标记出来,如下图所示:

\((l_{1x},l_{1y})....(l_{64x},l_{64y})\)分别是64个标志点。
如此一来就可以通过神经网络输出鼻子、眼睛、嘴、脸部轮廓这四个面部的标志的位置。
除了人脸特征点检测之外,还可以检测人体姿势动作,如下图所示:

滑动窗口
(略)
滑动窗口法的卷积实现
滑动窗算法可以使用卷积方式实现,以提高运行速度,节约重复运算成本。
首先,单个滑动窗口区域进入CNN网络模型时,包含全连接层。那么滑动窗口算法卷积实现的第一步就是将全连接层转变成为卷积层,如下图所示:

全连接层转变成卷积层的操作很简单,只需要使用与上层尺寸一致的滤波算子进行卷积运算即可。最终得到的输出层维度是1 x 1 x 4,代表4类输出值。
单个窗口区域卷积网络结构建立完毕之后,对于待检测图片,即可使用该网络参数和结构进行运算。例如16 x 16 x 3的图片,步进长度为2,CNN网络得到的输出层为2 x 2 x 4。其中,2 x 2表示共有4个窗口结果。对于更复杂的28 x 28 x3的图片,CNN网络得到的输出层为8 x 8 x 4,共64个窗口结果。

之前的滑动窗算法需要反复进行CNN正向计算,例如16 x 16 x 3的图片需进行4次,28 x 28 x3的图片需进行64次。
而利用卷积操作代替滑动窗算法,那么我们不需要把输入图像分割成四个子集,分别执行前向传播,而是把它们作为一张图片输入给卷积网络进行计算,其中的公共区域可以共享很多计算。
这大大节约了运算成本。值得一提的是,窗口步进长度与选择的MAX POOL大小有关。如果需要步进长度为4,只需设置MAX POOL为4 x 4即可。
边界框预测
滑动窗口算法有时会出现滑动窗不能完全涵盖目标的问题,如下图蓝色窗口所示。

YOLO(You Only Look Once)算法可以解决这类问题,生成更加准确的目标区域(如上图红色窗口)。
YOLO算法首先将原始图片分割成n x n网格,每个网格代表一块区域。为简化说明,下图中将图片分成3 x 3网格。

然后,利用上一节卷积形式实现滑动窗口算法的思想,对该原始图片构建CNN网络,得到的的输出层维度为3 x 3 x 8。其中,3 x 3对应9个网格,每个网格的输出向量y包含8个元素:
如果目标中心坐标\((b_x,b_y)\)不在当前网格内,则当前网格Pc=0;相反,则当前网格Pc=1(即只看中心坐标是否在当前网格内)。判断有目标的网格中,\(b_x,b_y,b_h,b_w\)限定了目标区域。值得注意的是,当前网格左上角坐标设定为(0, 0),右下角坐标设定为(1, 1),\((b_x,b_y)\)范围限定在[0,1]之间,但是\(b_h,b_w\)可以大于1,因为\(b_h,b_w\)表示的是目标框和网格的高度和宽度的比例。因为目标可能超出该网格,横跨多个区域,如上图所示。目标占几个网格没有关系,目标中心坐标必然在一个网格之内。
划分的网格可以更密一些。网格越小,则多个目标的中心坐标被划分到一个网格内的概率就越小,这恰恰是我们希望看到的。
交并比
IoU(Intersection Over Union),即交集与并集之比,可以用来评价目标检测区域的准确性。

如上图所示,红色方框为真实目标区域,蓝色方框为检测目标区域。两块区域的交集为绿色部分,并集为紫色部分。蓝色方框与红色方框的接近程度可以用IoU比值来定义:
一般约定,在计算机检测任务中,如果\({IoU}\ge0.5\),就说检测正确,如果预测器和实际边界框完美重叠,loU就是1。
一般约定,0.5是阈值,用来判断预测的边界框是否正确。如果想更严格一点或者说更精确一点,可以把阈值调得更高。
非极大值抑制
YOLO算法中,可能会出现多个网格都检测出到同一目标的情况,例如几个相邻网格都判断出同一目标的中心坐标在其内。


上图中,三个绿色网格和三个红色网格分别检测的都是同一目标。那如何判断哪个网格最为准确呢?方法是使用非最大值抑制算法。
非最大值抑制(Non-max Suppression)做法很简单,图示每个网格的Pc值可以求出,Pc值反映了该网格包含目标中心坐标的可信度。首先选取Pc最大值对应的网格和区域,然后计算该区域与所有其它区域的IoU,剔除掉IoU大于阈值(例如0.5)的所有网格及区域。这样就能保证同一目标只有一个网格与之对应,且该网格Pc最大,最可信。接着,再从剩下的网格中选取Pc最大的网格,重复上一步的操作。最后,就能使得每个目标都仅由一个网格和区域对应。如下图所示:

总结一下非最大值抑制算法的流程:
-
- 剔除Pc值小于某阈值(例如0.6)的所有网格;
-
- 选取Pc值最大的网格,利用IoU,摒弃与该网格交叠较大的网格;
-
- 对剩下的网格,重复步骤2。
Anchor Box
根据之前学习的内容,可以知道一个网格最多只能检测一个目标,但是实际应用当中,有可能发生一个网格中出现多个目标的糟糕情况。例如一个人站在一辆车前面,该如何使用YOLO算法进行检测呢?方法是使用不同形状的Anchor Boxes。
假设你有这样一张图片,对于这个例子,继续使用3×3网格,注意行人的中点和汽车的中点几乎在同一个地方,两者都落入到同一个格子中。

同一网格出现了两个目标:人和车。为了同时检测两个目标,我们可以设置两个Anchor Boxes

Anchor box 1检测人,Anchor box 2检测车。
也就是说,每个网格多加了一层输出。
原来的输出维度是 3 x 3 x 8,现在是3 x 3 x 2 x 8(也可以写成3 x 3 x 16的形式)。这里的2表示有两个Anchor Boxes,用来在一个网格中同时检测多个目标。
前8个参数为Anchor Box 1的参数,后8个为Anchor Box 2的参数。
每个Anchor box都有一个Pc值,若两个Pc值均大于某阈值,则检测到了两个目标。
在使用YOLO算法时,只需对每个Anchor box使用上一节的非最大值抑制即可。Anchor Boxes之间并行实现。
顺便提一下,Anchor Boxes形状的选择可以通过人为选取,也可以使用其他机器学习算法,例如K-Means算法对待检测的所有目标进行形状分类,选择主要形状作为Anchor Boxes。
候选区域
之前介绍的滑动窗算法会对原始图片的每个区域都进行扫描,即使是一些空白的或明显没有目标的区域,例如下图所示。这样会降低算法运行效率,耗费时间。

为了解决这一问题,尽量避免对无用区域的扫描,可以使用Region Proposals的方法。具体做法是先对原始图片进行分割算法处理,然后支队分割后的图片中的块进行目标检测。
比如说,分割算法在这里得到一个色块,所以你可能会选择这样的边界框(编号1),然后在这个色块上运行分类器,就像这个绿色的东西(编号2),在这里找到一个色块,接下来我们还会在那个矩形上(编号3)运行一次分类器,看看有没有东西。在这种情况下,如果在蓝色色块上(编号3)运行分类器,希望你能检测出一个行人,如果你在青色色块(编号4)上运行算法,也许可以发现一辆车。


浙公网安备 33010602011771号