coursera 吴恩达深度学习 Specialization 笔记(course 4 week 3)—— 物体检测

本周主要学习如何通过 CNN 来进行物体检测。

物体定位(单个物体)

什么是物体定位

  • 图像分类:图片中是否有车
  • 物体定位:不仅要识别出是否有车(单个对象),还要在车的周围生成一个边框,即分类+定位
  • 物体检测:找到一张图片里的多个对象并定位它们

如何定位

假设我们需要找出图片中是否有以下四类对象:

  • 行人
  • 摩托车
  • 无物体

我们最后用 softmax 输出四个分类,不仅如此,为了找出它们的位置,还需要输出以下四个值:

  • $b_x$ :方框中心的横坐标
  • $b_y$:方框中心的纵坐标
  • $b_h$:方框的高度
  • $b_w$:方框的宽度

最后目标标签为:

  • Pc 指的是图片中存在该单个对象的概率,若有则值为 1,若没有则值为 0
  • C1、C2、C3 当物体为某个类时,对应的 C 值取 1,其他取 0
  • 当 Pc 为 0 时,也就是图片中不存在物体时,剩下的 ? 值表示我们并不关心这些值是多少

损失函数

假设使用平方误差,那么:

特征点检测

当我们需要找出图片中的一些特征点时,我们可以在标签中增加这些点的坐标。

例如我们需要识别出下面这张脸的五官的轮廓,我们可以定义一些特征点,产生含有这些特征点坐标的训练集,然后我们将图片丢进神经网络,最后输出若干个值。

物体检测(多个物体)

滑动窗口检测法 Sliding Windows

拍一张照片然后裁剪掉其他不是汽车的部分,得到一张汽车剧中并几乎占全部画面的紧密裁剪的汽车图像,使用许多紧密裁剪的汽车图像作为训练集,训练一个神经网络判断是车。

在一张可能包含汽车的大图像中,先选择一个窗口尺寸,然后只读取这个小窗口内的图像,输入到上面训练的卷积网络中,做一个预测,滑动窗口检测指的是将小窗口按步长移动到下一个位置,再重复上述操作,再移动窗口,重复上述操作,直到滑动窗口遍历了图像中的所有位置。

然后我们可以取不同大小的窗口重复上述操作,只要图像某处中有一辆车,那么就会有某个窗口会圈住一辆车然后检测出来。

缺点:

  • 当你使用较大的窗口移动步长,算法表现会下降
  • 当你使用较小的步长,计算成本则会非常高

滑动窗口检测的卷积实现

如果每个小窗口的图像都通过这么一个卷积网络:

我们将全连接层改造成以下的结构,实现参数共享,减少计算量:

具体做法是:

我们将待检测的大图像直接输入到我们改造后的(本来用来预测窗口图像的)卷积网络中,最后的输出就是我们对应的每个滑动窗口的结果,而不是一个窗口一个窗口滑动,截取图像然后输入。

由于直接将整个图像输入到训练好的网络,在同一时间将所有的滑动窗口实现了前向传播,实现了参数的共享,减少了计算的成本。

缺点:由于窗口只能是正方形,所以边界框的位置不准确。

边界框预测

YOLO 算法介绍

为了更好地检测出物体的真实边界,可以使用 YOLO 算法,是 you only look once 的缩写。

有一张图片,首先用 9×9 的网络划分(当然实际使用中可以使用更加精细的),然后将开始学到的物体定位算法运用在这每一个网格中。

那么根据每个网格是否有物体,如果有,那么边界框坐标是多少,是什么类别,得到每个网格的标签值 y 为:

值得注意的是,每个物体就算跨越了多个网格,我们也只能将其划分到它中心点所在的网格里。

所以最后将这些标签堆叠起来形成一个维度为 3×3×8 的标签(8 指的是每个网格的 8 个标签值)。

我们要做的是输入训练集进入一个卷积网络,我们通过调整网络超参数使得最后输出一个 3×3×8 的向量,这就与我们 3×3×8 的标签形成对应,构造代价函数。经过训练之后,我们随便输入一张图像,就可以知道在网格每个位置是否存在物体,对应的边界框坐标是什么。

如何确定边界框的参数

一种方法是令网格的左上角为(0,0),右下角为(1,1),那么中心点的坐标由它相对(0,0)的位置决定,一定介于 0~1 之间;而方框的长跟宽根据它和网格宽度的比例决定,可以超过 1.

例如上面黄色中心点的坐标约为(0.4,0.3,0.9,0.5)。

如何评价物体检测算法

为了知道物体检测算法的性能好坏,可以使用一个叫做“交并比 (Intersection Over Union)”的函数.

假设红框是实际的边界,紫框是算法预测的边界,黄色部分是两者的交集,绿色部分是两者的并集,那么:

交并比 IoU = 交集的面积 / 并集的面积。

判别:一般来说,如果 IoU 大于等于 0.5,便可认为定位正确。也可以定义更严格的值。

非最大值抑制 non-max suppression

