全文转载,仅供自己学习,侵删。
RCNN:我们先来研究一下图片,嗯,这些位置很可能存在一些对象,你们对这些位置再检测一下看到底是哪些对象在里面。
YOLO:我们把图片大致分成98个区域,每个区域看下有没有对象存在,以及具体位置在哪里。
RCNN:你这么简单粗暴真的没问题吗?
YOLO:当然没有…咳,其实是有一点点问题的,准确率要低一点,但是我非常快!快!快!
RCNN:为什么你用那么粗略的候选区,最后也能得到还不错的bounding box呢?
YOLO:你不是用过边框回归吗?我拿来用用怎么不行了。
一、算法大致讲解:
1、简述:
RCNN虽然会找到一些候选区,但毕竟只是候选,等真正识别出其中的对象以后,还要对候选区进行微调,使之更接近真实的bounding box。这个过程就是边框回归:将候选区bounding box调整到更接近真实的bounding box。既然反正最后都是要调整的,干嘛还要先费劲去寻找候选区呢,大致有个区域范围就行了,所以YOLO就这么干了。
实际上,YOLO并没有真正去掉候选区,而是采用了预定义的候选区(准确点说应该是预测区,因为并不是Faster RCNN所采用Anchor)。也就是将图片划分为 7x7=49 个网格(grid),每个网格允许预测出2个边框(bounding box,包含某个对象的矩形框),总共 49x2=98 个bounding box。可以理解为98个候选区,它们很粗略的覆盖了图片的整个区域。
2、结构
去掉候选区这个步骤以后,YOLO的结构非常简单,就是单纯的卷积、池化最后加了两层全连接。单看网络结构的话,和普通的CNN对象分类网络几乎没有本质的区别,最大的差异是最后输出层用线性函数做激活函数,因为需要预测bounding box的位置(数值型),而不仅仅是对象的概率。所以粗略来说,YOLO的整个结构就是输入图片经过神经网络的变换得到一个输出的张量,如下图所示。
因为只是一些常规的神经网络结构,所以,理解YOLO的设计的时候,重要的是理解输入和输出的映射关系.
3、算法综述:
算法首先把输入图像划分成SxS的格子,然后对每个格子都预测B个bounding boxes,每个bounding box都包含5个预测值:x,y,w,h和confidence。x,y就是bounding box的中心坐标,与grid cell对齐(即相对于当前grid cell的偏移值),使得范围变成0到1;w和h进行归一化(分别除以图像的w和h,这样最后的w和h就在0到1范围)。每个bounding box都对应一个confidence score,如果grid cell里面没有object,confidence就是0,如果有,则confidence score等于预测的box和ground truth的IOU值。
所以如何判断一个grid cell中是否包含object呢?
答案是:如果一个object的ground truth的中心点坐标在一个grid cell中,那么这个grid cell就是包含这个object,也就是说这个object的预测就由该grid cell负责。
每个grid cell都预测C个类别概率,表示一个grid cell在包含object的条件下属于某个类别的概率。在本文中作者取S=7,B=2,C=20(因为PASCAL VOC有20个类别),所以最后有7x7x30个tensor。(每个格子产生2个bounding box,每个bounding box产生5个数,2x5=10,每个格子再产生20个分类的分数,加一起,一个格子产生了30个数。)
其实就是:把原图划分成7x7的格子,每个格子会产生两个bounding box,每个bounding box产生五个数,包括坐便位移,尺度缩放,以及confidence。与此同时每个格子产生分类20个分类的分数。
虽然每个格子可以预测B个bounding box,但是最终只选择只选择IOU最高的bounding box作为物体检测输出,即每个格子最多只预测出一个物体。当物体占画面比例较小,如图像中包含畜群或鸟群时,每个格子包含多个物体,但却只能检测出其中一个。这是YOLO方法的一个缺陷。
为什么这么说呢?
是因为:在测试阶段,每个格子产生了2个bounding box,每个bounding box的confidence的值去乘以类别的score,类别的score是一样的,导致bounding box的confidence高的产生的最终类别分数也会高,然后在进行NMS非极大值抑制的时候,就会把低的分数去除掉的。所以说:最终只选择只选择IOU最高的bounding box作为物体检测输出,即每个格子最多只预测出一个物体。
二、算法细节讲解&总结:
1、输入
输入就是原始图像,唯一的要求是缩放到448x448的大小。主要是因为YOLO的网络中,卷积层最后接了两个全连接层,全连接层是要求固定大小的向量作为输入,所以倒推回去也就要求原始图像有固定的尺寸。那么YOLO设计的尺寸就是448x448。
2、输出
输出是一个 7x7x30 的张量(tensor)。
3、输入和输出的映射关系
4、7*7网格
根据YOLO的设计,输入图像被划分为 7x7 的网格(grid),输出张量中的 7x7 就对应着输入图像的 7x7 网格。或者我们把 7x7x30 的张量看作 7x7=49个30维的向量,也就是输入图像中的每个网格对应输出一个30维的向量。参考上面图5,比如输入图像左上角的网格对应到输出张量中左上角的向量。
要注意的是,并不是说仅仅网格内的信息被映射到一个30维向量。经过神经网络对输入图像信息的提取和变换,网格周边的信息也会被识别和整理,最后编码到那个30维向量中。
5、30维向量
具体来看每个网格对应的30维向量中包含了哪些信息。
① 20个对象分类的概率
因为YOLO支持识别20种不同的对象(人、鸟、猫、汽车、椅子等),所以这里有20个值表示该网格位置存在任一种对象的概率。
② 2个bounding box的位置
每个bounding box需要4个数值来表示其位置,(Center_x,Center_y,width,height),即(bounding box的中心点的x坐标,y坐标,bounding box的宽度,高度),2个bounding box共需要8个数值来表示其位置。
③ 2个bounding box的置信度
bounding box的置信度 = 该bounding box内存在对象的概率 * 该bounding box与该对象实际bounding box的IOU
用公式来表示就是:
其中,若bounding box包含物体,则P(object) = 1;否则P(object) = 0。
IOU(intersection over union)为预测bounding box与物体真实区域的交集面积(以像素为单位,用真实区域的像素面积归一化到[0,1]区间)。
每个bounding box都对应一个confidence score,如果grid cell里面没有object,confidence就是0,如果有,则confidence score等于预测的box和ground truth的IOU值。
所以如何判断一个grid cell中是否包含object呢?
答案是:如果一个object的ground truth的中心点坐标在一个grid cell中,那么这个grid cell就是包含这个object,也就是说这个object的预测就由该grid cell负责。
综合来说,一个bounding box的置信度Confidence意味着它 是否包含对象且位置准确的程度。置信度高表示这里存在一个对象且位置比较准确,置信度低表示可能没有对象 或者 即便有对象也存在较大的位置偏差。
注意:class 信息是针对每个网格的,confidence 信息是针对每个 bounding box 的。
在 test 的时候,每个网格预测的 class 信息和 bounding box 预测的 confidence信息相乘,就得到每个 bounding box 的 class-specific confidence score:
等式左边第一项就是每个网格预测的类别信息,第二、三项就是每个 bounding box 预测的 confidence。这个乘积即 encode 了预测的 box 属于某一类的概率,也有该 box 准确度的信息。
得到每个 box 的 class-specific confidence score 以后,设置阈值,滤掉得分低的 boxes,对保留的 boxes 进行 NMS 处理,就得到最终的检测结果。
6、讨论
(1)一张图片最多可以检测出49个对象
每个30维向量中只有一组(20个)对象分类的概率,也就只能预测出一个对象。所以输出的 7x7=49个 30维向量,最多表示出49个对象。
(2) 总共有 49x2=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,选择预测得相对比较准的那个。
这里采用2个bounding box,有点不完全算监督算法,而是像进化算法。如果是监督算法,我们需要事先根据样本就能给出一个正确的bounding box作为回归的目标。但YOLO的2个bounding box事先并不知道会在什么位置,只有经过前向计算,网络会输出2个bounding box,这两个bounding box与样本中对象实际的bounding box计算IOU。这时才能确定,IOU值大的那个bounding box,作为负责预测该对象的bounding box。
训练开始阶段,网络预测的bounding box可能都是乱来的,但总是选择IOU相对好一些的那个,随着训练的进行,每个bounding box会逐渐擅长对某些情况的预测(可能是对象大小、宽高比、不同类型的对象等)。所以,这是一种进化或者非监督学习的思想。
(4)对bounding box的理解:
bounding box是怎么产生的?回归产生的,回归?哎呀,妈呀,回归是什么我都忘记了,好吧,我来举个初中的线性回归例子简单回顾一下
有两组数据A和B
A = [1,2,3,4,5]
B = [2,4,6,8,10]
利用回归的思想预测当A为6的时候B对应的值是多少,很明显回归参数就是2,回归程为y = 2x,所以A为6的时候B对应的值应该是12,这就是最简单的回归思路了。
然后yolo1中提到的就是直接利用整幅图像经过网络结构产生7*7的grid cell,每个grid cell预测x,y,w,h,confidence等几个值,其中confidence就是IOU的值。
(5)可以调整网格数量、bounding box数量
7x7网格,每个网格2个bounding box,对448x448输入图像来说覆盖粒度有点粗。我们也可以设置更多的网格以及更多的bounding box。设网格数量为 SxS,每个网格产生B个边框,网络支持识别C个不同的对象。这时,输出的向量长度为:C+Bx(4+1)整个输出的tensor就是:
SxSx(C+Bx(4+1))YOLO选择的参数是 7x7网格,2个bounding box,20种对象,因此 输出向量长度 = 20 + 2x (4+1) = 30。整个输出的tensor就是 7x7x30。因为网格和bounding box设置的比较稀疏,所以这个版本的YOLO训练出来后预测的准确率和召回率都不是很理想,后续的v2、v3版本还会改进。当然,因为其速度能够满足实时处理的要求,所以对工业界还是挺有吸引力的。
三、损失函数
YOLO给出的损失函数如下:
其中,x,y,w,C,p为网络预测值,x,y,w,C,p帽 为标注值。ii(obj)(i)表示物体落入格子i中,ii(obj)(ij) 表示物体落入格子i的第j个bounding box内。ii(noobj)(ij) 表示物体未落入格子i的第j个bounding box内。
YOLO方法模型训练依赖于物体识别标注数据,因此,对于非常规的物体形状或比例,YOLO的检测效果并不理想。
(1)bounding box的位置误差
公式第1行和第2行。
前面两行表示localization error(即坐标误差),第一行是box中心坐标(x,y)的预测,第二行为宽和高的预测。这里注意用宽和高的开根号代替原来的宽和高,这样做主要是因为相同的宽和高误差对于小的目标精度影响比大的目标要大。
a)都带有ii(noobj)(ij)意味着只有"负责"(IOU比较大)预测的那个bounding box的数据才会计入误差。
b)第2行宽度和高度先取了平方根,因为如果直接取差值的话,大的对象对差值的敏感度较低,小的对象对差值的敏感度较高,所以取平方根可以降低这种敏感度的差异,使得较大的对象和较小的对象在尺寸误差上有相似的权重。
这里注意用宽和高的开根号代替原来的宽和高,这样做主要是因为相同的宽和高误差对于小的目标精度影响比大的目标要大。举个例子,原来w=10,h=20,预测出来w=8,h=22,跟原来w=3,h=5,预测出来w=1,h=7相比,其实前者的误差要比后者小,但是如果不加开根号,那么损失都是一样:4+4=8,但是加上根号后,变成0.15和0.7。
c)乘以 系数 调节bounding box位置误差的权重(相对分类误差和置信度误差)。YOLO设系数为5,即调高位置误差的权重。
(2)bounding box的置信度误差
公式第3行和第4行。
第三、四行表示bounding box的confidence损失,就像前面所说的,分成grid cell包含与不包含object两种情况。这里注意下因为每个grid cell包含两个bounding box,所以只有当ground truth 和该网格中的某个bounding box的IOU值最大的时候,才计算这项。
a)第3行是存在对象的bounding box的置信度误差。带有ii(obj)(ij)意味着只有"负责"(IOU比较大)预测的那个bounding box的置信度才会计入误差。
b)第4行是不存在对象的bounding box的置信度误差。因为不存在对象的bounding box应该老老实实的说"我这里没有对象",也就是输出尽量低的置信度。如果它不恰当的输出较高的置信度,会与真正"负责"该对象预测的那个bounding box产生混淆。其实就像对象分类一样,正确的对象概率最好是1,所有其它对象的概率最好是0。
c)第4行会乘以系数调节不存在对象的bounding box的置信度的权重(相对其它误差)。YOLO设置 系数为0.5,即调低不存在对象的bounding box的置信度误差的权重。
(3)对象分类的误差
公式第5行,注意ii(obj)(i)意味着存在对象的网格才计入误差。第五行表示预测类别的误差,注意前面的系数只有在grid cell包含object的时候才为1。
可以看到,式中有几项是带系数的,这是因为:
[1] 位置相关误差(坐标、IOU)与分类误差对网络loss的贡献值是不同的。
[2] 在计算IOU误差时,落入物体的格子与无落入物体的格子,二者的IOU误差对网络loss的贡献值是不同的。若采用相同的权值,那么无落入物体的格子的confidence值近似为0,反过来,变相放大了落入物体的格子的confidence误差在计算网络参数梯度时的影响。
[3]对于相等的误差值,大物体误差对检测的影响应小于小物体误差对检测的影响。这是因为,相同的位置偏差占大物体的比例远小于同等偏差占小物体的比例。YOLO将物体大小的信息项(w和h)进行求平方根来改进这个问题。(注:这个方法并不能完全解决这个问题)。
四、训练
1)预训练。使用 ImageNet 1000 类数据训练YOLO网络的前20个卷积层+1个average池化层+1个全连接层。训练图像分辨率resize到224x224。
2)用步骤1)得到的前20个卷积层网络参数来初始化YOLO模型前20个卷积层的网络参数,然后用 VOC 20 类标注数据进行YOLO模型训练。检测通常需要有细密纹理的视觉信息,所以为提高图像精度,在训练检测模型时,将输入图像分辨率从224 × 224 resize到448x448。
训练时B个bbox的ground truth设置成相同的.
五、测试
测试:
如图所示,使用YOLO来检测物体,其流程是非常简单明了的:
1、将图像resize到448x448作为神经网络的输入
2、运行神经网络,得到一些bounding box坐标、box中包含物体的置信度和class probabilities
3、进行非极大值抑制,筛选Boxes
那每个bounding box的最终类别分数怎么计算呢?
每个bounding box的confidence和每个类别的score相乘,得到每个bounding box属于哪一类的confidence score。
即得到每个bounding box属于哪一类的confidence score。也就是说最后会得到20x(7x7x2)=20x98的score矩阵,括号里面是bounding box的数量,20代表类别。
NMS:非极大值抑制
接下来的操作都是20个类别轮流进行:在某个类别中(即矩阵的某一行),将得分少于阈值(0.2)的设置为0,然后再按得分从高到低排序。最后再用NMS算法去掉重复率较大的bounding box(NMS:针对某一类别,选择得分最大的bounding box,然后计算它和其它bounding box的IOU值,如果IOU大于0.5,说明重复率较大,该得分设为0,如果不大于0.5,则不改;这样一轮后,再选择剩下的score里面最大的那个bounding box,然后计算该bounding box和其它bounding box的IOU,重复以上过程直到最后)。最后每个bounding box的20个score取最大的score,如果这个score大于0,那么这个bounding box就是这个socre对应的类别(矩阵的行),如果小于0,说明这个bounding box里面没有物体,跳过即可。
参考:
整体
整体
测试
损失函数
https://blog.youkuaiyun.com/guleileo/article/details/80581858