目标检测 - -DeepLearning.ai 学习笔记(4-3)

课程笔记地址https://blog.csdn.net/column/details/26931.html
课程代码地址https://github.com/duboya/DeepLearning.ai-pragramming-code/tree/master
欢迎大家forkstar!(-O-)

卷积神经网络 — 目标检测

1. 目标定位和特征点检测

图片检测问题:

  • 分类问题:判断图中是否为汽车;
  • 目标定位:判断是否为汽车,并确定具体位置;
  • 目标检测:检测不同物体并定位。

目标分类和定位:

对于目标定位问题,我们卷积神经网络模型结构可能如下:

输出:包含图片中存在的对象及定位框

  • 行人,0 or 1;
  • 汽车,0 or 1;
  • 摩托车,0 or 1;
  • 图片背景,0 or 1;
  • 定位框: b x b_x bx b y b_y by b h b_h bh b w b_w bw
    其中, b x b_x bx b y b_y by表示汽车中点, b h b_h bh b w b_w bw分别表示定位框的高和宽。以图片左上角为(0,0),以右下角为(1,1),这些数字均为位置或长度所在图片的比例大小。

目标标签 y:

  • P c P_c Pc = 1时,表示图片中存在物体;
  • P c P_c Pc = 0时,表示图片中不存在物体,那么此时,输出y的其他值为多少均没有意义,也不会参与损失函数的计算:

[ 0 ? ? … ? ] \begin{bmatrix} 0\\?\\?\\ \dots\\? \end{bmatrix} 0???

损失函数:

如果采用平方误差形式的损失函数:

  • P c = 1 P_c = 1 Pc=1时:

L ( y ^ , y ) = ( y ^ 1 − y 1 ) 2 + ( y ^ 2 − y 2 ) 2 + ⋯ + ( y ^ 8 − y 8 ) 2 L(\hat{y},y) = (\hat{y}_1 - y_1)^2 + (\hat{y}_2 - y_2)^2 + \dots + (\hat{y}_8 - y_8)^2 L(y^,y)=(y^1y1)2+(y^2y2)2++(y^8y8)2

此时,我们需要关注神经网络对所有输出值的准确度;

  • P c = 0 P_c = 0 Pc=0时:
    L ( y ^ , y ) = ( y ^ 1 − y 1 ) 2 L(\hat{y},y) = (\hat{y}_1 - y_1)^2 L(y^,y)=(y^1y1)2
    此时,我们只关注神经网络对背景值的准确度。

当然在实际的目标定位应用中,我们可以使用更好的方式是:

  • c 1 c_1 c1 c 2 c_2 c2 c 3 c_3 c3 和 softmax 使用对数似然损失函数;
  • 对边界框的四个值应用平方误差或者类似的方法;
  • P c P_c Pc 应用 logistic regression 损失函数,或者平方预测误差。

特征点检测:

由前面的目标定位问题,我们可以知道,神经网络可以通过输出图片上特征点的坐标(x, y),来实现对目标特征的识别和定位标记。

如对于人脸表情识别的问题中,我们通过标定训练数据集中特征点的位置信息,来对人脸进行不同位置不同特征的定位和标记。AR的应用就是基于人脸表情识别来设计的,如脸部扭曲、增加头部配饰等。

在人体姿态检测中,同样可以通过对人体不同的特征位置关键点的标注,来记录人体的姿态。

2. 目标检测

目标检测采用的是基于滑动窗口的检测算法。

训练模型:

  • 训练集X:将有汽车的图片进行适当的剪切,剪切成整张几乎都被汽车占据的小图或者没有汽车的小图;
  • 训练集Y:对X中的图片进行标注,有汽车的标注1,没有汽车的标注0。

滑动窗口目标检测:

利用滑动窗口在实际图片中实现目标检测。

  • 首先选定一个特定大小的窗口,将窗口内的图片输入到模型中进行预测;
  • 以固定步幅滑动该窗口,遍历图像的每个区域,对窗内的各个小图不断输入模型进行预测;
  • 继续选取一个更大的窗口,再次遍历图像的每个区域,对区域内是否有车进行预测;
  • 遍历整个图像,可以保证在每个位置都能检测到是否有车。

缺点:计算成本巨大,每个窗口的小图都要进行卷积运算,(但在神经网络兴起之前,使用的是线性分类器,所以滑动窗口算法的计算成本较低)。