如下图所示,一个 19×19 的网格将图片划分,运行 YOLO 算法,可能对于一辆汽车,有许多网格都认为该汽车的中心点在它那里,即这辆汽车的范围内的许多网格都认为自己检测到了汽车了,发生重复检测的问题。抑制非最大值可以确保算法对一个物体只检测一次,而不是检测许多次。

如果一辆车检测了许多次,就会在其周围产生许多方框,如下图所示,每个方框上的数字表示该网格认为自己检测到了物体的概率:

抑制非最大值的具体的做法为(假设只是检测单一物体):

  • 每个网格的输出为:$\begin{bmatrix}
    p_c\\
    b_x\\
    b_y\\
    b_h\\
    b_w\\
    \end{bmatrix}$
  • 丢弃所有低概率网格,例如 $p_c \leqslant 0.6$ (或其他概率)的网格
  • 在剩下的网格中
    • 挑选出具有最大 $p_c$ 值的网格
    • 丢弃那些与刚刚选出的网格的方框的 IoU 值大于 0.5 的网格(如果 IoU 大于某个阈值,这说明这两个方框重合度太高,便认为它们识别的是同一个物体)
    • 在剩下的网格中重复上述操作

如果检测是多种物体,比如汽车、行人、摩托车,那么正确的做法是:各自独立,进行三次“抑制非最大值”。

实际中的使用方法见下方的“非最大值抑制”。

锚框法 anchor boxes

目前看过的物件检测算法,有一个问题是每一个网格只能侦测一个物件,如果一个网格想要侦测多个物体,可以使用“锚框法 anchor boxes”。

对于上面这张图,我们发现人和汽车的中心点几乎重叠在一起,在一个格子里,如果输出 $y = \left[ \begin{array} { c } { p _ { c } } \\ { b _ { x } } \\ { b _ { y } } \\ { b _ { w } } \\ { b _ { w } } \\ { c _ { 1 } } \\ { c _ { 2 } \\ c_3 } \end{array} \right]$,那么它无法同时输出两个物体的方框,只能二选一,我们可以在这个网格画出两个锚框(也可能更多)框住这两个物体,如下图所示:

然后将输出的标签改为:

用锚框 1 来框住行人,锚框 2 来框住汽车。

在使用锚框前:训练图片中的每个物体被分给一个包含了它中心点的格子。输出维度 3×3×8。

使用锚框后:训练图片中的每个物体被分给(1)包含了它中心点的格子(2)这个格子里据有更高 IoU 的锚框。输出维度为 3×3×2×8。

举个例子:

标签值 $y=\left[ \begin{array} { l } { p _ { c } } \\ { b _ { x } } \\ { b _ { y } } \\ { b _ { h } } \\ { b _ { w } } \\ { c_ { 1 } } \\ { c _ { 2 } }\\ { c _ { 3 } } \\ { p _ { c } } \\ { b _ { x } } \\ { b _ { y } } \\ { b _ { h } } \\ { b _ { w } } \\ { c _ { 1 } } \\ { c _ { 2 } } \\ { c _ { 3 } } \end{array} \right]$,假如某个网格有两个物体,则为 $ \left[ \begin{array} { l } { 1 } \\ { b _ { x } } \\ { b _ { y } } \\ { b _ { h } } \\ { b _ { w } } \\ { 1 } \\ { 0}\\ { 0 } \\ { 1 } \\ { b _ { x } } \\ { b _ { y } } \\ { b _ { h } } \\ { b _ { w } } \\ { 0 } \\ { 1 } \\ { 0 } \end{array} \right] $,如果只有车,则为 $ \left[ \begin{array} { l } { 0 } \\ { ? } \\ { ?} \\ { ? } \\ { ? } \\ { ?} \\ { ?}\\ { ? } \\ { 1 } \\ { b _ { x } } \\ { b _ { y } } \\ { b _ { h } } \\ { b _ { w } } \\ { 0 } \\ { 1 } \\ { 0 } \end{array} \right] $

实际上,在一个网格处理两个物体的情况很少发生,尤其是当网格为 19×19 时。

YOLO 物体检测算法

综合上面所有要素,来组成目前最先进的目标检测算法——YOLO 算法。

构建训练集并训练

  • 三个分类类别:行人、汽车、摩托车
  • 两个锚框
  • 3×3 的网格划分(实际中一般是 19×19)
  • 遍历每张图片的 9 个网格,得到标签向量,维度是 3×3×2×8

进行预测

非最大值抑制

  • 每个网格都会得到两个预测的边界框(因为有两个锚框)

  • 计算每个方框的“分数”,如下图所示:

  • 去掉所有分数低于某个阈值的方框

  • 在剩下的方框中,对于分类的每个类别(行人、汽车、摩托车等),单独对每个预测的类别执行非最大值抑制

    • 挑选出分数最大的方框
    • 丢弃那些与刚刚分数最大方框的 IoU 值大于 0.5(或其他阈值) 的网格
      • 如果 IoU 大于某个阈值,这说明这两个方框重合度太高,便认为它们识别的是同一个物体
    • 除了分数最大方框的剩下的方框中,找出分数最大的,重复上述操作
    • 直到没有更低分数的方框存在,停止迭代,得到最终的预测框

微信捐赠
支付宝捐赠