目标检测是计算机视觉中急速发展的一个领域,它的效果随着这几年技术的发展也好了很多。
3.1目标定位
为了建立目标检测,我们先学习目标对象的定位。
之前我们已经介绍了图像分类,通过给你一张图像,能够给出图像中物体的类别。比如猫狗识别等。
而目标定位是不仅要识别出物体的类别,同时也负责生成一个物体的边框。
后面还会介绍目标检测,目标检测是需要对一张图像中多个物体全部检测出来并给出对应的类别和边框。
因此可以说,图像分类和分类并定位问题,通常来说只有一个对象。而目标检测通常会有很多个对象,而且是多个来自不同类别的对象。
下面本节课介绍目标分类并定位。
在图像分类中 我们在多层卷积网络中输入一张图像, 这会导致我们的卷积网络输出一个特征向量, 将特征向量传给一个可能是softmax 层,输出预测结果。
(假设你的输出有两种类别,那么softmax层就是有四个结果的输出)
如果我们想同时定位物体,需要改变我们的神经网络。
通过得到更多的输出单位,使得神经网络可以输出一个边框。
具体来说,是指我们的神经网络需要额外输出四个数字,分别是 x,y,w,h ,这四个数字决定了检查对象的边框的参数。
下面我们介绍如何在训练数据集上定义标签。
前提:
- 在一张图像中药识别的对象只有一个。
- 识别对象的类别有四种,分别是类别1、类别2、类别3、都不是。
类标签中有8个输出,分别表示是否有对象(1或0)、对象中心点的x坐标、对象中心点的y坐标、对象高度、对象宽度、是否属于类别1、是否属于类别2、是否属于类别3。
对于不是既定类别的图像,标签中的第一个值为0,后面的值无关紧要,因为也不会用来计算。
最后介绍损失函数。
当输出第一个值为1时,可以用平方差的和来表示损失;当输出第一个值为0时,仅需要对第一个值求平方。
3.2 特征点检测
Landmark detection
比如我们要建立一个人脸检测应用,我们需要算法输出某人的眼角在哪里。
一个点有x和y坐标,那么我们神经网络最后一层可以设置两个输出,分别是lx,ly
如果我们需要神经网络告诉我们眼角的所有四个角,我们可以 设置最后一层输出l1x, l1y,l2x,l2y,l3x,l3y,lx4,l4y
同理,我们可以定义人脸的N个关键点,(通过这N个关键点的位置可以用来判断一个人的行为)
并产生一个包含所有N个关键点的训练数据,那么我们设计输出的时候可以设置为2N+1, 2N是因为一个点有x和y两个坐标,最后加1表示是否是人脸。
注意关键点的位置输出顺序在不同图像中需要保持一致。
3.3 目标检测
本节课我们介绍使用卷积神经网络和滑动窗口(sliding windows)来进行目标检测。
首先我们先建立一个有标签的训练数据集,其中训练集中包含紧密剪裁的汽车样例。这里强调是紧密剪裁,就是指一张有车图像需要把多余的都剪掉,余下的部分作为训练数据集样例。
有了这个紧密剪裁的训练数据集,我们可以训练一个卷积神经网络。
当模型训练完成后,我们可以应用滑动窗口来进行目标检测。具体步骤如下:
对于给定的原始图像,选择一个小的尺寸,然后将这个小的矩形窗口的图像输入到卷积神经网络中。这里依次从左至右,从上至下的遍历小窗口,使整个图像的所有位置都被覆盖到。
注意这里遍历的次数取决于遍历的步长,当步长小的话,遍历的就会紧密,检测到目标的可能性会大。当步长大的话,遍历的就会宽松,检测到目标的可能性就减少。
当我们遍历完成一次后,我们接着用较大的窗口,来进行同样的遍历操作。
接着再用更大的窗口进行第三次遍历过程。
我们的期望是,如果图像中有一辆车,那么就会有某个窗口,输入这个窗口区域的图像,卷积神经网络就会检测到物体。
之所以称之为滑动窗口检测,是因为把这些窗口,按照一定的步长,滑过整个图像。来判断每个方框内是否有车。
缺点:计算成本高。
因为我们剪裁了很多不同的正方形图像,并让每个图像都单独通过卷积神经网络的运算。
如果步长大,通过卷积神经网络的窗口数量会减少,但比较粗糙的颗粒度会影响算法性能。
而如果步长小,那么小区域的数量会巨大,将他们都通过卷积神经网络,意味着很高的计算成本。
在深度学习流行前,人们使用简单的线性分类器,其计算成本低,使用滑动窗口还是有可行性的。
但基于卷积神经网络,计算成本高, 滑动窗口检测会很慢。而且除非使用很小的步长,否则很难在图像中精确的定位到目标。
3.4 卷积的滑动窗口实现
这节课学习如何通过卷积的形式来实现这个算法。
下面是介绍将如何将神经网络的全连接层转换为卷积层。
这里开始用卷积实现滑动窗口。
这里涉及滑动窗口卷积神经网络的输入是14143的图像。
图中第一行是转换成卷积层后的一个标准流程。
第二行是介绍当我们输入图像尺寸为16163时,一次卷积运算,实际上等同于之前把图像分割后的四次卷积运算。这样是让4次卷积神经网络的前向运算共享计算过程。利用这4个14*14的图像块的共同区域, 共享了大量的计算。
另外因为使用了最大池化,相当于在原来图像中以2为步长运行卷积神经网络。
第三行和第二行同理,只是采用了更大的输入图像。
后续:
这个算法还有一个缺点,是窗口边框的定位不精确。下一节会介绍改进。( 在上一节的课程中提到了多个不同的尺寸进行遍历,在这种方式下如何实现?现在这种理解就是只有和滑动窗口卷积神经网络的同一尺寸。)
3.5 Bounding Box 预测
上一节课中学习使用卷积的方式来高效的完成滑动窗口的运算。但存在检测物体的窗口边框不精确的问题。原因在于我们采用一个固定边框去滑动窗口,可能没有一个边框与物体的位置恰好吻合。
在这个图中,或许画出的框对于该物体来说是最吻合的,但一个物体的真正位置并不一定是正方形的。
这节课我们学习如何更精确的预测边界框。
YOLO算(YOU ONLY LOOK ONCE)法就是一个比较好的精确输出边界框的算法。
YOLO 的思想如下:
假设我们有一张100100的输入图像,我们要将其用网格进行划分, 这里演示我们使用33的网格(在实际上会使用到更精细的网格,目的是使得同一个网格内不容易出现两个物体。)
基本思路是把本周最初介绍的图像分类并定位的算法用到每一个网格中。
下面是如何定义用于训练的标签:
假设我们的类别是三,对于每一个网格,输出都是八个维度。
如果一个网格内没有目标,则第一个维度为0,后面的维度元素值无所谓。如果有目标,第一个维度元素为1,接着是目标中心点的x轴和y轴坐标,三个类别的bool值。
**这里需要注意:**把一个目标划分到某一个网格的依据是该目标的中心点属于哪个网格内。也即是说,虽然会存在一个物体跨越多个网格的情况,但它只能属于一个网络。
因此,对于33 9个网格的每一个,我们都有有一个8维的输出。那么总的输出大小就是33*8。也就是一张图像的Target output。
所以现在为了训练我们的神经网络,我们的输入大小是1001003,然后设计一个卷积神经网络,包括卷积层、最大池化等等,最终将它逐渐映射到338的输出上。
YOLO算法的优势在于能够精确的输出边界框。
我们通过输入一张图像,就能够得到输出中3*3中是0或1,对于1的又能得到边界框和类别。
这里有个后续再解决的问题,就是对于同一个网格中存在两个目标的情况。其中实际上我们会使用19*19这样更精细的网格,来尽量避免出现同一个网格出现两个物体。但这种也不能完全保证,具体解决方式在后续介绍。
补充:
如何决定边界框的参数bx,by,bh,和bw?
我们把左上角的点作为(0,0),右下角的点作为(1,1),所以要指定物体中心点在这个网格的相对位置,分别是在0到1到的范围内。(如果出了这个范围,说明中心点不在这个网格,那就不属于这个网格。而属于其他网格,也必然中心但的相对位置为0到1的值)。但物体的相对宽和高,都可以大于1,因为物体可能会跨越多个 网格。
总结
- YOLO 算法和之前介绍的图像分类并定位的算法十分相似,它会直接输出边界框的坐标位置,以及它允许你的神经网络输出任意长宽比的边界框。同时输出的坐标位置也更为精确,不再受限于滑动窗口的步长。
- 这个算法是通过卷积实现的,不需要在33的网格上执行这个算法9次。而是通过一次卷积网络过程,就使得所有33 网格所需的计算被大量的共享。所以它的效率是很高的。
- 论文比较难懂,但仍值得一读。
3.6 交并比
如何判断我们的目标检测算法是否有效?
这里我们介绍一个函数,叫交并比(Intersection Over Union),它是两个边界框重叠程度的一个度量方式。
交并比,是指计算两个区 域交集的部分比上两个区域并集的部分。
在计算机视觉领域的标准,如果IOU 大于等于0.5 说明结果被判断是正确的。如果预测的和真实的边界框完美重合,那么IOU=1.
一般用0.5作为一个临界值,来判断预测的边界框是否准确。如果想严格一点,也可以设置0.6或者其他数字。
3.7 非极大值抑制
目前所学的目标检测的问题之一是对同一个目标会有多次检测。
非极大值抑制是一种能够使得一个物体只得到一个检测结果的算法。
从技术上来书欧,这个车只有一个中心点,那么它应该被分配到一个网格单元中。
实际上,我们对每个网格都进行了目标分类和定位算法,不仅仅是一个网格可以决定这是否与是一辆车,可能会有多个网格都检测到这是一辆车,并给出了预测位置。
非极大值抑制要做的是清理这些检测,使每辆车只得到一个检测结果。
首先丢弃所有概率值小于0.6的检测框。
对于同一个预测类别下的检测框,选择概率最大的一个,作为目标检测框。
然后从所有剩下的检测框中,消除掉和该检测框IOU大于等于0.5的检测框。
然后再找到所有剩下检测框中,概率最大的一个,继续作为另一个检测目标的检测框。
然后从所有剩下的检测框中,消除掉和该检测框IOU大于等于0.5的检测框。
不断循环这个过程,直到每一个检测框,不是被输出作为预测结果,就是被抑制。
如果有N个类别,非极大值抑制过程就独立执行N次。
因此,我们可以看到非极大值抑制的本质是输出有着最大可能性的检测框,抑制那么非最大可能性的、且与最大可能性的检测框邻近的检测框。
3.8 Anchor Boxes
到目前为止 ,目标检测存在的一个问题是一个网格只能检测出一个对象。
如果想让一个网格检测出多个对象,可以使用anchor box。
举例说明:
在这张图中,行人的中心点和汽车的中心点,几乎在同一个位置,两者都落入到同一个网格中。
那么对于那个格子,如果我们检测的是三个类别行人、汽车和摩托,且y输出的向量8维向量,那么它将无法输出检测结果。
anchor box 的思想是预先设定两个anchor box ,然后将预测结果和这两个achor box 关联起来。一般来说,我们可能需要更多的anchor box ,可能五个或者更多。在本节课中我们用两个anchor box 。
所以我们要定义数据集的类别标签
前8个元素值是和anchor box1 相关的输出,后8个元素值是和anchor box2 相关的另外8个输出。
因为行人的形状和anchor box 1 更接近,我们使用前8个元素。汽车的形状和anchor box 2 更接近,我们使用后8个元素。
总结一下:
使用anchor box 之前:
对于训练数据集图像的每个对象,我们都是根据那个对象中点位置,分配到对应的网格中。对于33的网格,就会输出33*8。
使用anchor box 之后:
在训练数据集图像中的每个对象,仍然和之前一样,根据那个对象中点位置,分配到对应的网格中。
但是它还分配到一个和对象形状交并比最高的anchor box 。
所以当有两个anchor box时,当我们分析一个图像中的对象,就看它的边界框和哪一个anchor box 的交并比最高。
这样这个对象就不仅分配到网格,而是分配到一对(网格,anchor box)。
这就是对象在目标标签的编码方式。
(这里有个疑问:我们再设计标签时,有N个类别,就设置N*8的输出,然后N个类比的输出是有顺序的设置,这种不行吗?为什么要用物体实际边框与anchorbox 求交并比来确定在输出标签的位置呢?根据下一节的课程内容,这个过程是在训练标签设置阶段的过程
但对一个网格内有三个对象,这种情况算法处理不好;
还有一个情况是两个对象都分配到同一个anchor box,但他们的anchorbox 形状都一样。 这样的情况也处理不好。
另外anchor box 的目的是解决同一个网格中分配到两个对象的情况,这种情况在网格粒度很细的情况下比如19*19本身发生概率就很小。但确实也会发生。anchor box使得我们的学学习算法更加有针对性的处理。
最后,我们如何设定anchor box呢?
人们一般是手工指定anchor box形状,选择5到10个anchor box 形状,覆盖到多种不同的形状。还有更高级的做法,是YOLO V2版本中提到了采用Kmeans 算法
3.9 YOLO
训练阶段,构造训练数据集。
数据类别一共有三个类别,分别是行人、汽车、自行车。这里用了两个anchor box。 使用3*3 的网格,那么每个网格的输出是16维的向量。那么有物体的网格,就需要判断物体和哪个anchor IOU大,就关联到16维向量对应的输出中。
预测阶段:
输入一张图像,神经网络就会输出332*8大小的向量。
最后运用非极大值抑制。
3.10 候选区域
R-CNN
Fast R-CNN
Faster R-CNN