卷积层替代全连接层:

对于卷积网络中全连接层,我们可以利用 1 × 1 1 \times 1 1×1大小卷积核的卷积层来替代。

在上一周课程中,Ng讲授过 1 × 1 1 \times 1 1×1 的卷积核相当于在一个三维图像的切片上应用了一个全连接的神经网络。同样,全连接层也可以由 1 × 1 1 \times 1 1×1 大小卷积核的卷积层来替代。需注意卷积核的个数与隐层神经元个数相同(即保证输出具有相同的channel)。

滑动窗口的卷积实现:

在我们实现了以卷积层替代全部的全连接层以后,在该基础上进行滑动窗口在卷积层上的操作。下面以一个小的图片为例:

我们以上面训练好的模型,输入一个16x16x3大小的整幅图片,图中蓝色部分代表滑动窗口的大小。我们以 1 为大小的步幅滑动窗口,分别与卷积核进行卷积运算,最后得到4幅10×10×16大小的特征图,然而因为在滑动窗口的操作时,输入部分有大量的重叠,也就是有很多重复的运算,导致在下一层中的特征图值也存在大量的重叠,所以最后得到的第二层激活值(特征图)构成一副12×12×16大小的特征图。对于后面的池化层和全连接层也是同样的过程。

注:上述视图中第二行图像输入本意并非是指 stride = 2,而是意值 16x16x3 图像可以看做是由 4 个 14x14x3 的图像得到,而之所以是选用 4 个 14x14x3 图像得到的原因是:单个 14x14x3 进行 5x5 卷积操作的结果可以看做是 16x16x3 由 4 个 14x14x3 进行 5x5 卷积操作后合并得到(存在大量公共区域,只有边缘两个两列像素点为独有),这种变换的原因的目的还是一个:即共享重叠区域的运算。

那么由此可知,滑动窗口在整幅图片上进行滑动卷积的操作过程,就等同于在该图片上直接进行卷积运算的过程。所以卷积层实现滑动窗口的这个过程,我们不需要把输入图片分割成四个子集分别执行前向传播,而是把他们作为一张图片输入到卷积神经网络中进行计算,其中的重叠部分(公共区域)可以共享大量的计算。

汽车目标检测:

依据上面的方法,我们将整张图片输入到训练好的卷积神经网络中。无需再利用滑动窗口分割图片,只需一次前向传播,我们就可以同时得到所有图片子集的预测值。

利用卷积的方式实现滑动窗口算法的方法,提高了整体的计算效率。

将卷积核的滑动卷积操作与滑窗的滑动操作结合,无需再利用滑动窗口分割图片,只需一次前向传播,我们就可以同时得到所有图片子集的预测值,大大提升了检测效率!

3. Bounding Box 预测

前面一节的卷积方式实现的滑动窗口算法,使得在预测时计算的效率大大提高。但是其存在的问题是:不能输出最精准的边界框(Bounding Box)。

在滑动窗口算法中,我们取的一些离散的图片子集的位置,在这种情况下,有可能我们没有得到一个能够完美匹配汽车位置的窗口,也有可能真实汽车的边界框为一个长方形。所以我们需要寻找更加精确的边界框。

YOLO:

