论文:链接
代码:TensorFlow版本
核心思想:将整张图片作为网络的输入,直接在输出层对BBox的位置和类别进行回归。
回顾:两阶段目标检测的实现过程:1、采用滑动窗口,对每个窗口进行分类和位置修正;2、用RPN网络提取候选区域,特征图对应的候选区域经过roipooling得到所需特征;3、SSD继承RPN类似的anchor机制,设定预设框并对每个预设框赋予groundtruth,全卷积网络训练目标。
在PASCAL VOC中,将一张448×448的输入图像,划分为7×7个网格(grid cell),每个网络预测2个bounding box,经过网络结构输出7730维的张量。
1):20个对象分类的概率
论文中YOLO支持识别20种不同的对象,所以这20个值表示该网格包含这20个类别对象的概率,记为:
2):两个bounding box的信息
每个bounding box需要4个数值来表示其位置,(Center_x,Center_y,width,height),即bounding box的中心点的x坐标,y坐标,bounding box的宽度,高度,2个bounding box共需要8个数值来表示其位置。(其中坐标的具体含义在后面代码中解释)
3):两个bounding box的置信度
bounding box的置信度 = 该bounding box内存在对象的概率 * 该bounding box与该对象实际bounding box的IOU
用公式表示为:
P r ( O b j e c t ) P_{r}\left ( Object \right ) Pr(Object) 是bounding box内存在对象的概率,区别于 P ( C i ∣ O b j e c t ) P\left ( C_{i} |Object \right ) P(Ci∣Object), P r ( O b j e c t ) P_{r}\left ( Object \right ) Pr(Object)并不管是哪个对象,它体现的是 有或没有 对象的概率,而 P ( C i ∣ O b j e c t ) P\left ( C_{i} |Object \right ) P(Ci∣Object) 意思是假设已经有一个对象在网格中了,这个对象具体是哪一个。 I O U p r e d t r u t h IOU_{pred}^{truth} IOUpredtruth 是 bounding box 与 object 真实bounding box 的IOU。要注意的是,现在讨论的30维向量中的bounding box是YOLO网络的输出,也就是预测的bounding box。所以 I O U p r e d t r u t h IOU_{pred}^{truth} IOUpredtruth 体现了预测的bounding box与真实bounding box的接近程度。但在测试阶段,并不知道object的真实bounding box,完全依赖网络的输出,这时是无法计算IOU的。
【总结】
30维向量 = 20个对象的概率 + 2个bounding box的置信度 + 2个bounding box * 4个坐标
1):一张图像最多能检测出49个对象
每个30维向量中只有一组(20个)对象分类的概率,也就只能预测出一个对象。所以输出的 7*7=49个 30维向量,最多表示出49个对象。
2):总共有49*2 = 98个候选区域(bounding box)
每个30维向量中有2组bounding box,所以总共是98个候选区
3):YOLO的bounding box并不是Faster RCNN的Anchor
Faster RCNN等一些算法采用每个grid中手工设置n个Anchor(先验框,预先设置好位置的bounding box)的设计,每个Anchor有不同的大小和宽高比。YOLO的bounding box看起来很像一个grid中2个Anchor,但它们不是。YOLO并没有预先设置2个bounding box的大小和形状,也没有对每个bounding box分别输出一个对象的预测。它的意思仅仅是对一个对象预测出2个bounding box,选择预测得相对比较准的那个。
论文中说明到:Our system divides the input image into an S*S grid. If the center of an object falls into a grid cell, that grid cell is responsible for detecting that object. 意思是说,物体的中心点落到哪个grid cell,这个grid cell就负责预测物体,也就是将物体归属到一个grid中。具体实现是计算出物体的中心位置,这个中心点落在哪个grid中,该grid对应的输出向量中该类别对象的概率为1,其他类别的概率为0.
YOLO predicts multiple bounding boxes per grid cell. At training time we only want one bounding box predictor to be responsible for each object. 这个意思是说一个grid产生多个 bounding box(论文中设置为2),在训练的时候只选取一个作为预测结果。(如何选取在后面代码中解释)
作为监督学习,首先要构造训练样本,才能让模型从中学习
对于一张输入的图像,其对应的输出是7×7×30张量(监督学习中的y或label)应该填写什么数据?
首先7×7对应的是7×7个输入的网格,30维向量分别是:
● 20个分类对象的概率
对于输入图像中的每个对象,先找到其中心点。比如上图中的自行车,其中心点在黄色圆点位置,中心点落在黄色网格内,所以这个黄色网格对应的30维向量中,自行车的概率是1,其它对象的概率是0。所有其它48个网格的30维向量中,该自行车的概率都是0。这就是所谓的"中心点所在的网格对预测该对象负责"。狗和汽车的分类概率也是同样的方法填写。
● 2个bounding box的位置
训练样本的bounding box位置应该填写对象实际的bounding box,但一个对象对应了2个bounding box,该填哪一个呢?这里有两种实现方式:①将这两个bounding box的位置都填写为实际物体的 bounding box;②填写一个bounding box为实际物体的值,在后面计算loss中进行维度扩展。其实这两种实现方式本质都是一样的。(具体实现过程可参考原码)
● 2个bounding box的置信度
用网络输出的2个bounding box与对象真实bounding box一起计算出IOU。
然后看2个bounding box的IOU,哪个比较大(更接近对象实际的bounding box),就由哪个bounding box来负责预测该对象是否存在,即该bounding box的 P r ( O b j e c t ) P_{r}\left ( Object \right ) Pr(Object) =1,同时对象真实bounding box的位置也就填入该bounding box。另一个不负责预测的bounding box的 P r ( O b j e c t ) P_{r}\left ( Object \right ) Pr(Object) =0.
总的来说就是,与对象实际bounding box最接近的那个bounding box,其 confidence= I O U p r e d t r u t h IOU_{pred}^{truth} IOUpredtruth,该网格的其它bounding box的confidence=0.
举个例子,比如上图中自行车的中心点位于4行3列网格中,所以输出tensor中4行3列位置的30维向量如下图所示(图源水印)。
损失函数就是网络的实际输出值与样本标签值之间的偏差
YOLO的损失函数计算如下:
公式中
I i o b j I_{i}^{obj} Iiobj 是网格i中存在对象;
I i j o b j I_{ij}^{obj} Iijobj 是网格i中的第j个bounding box存在对象;
I i j n o o b j I_{ij}^{noobj} Iijnoobj 是网格i中的第j个bounding box中不存在对象;
总的来说,就是用网络输出与样本标签的各项内容的误差平方和作为一个样本的整体误差。 损失函数中的几个项是与输出的30维向量中的内容相对应的。
1):对象分类误差
公式第5行,注意 I i o b j I_{i}^{obj} Iiobj 意味着存在对象的网格才计入误差。
2):bounding box的位置误差
公式第1行和第2行。
a)都带有 I i j o b j I_{ij}^{obj} Iijobj 意味着只有"负责"(IOU比较大)预测的那个bounding box的数据才会计入误差。
b)第2行宽度和高度先取了平方根,论文中的解释是 Sum-squared error also equally weights errors in large
boxes and small boxes. Our error metric should reflect that small deviations in large boxes matter less than in small boxes. To partially address this we predict the square root of the bounding box width and height instead of the width and height directly. 意思是说对不同大小的边界框,较小边界框的误差应该要比较大边界框的误差更敏感,所以将边界框的宽高预测改为对其平方根的预测。如下图所示:
c)乘以 λ c o o r d \lambda_{coord} λcoord 调节bounding box位置误差的权重(相对分类误差和置信度误差)。论文中设置 λ c o o r d \lambda_{coord} λcoord=5 ,即调高位置误差的权重。
3):bounding box的置信度误差
公式第3行和第4行。
a)第3行是存在对象的bounding box的置信度误差。带有 I i j o b j I_{ij}^{obj} Iijobj 意味着只有"负责"(IOU比较大)预测的那个bounding box的置信度才会计入误差。
b)第4行是不存在对象的bounding box的置信度误差。乘以 λ n o o b j \lambda_{noobj} λnoobj 调节不存在对象的bounding box的置信度的权重(相对其它误差)。论文中设置 λ n o o b j \lambda_{noobj} λnoobj=0.5 ,即调低不存在对象的bounding box的置信度误差的权重。
YOLO先使用ImageNet数据集对前20层卷积网络进行预训练,然后使用完整的网络,在PASCAL VOC数据集上进行对象识别和定位的训练和预测。YOLO的网络结构如下图所示:
YOLO的最后一层采用线性激活函数,其它层都是Leaky ReLU。训练中采用了drop out和数据增强(data augmentation)来防止过拟合。
每个网格预测的class信息 P r ( C l a s s i ∣ O b j e c t ) P_{r}\left ( Class_{i}|Object \right ) Pr(Classi∣Object) 和 bounding box预测的confidence信息 P r ( O b j e c t ) ∗ I O U p r e d t r u t h P_{r}\left ( Object \right )*IOU_{pred}^{truth} Pr(Object)∗IOUpredtruth 相乘,就得到每个bounding box的class-specific confidence score。即
在yolo的预测过程中,使用物体的类别预测最大值p乘以预测框的最大值c,作为输出预测物体的置信度。假设在预测中输入一张图片,不考虑batch,最终网络输出 7×7×30 的张量。可以划分为三个部分:类别概率部分 [7, 7, 20],置信度部分 [7, 7, 2],边界框部分 [7, 7, 2, 4]。根据上面的公式,将前两项进行相乘 [7, 7, 1, 20] 和 [7,7,2,1],(各补一个维度)得到类别置信度 [7, 7, 2, 20], 总共预测了 7×7×2 = 98 个。
数据已经有了,那如何得到检测框的结果呢?有两种处理方法
方法一:
①对每个预测框选取置信度最大的那个类别作为其预测标签,得到每个预测框的预测类别及置信度,大小是 [7, 7, 2];
②设置置信度阈值,将小于阈值的box过滤掉,经过这层处理后剩余的是置信度较高的box;
③经过②处理后对剩余的box使用NMS算法,最后留下的就是检测结果。
这里需要注意的是NMS对所有的框一视同仁还是区分类别使用NMS,不过在代码里是同等对待所有的框的。
方法二:
先使用NMS,然后再确定各个box的类别。其基本过程如下图所示。对于98个boxes,首先将小于置信度阈值的值归0,然后分类别地对置信度值采用NMS,这里NMS处理结果不是剔除,而是将其置信度值归为0。最后才是确定各个box的类别,当其置信度值不为0时才做出检测结果输出。
YOLO以速度见长,处理速度可以达到45fps,其快速版本(网络较小)甚至可以达到155fps。这得益于其识别和定位合二为一的网络设计,而且这种统一的设计也使得训练和预测可以端到端的进行,非常简便。
不足之处是小对象检测效果不太好(尤其是一些聚集在一起的小对象),对边框的预测准确度不是很高,总体预测精度略低于Fast RCNN。主要是因为网格设置比较稀疏,而且每个网格只预测两个边框,另外Pooling层会丢失一些细节信息,对定位存在影响。