YOLO算法可以使得滑动窗口算法寻找到更加精准的边界框。

  • 在整幅图片上加上较为精细的网格,将图片分割成 n × n n \times n n×n 个小的图片;
  • 采用图像分类和定位算法,分别应用在图像的 n × n n \times n n×n 个格子中。
  • 定义训练标签:(对于每个网格,定义如前面的向量 y i y_i yi
    y i = [ P c   b x   b y   b h   b w   c 1   c 2   c 3 ] y_i = [P_c \ b_x \ b_y \ b_h \ b_w \ c_1 \ c_2 \ c_3] yi=[Pc bx by bh bw c1 c2 c3]
    对于不同的网格 i 有不同的标签向量 y i y_i yi
  • n × n n \times n n×n个格子标签合并在一起,最终的目标输出Y的大小为: n × n × 8 n \times n \times 8 n×n×8(这里8是因为例子中的目标值有8个)。

通过这样的训练集训练得到目标探测的卷积网络模型。我们利用训练好的模型,将与模型输入相同大小的图片输入到训练好的网络中,得到大小为n×n×8的预测输出。通过观察n×n不同位置的输出值,我们就能知道这些位置中是否存在目标物体,然后也能由存在物体的输出向量得到目标物体的更加精准的边界框

个人觉得这里已经潜意思地表达了对于bounding box,当unit cell不能包含完整detected objection时,要联合周围输出向量来一起探测,毕竟此时,周围向量也往往同时认为detecting objection 的midpoint 在自己中,只是对应的 p c p_c pc比较小,要被后面的Non-max supression抑制,但其可以协助bounding box,如将与对应 p c p_c pc最高的unit cell交并比不为0的unit cell联合到 p c p_c pc最高的unit cell中,再次做目标识别与定位及可得到完整的bounding box。

上方想法是错误的,不用担心当 unit cell 不能完全包括物体,因为要多次划分不同尺度的 unit cell,如 1 ∗ * 1, 2 ∗ * 2, 4 ∗ * 4, …, 19 ∗ * 19,这样总是能有起码一种以上的 unit cell 可以完全包括待检测物体,而事实上经常出现的情况是一个物体被多次被 unit cell 包括,也诞生了多种 bounding box ,这时候,才是依据 P c P_c Pc 进行选择,然后进行 NMS (非最大值抑制) 来排除干扰项的过程!

YOLO notation:

  • 将对象分配到一个格子的过程是:观察对象的中点,将该对象分配到其中点所在的格子中,(即使对象横跨多个格子,也只分配到中点所在的格子中,其他格子记为无该对象,即标记为“0”);
  • YOLO显式地输出边界框,使得其可以具有任意宽高比,并且能输出更精确的坐标,不受滑动窗口算法滑动步幅大小的限制;
  • YOLO是一次卷积实现,并不是在 n×n 网格上进行 n 2 n^2 n2次运算,而是单次卷积实现,算法实现效率高,运行速度快,可以实现实时识别。

bounding boxes 细节:

利用YOLO算法实现目标探测的时候,对于存在目标对象的网格中,定义训练标签Y的时候,边界框的指定参数的不同对其预测精度有很大的影响。这里给出一个较为合理的约定:(其他定值方式可阅读论文)

  • 对于每个网格,以左上角为(0,0),以右下角为(1,1);
  • 中点bx、by表示坐标值,在0~1之间;
  • 宽高bh、bw表示比例值,存在>1的情况。

注:这里自己是有个问题的,当利用YOLO算法划分的网络不能一个grid cell包含一个检测对象时,即对应的bh, bw > 1时,是如何检测的。毕竟此时输入图片是该检测对象的一部分,仅仅通过输入图像能确定该grid cell包含此检测对象,不能确定完整的bounding box,此时,如何知道完整的目标边框大小呢?是将周围几个小的grid unit合并在一起再次重新进行 检测边框吗?

这才是 YOLO 算法实质(通过对图像进行多次不同尺度划分,如 1 ∗ * 1、2 ∗ * 2、4 ∗ * 4、10 ∗ * 10乃至19 ∗ * 19,划分越细,计算量越大,通过每次划分都进行一次对象检测,“得到对同一个对象的多次检测,也就是在一个对象上有多个具有重叠的不同的边界框;” 这样可总是能找到一个 bouding box 可以完全包括待检测物体,这时候对应最大的 P c P_c Pc,也正是因为这个过程,诞生了一系列 “一个对象上有多个具有重叠的不同的边界框”,接下来就是使用 NMS 过程,“也就是说抑制那些不是最大值,却比较接近最大值的边界框。”)

4. 交并比(Intersection-over-Union)

交并比函数用来评价目标检测算法是否运作良好。

对于理想的边界框和目标探测算法预测得到的边界框,交并比函数计算两个边界框交集和并集之比。

I o U = 交 集 面 积 并 集 面 积 IoU = \frac{交集面积}{并集面积} IoU=

一般在目标检测任务中,约定如果 IoU⩾0.5 ,那么就说明检测正确。当然标准越大,则对目标检测算法越严格。得到的IoU值越大越好。

注:这里的IoU算的是检测标注有目标对象的框与实际对象真实框之间的IoU,故而当检测边框与实际边框完美重合时,IoU = 1,当不完美时候也需满足IoU > 0.5 才被认定为检测正确(当检测到对象的IoU < 0.5时,说明检测边框内只含有目标边框的一小部分,不被认为是检测正确,此时,检测准确的边框更大可能在附近其他边框),IoU标准越高,边框检测要求越高。“More generally, loU is a measure of the overlap between bounding boxes. --Andrew Ng”

5. 非最大值抑制(non-max suppression,NMS)

对于我们前面提到的目标检测算法,可能会对同一个对象做出多次的检测,非最大值抑制可以确保我们的算法对每个对象只检测一次。

多网格检测同一物体:

对于汽车目标检测的例子中,我们将图片分成很多精细的格子。最终预测输出的结果中,可能会有相邻的多个格子里均检测出都具有同一个对象。

NMS算法思想:

  • 在对 n × n n \times n n×n个网格进行目标检测算法后,每个网格输出的 P c P_c Pc 为一个0~1的值,表示有车的概率大小。其中会有多个网格内存在高概率;
  • 得到对同一个对象的多次检测,也就是在一个对象上有多个具有重叠的不同的边界框;
  • 非最大值抑制对多种检测结果进行清理:选取最大 P c P_c Pc的边界框,对所有其他与该边界框具有高交并比或高重叠的边界框进行抑制;
  • 逐一审视剩下的边界框,寻找最高的 P c P_c Pc值边界框,重复上面的步骤。
  • 非最大值抑制,也就是说抑制那些不是最大值,却比较接近最大值的边界框。

这才是 YOLO 算法实质(通过对图像进行多次不同尺度划分,如 11、22、44、1010乃至19*19,划分越细,计算量越大,通过每次划分都进行一次对象检测,“得到对同一个对象的多次检测,也就是在一个对象上有多个具有重叠的不同的边界框;” 这样可总是能找到一个 bouding box 可以完全包括待检测物体,这时候对应最大的 P c P_c Pc,也正是因为这个过程,诞生了一系列 “一个对象上有多个具有重叠的不同的边界框”,接下来就是使用 NMS 过程,“也就是说抑制那些不是最大值,却比较接近最大值的边界框。”)

NMS算法:

以单个对象检测为例:

  • 对于图片每个网格预测输出矩阵: y i = [ P c   b x   b y   b h   b w ] y_i=[P_c \ b_x \ b_y \ b_h \ b_w] yi=[Pc bx by bh bw],其中 P c P_c Pc表示有对象的概率;
  • 抛弃 P c ≤ 0.6 P_c \le 0.6 Pc0.6 的边界框;
  • 对剩余的边界框(while):
    • 选取最大 P c P_c Pc值的边界框,作为预测输出边界框;
    • 抛弃边界框 I o U ≤ 0.5 IoU \le 0.5 IoU0.5的剩余的边界框。

对于多对象检测,输出标签中就会有多个分量。正确的做法是:对每个输出类别分别独立进行一次非最大值抑制。

6. Anchor box

通过上面的各种方法,目前我们的目标检测算法在每个格子上只能检测出一个对象。使用Anchor box 可以同时检测出多个对象。

重叠目标:

对于重叠的目标,这些目标的中点有可能会落在同一个网格中,对于我们之前定义的输出: y i = [ P c   b x   b y   b h   b w   c 1   c 2   c 3 ] y_i=[P_c \ b_x \ b_y \ b_h \ b_w \ c_1 \ c_2 \ c_3] yi=[Pc bx by bh bw c1 c2 c3],只能得到一个目标的输出。

而Anchor box 则是预先定义多个不同形状的Anchor box,我们需要把预测目标对应地和各个Anchor box 关联起来,所以我们重新定义目标向量:
y i = [ 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 ⋯ &ThinSpace; ] y_i=[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 \cdots] yi=[Pc bx by bh bw c1 c2 c3 Pc bx by bh bw c1 c2 c3]

用这样的多目标向量分别对应不同的Anchor box,从而检测出多个重叠的目标。

注:需要说明的是这里检测多个重叠目标是指重叠目标具有不同的anchor box,如果重叠目标具有相同的anchor box,如都是瘦长或者都是宽胖,则无法用anchor box处理(毕竟一个anchor box只能对应检测一种对象),此外,当一个grid cell中具有三个以上detecting objection midpoint时候,也是不好处理,对于以上两种情况,往往采用一些默认处理方式来打破僵局。(事实上,当利用YOLO算法把grid划分比较细的时候,如这里用19x19,将两个以上objection midpoint划分到同一个grid cell的概率是很小的)

  • 不使用Anchor box:训练图片中的每个对象,根据对象的中点,分配到对应的格子中。输出大小(例如8): n × n × 8 n \times n \times 8 n×n×8

  • 使用Anchor box:训练图片的每个对象,根据对象的中点,分配到对应的格子中,同时还分配到一个和对象形状的IoU最高的Anchor box 中。输出大小(例如两个Anchor box): n × n × 16 n \times n \times 16 n×n×16

例子:

如下面的图片,里面有行人和汽车,我们为其分配两个Anchor box。对于行人形状更像Anchor box 1,汽车形状更像Anchor box 2,所以我们将人和汽车分配到不同的输出位置。

如果格子中只有汽车的时候,我们使用了两个Anchor box,那么此时我们的目标向量就成为:
y i = [ 0   ?   ?   ?   ?   ?   ?   ?   1   b x   b y   b h   b w   0   1   0 ] y_i = [0 \ ? \ ? \ ? \ ? \ ? \ ? \ ? \ 1 \ b_x \ b_y \ b_h \ b_w \ 0 \ 1 \ 0] yi=[0        1 bx by bh bw 0 1 0]
其中,“?”代表的是该位置是什么样的参数我们都不关系。

难点问题:

  • 如果我们使用了两个Anchor box,但是同一个格子中却有三个对象的情况,此时只能用一些额外的手段来处理;

  • 同一个格子中存在两个对象,但它们的Anchor box 形状相同,此时也需要引入一些专门处理该情况的手段。

但是以上的两种问题出现的可能性不会很大,对目标检测算法不会带来很大的影响。

Anchor box 的选择:

  • 一般人工指定Anchor box 的形状,选择5~10个以覆盖到多种不同的形状,可以涵盖我们想要检测的对象的形状;

  • 高级方法:K-means 算法:将不同对象形状进行聚类,用聚类后的结果来选择一组最具代表性的Anchor box,以此来代表我们想要检测对象的形状。

7. YOLO算法目标检测

假设我们要在图片中检测三种目标:行人、汽车和摩托车,同时使用两种不同的Anchor box。

训练集:

  • 输入X:同样大小的完整图片;

  • 目标Y:使用3×3网格划分,输出大小3×3×2×8,或者3×3×16;

  • 对不同格子中的小图,定义目标输出向量Y。

模型预测:

输入与训练集中相同大小的图片,同时得到每个格子中不同的输出结果: 3 × 3 × 2 × 8 3 \times 3 \times 2 \times 8 3×3×2×8

运行非最大值抑制(NMS):

  • 假设使用了2个Anchor box,那么对于每一个网格,我们都会得到预测输出的2个bounding boxes,其中一个 P c P_c Pc比较高;

  • 抛弃概率 P c P_c Pc值低的预测bounding boxes;

  • 对每个对象(如行人、汽车、摩托车)分别使用NMS(non-max supression algorithm)算法得到最终的预测边界框。

8. 候选区域(region proposals)

R-CNN:

R-CNN(Regions with convolutional networks),会在我们的图片中选出一些目标的候选区域,从而避免了传统滑动窗口在大量无对象区域的无用运算。

所以在使用了R-CNN后,我们不会再针对每个滑动窗口运算检测算法,而是只选择一些候选区域的窗口,在少数的窗口上运行卷积网络。

具体实现:运用图像分割算法,将图片分割成许多不同颜色的色块,然后在这些色块上放置窗口,将窗口中的内容输入网络,从而减小需要处理的窗口数量。

更快的算法:

  • R-CNN:给出候选区域,对每个候选区域进行分类识别,输出对象 标签bounding box,从而在确实存在对象的区域得到更精确的边界框,但速度慢;
  • Fast R-CNN:给出候选区域,使用滑动窗口的卷积实现去分类所有的候选区域,但得到候选区的聚类步骤仍然非常慢;
  • Faster R-CNN:使用卷积网络给出候选区域。

注:目前来看,即便是faster R-CNN,相对于YOLO算法依旧是比较慢,Ng个人目前更倾向于YOLO算法,其直接将图像进入前馈输入进行判别,可以达到实时检测。

注:补充参考自:
https://blog.csdn.net/koala_tree/article/details/78597575

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值