YOLO(You Only Look Once),经典的one-stage方法,把检测问题转化为回归问题,简单的CNN网络就搞定了,可以对视频进行实时检测,应用领域非常广。
说起目标检测系统,就要先明白,图像识别、目标定位和目标检测的区别。图像识别也可以说成是目标分类,顾名思义,目的是为了分类出图像中的物体是什么类别。目标定位是不仅仅要识别出是一种什么物体,还要预测出物体的位置,并使用bounding box框出。目标检测就更为复杂,它可以看作是图像识别+多目标定位,即要在一张图片中定位并分类出多个物体。
目标检测对于人类来说极为简单,经过上万年的进化,人类天生具有复杂的感知与视觉系统,这是机器无可比拟的,我们可以只对图片看一眼,即分辨出物体的种类和它相应的位置,根据先前的知识进行归纳,适应不同图像环境都是人类专属技能。但是对于计算机来说,一张图片只是具有无数RGB像素点的矩阵,它本身并不知道猫狗动物,大小形状的概念,如果再给它一张具有复杂自然场景背景的图片,想要检测出物体更是难上加难。但是是问题,总会有解决的办法。问题是由人类提出来的,当然还要靠人类的智慧来处理。面对这样的计算机难题,很多研究学者蜂拥而至,从此目标检测领域变成了非常热门的研究方向,当然也诞生出了许多的解决方法。
传统的目标检测方法大致分为三个步骤,先使用不同的方法(滑动窗口,区域候选)提取区域的特征图,然后再使用分类器进行识别,最后回归预测。大多数方法都较为复杂,速度较慢,训练耗时。
传统的方法可以按照检测系统分为两种:
目前深度学习相关的目标检测方法大致可以分为两派:
本文着重于介绍一下目标检测系统:YOLO
将整张图片作为网络的输入,直接在输出层对bounding box的位置和所属类别进行回归。与Faster R-CNN网络相比,虽然后者也是使用整张图片作为输入,但是它采用了RCNN那种区域预测+分类的思想,把提取proposal的步骤放在了CNN中实现,而YOLO则采用直接回归的思路,将目标定位和目标类别预测整合于单个神经网络模型中。
直接在输出层回归bbox的位置和所属类别。
按照 YOLO:Unified,Real-Time Object Detection 中所说,YOLO检测系统简单直接,可以看做只有三步:
1.输入:448 x 448 x 3,由于网络的最后需要接入两个全连接层,全连接层需要固定尺寸的输入,故需要将输入resize。
2.Conv + FC:主要使用1x1卷积来做channle reduction,然后紧跟3x3卷积。对于卷积层和全连接层,采用Leaky ReLU激活函数:max(x,0.1x) ,但是最后一层采用线性激活函数。
3.输出:最后一个FC层得到一个1470 x 1的输出,将这个输出reshap一下,得到 7 x 7 x 30 的一个tensor,即最终每个单元格都有一个30维的输出,代表预测结果。具体如下:
2、每个网格要预测B个bounding box,每个box除了要回归自身的位置之外,还要附带预测一个confidence值。这个值代表了所预测的bounding box中是否含有object和若有object,这个object预测得有多准的两重信息,计算方式:
P r ( O b j e c t ) ∗ I o U p r e d t r u t h Pr(Object)∗IoU^{truth}_{pred} Pr(Object)∗IoUpredtruth
然后看2个bounding box的IOU,哪个比较大(更接近对象实际的bounding box),就由哪个bounding box来负责预测该对象是否存在,即该bounding box的 P r ( O b j e c t ) Pr(Object) Pr(Object)=1,同时对象真实bounding box的位置也就填入该bounding box。另一个不负责预测的bounding box的 P r ( O b j e c t ) = 0 Pr(Object)=0 Pr(Object)=0。
总的来说就是,与对象实际bounding box最接近的那个bounding box,其 C o n f i d e n c e = I o U p r e d t r u t h Confidence=IoU^{truth}_{pred} Confidence=IoUpredtruth该网格的其它bounding box的 C o n f i d e n c e = 0 Confidence=0 Confidence=0。
说人话:拿上面狗的图片举例子
首先将狗的图片分为7*7的网格,而红色的点所在的网格就是狗的标注框中心点所在的网格,因此这个框负责预测狗这个物体。
每个网格可以定义有几个anchor box,当然,这里是定义了2个anchor box。拿其中一个anchor box举例,经过与真实框的IOU计算之后就是回归出来的框Bounding Box(也就是网络输出的框(图中的黄色框),他与真实框和anchor box都有差距)(anchor box 的个数和大小由自己定义,写在配置文件中)
返回回来的Bounding Box携带5个值(x,y,w,h,c),(x,y)为Bounding Box的中心坐标,w,h为Bounding Box的宽和高。另外还有一个c意思就是confidence,这个值反映出了两个信息,一个是这个框的IOU比较高,也就是这个框是被筛选出来的,否则也不会返回Bounding Box对吧,另一个就是这个框预测的准确度。
至于公式可以这样理解:
如果这个网格是物体框的中心点,那当然是咱们想要的,所以为1,否则就是背景呗,背景不是我们想要的所以是0。
Bounding Box与anchor box的区别可以看看这篇文章:https://blog.csdn.net/m0_54146002/article/details/120486688
3、每个网格单元针对20种类别预测bboxes属于单个类别的条件概率 P r ( C l a s s i ∣ O b j e c t ) Pr(Class_i ∣Object) Pr(Classi∣Object),属于同一个网格的B个bboxes共享一个条件概率。在测试时,将条件概率分别和单个的bbox的confidence预测相乘:
P r ( C l a s s i ∣ O b j e c t ) ⏞ c o n d i t i o n a l c l a s s p r o b ∗ P r ( O b j e c t ) ∗ I o U p r e d t r u t h ⏞ b b o x c o n f i d e n c e = P r ( C l a s s i ) ∗ I o U p r e d t r u t h \overbrace{Pr(Class_i ∣Object)}^{conditional{\,} class{\,} prob}∗\overbrace{Pr(Object)∗IoU^{truth}_{pred}}^{bbox{\,} confidence}=Pr(Class_i)∗IoU^{truth}_{pred} Pr(Classi∣Object) conditionalclassprob∗Pr(Object)∗IoUpredtruth bboxconfidence=Pr(Classi)∗IoUpredtruth
即20个对象分类的概率
对于输入图像中的每个对象,先找到其中心点。比如上图中的自行车,其中心点在黄色圆点位置,中心点落在黄色网格内,所以这个黄色网格对应的30维向量中,自行车的概率1,其它对象的概率是0。所有其它48个网格的30维向量中,该自行车的概率都是0。这就是所谓的"中心点所在的网格对预测该对象负责"。狗和汽车的分类概率也是同样的方法填写。
说人话:
以狗举例,如果候选框的grid cell和标注框的grid cell是一个即都是蓝色的grid cell,那么这个网格的 P r ( 狗 ∣ O b j e c t ) = 1 Pr(狗∣Object) =1 Pr(狗∣Object)=1, P r ( 其他 19 种 ∣ O b j e c t ) = 0 Pr(其他19种∣Object) =0 Pr(其他19种∣Object)=0,如果预测框的grid cell既不是上图中的蓝色grid cell,也不是黄和粉grid cell呢?就是 P r ( 20 种 ∣ O b j e c t ) = 0 Pr(20种∣Object) =0 Pr(20种∣Object)=0呗。
4、在Pascal VOC中,YOLO检测系统的图像输入为448×448,S=7,B=2,一共有20个class(C=20),输出就是7×7×30的一个tensor。这个是怎么算出来的呢?看下面详解。
YOLO使用了24个级联卷积层和最后2个全连接层,交替的1×1卷积层降低了前面层的特征空间。在ImageNet分类任务上使用分辨率的一半(224×224输入图像)对卷积层进行预训练,然后将分辨率加倍进行目标检测。
YOLO网络借鉴了GoogleNet的思想,但与之不同的是,为了更好的性能,它增加额外的4层卷积层(conv)。YOLO一共使用了24个级联的卷积层和2个全连接层(fc),其中conv层中包含了1×1和3×3两种kernel,最后一个fc全连接层后经过reshape之后就是YOLO网络的输出,是长度为S×S×(B×5+C)=7×7×30的tensor,最后经过识别过程得到最终的检测结果。
上文说到每个bounding box要预测(x,y,w,h,confidence)五个值,一张图片共分为S×S个网格,每个网格要预测出B个bounding box和一个网格负责的object的类别信息,记为C。
则输出为S ∗ S ∗ ( 5 ∗ B + C ) SS(5*B+C)S∗S∗(5∗B+C)的tensor张量,(x,y)表示bounding box相对于网格单元的边界的offset,归一化到(0,1)范围之内,而w,h表示相对于整个图片的预测宽和高,也被归一化到(0,1)范围内。c代表的是object在某个bounding box的confidence。
使用下图更形象的说明,7×7×30的Tensor中的一个1×1×30的前10维的所代表的含义。
下面解释如何将预测坐标的x,y用相对于对应网格的offset归一化到0-1和w,h是如何利用图像的宽高归一化到0-1之间。
每个单元格预测的B个(x,y,w,h,confidence)向量,假设图片为S×S个网格,S=7,图片宽为wi 高为hi :
1.(x,y)是bbox的中心相对于单元格的offset
对于下图中蓝色单元格,坐标为(xcol=1,yrow=4),假设它的预测输出是红色框bbox,设bbox的中心坐标为(xc,yc),那么最终预测出来的(x,y)是经过归一化处理的,表示的是相对于单元格的offset,公式:
x = x c w i ∗ S − x c o l , y = y c h i ∗ S − y r o w x=\frac{x_c}{w_i}*S-x_{col},y=\frac{y_c}{h_i}*S-y_{row} x=wixc∗S−xcol,y=hiyc∗S−yrow
2.(w,h)是bbox相对于整个图片的比例
预测的bbox的宽高为wb, hb,(w,h)表示的是bbox相对于整张图片的占比,公式:
w = w b w i = , y = h b h i w=\frac{w_b}{w_i}=,y=\frac{h_b}{h_i} w=wiwb=,y=hihb
如果还不理解,可以看这里
前面说了,共有7x7=49个“grid cell”,而每个“grid cell”有两个“bounding box”,负责预测“ground truth”的位置和类别。因此,最后的30实际上是由5x2+20组成的。
第一个5,分别是x,y,w,h,c。其中:
x,y是指“bounding box”的预测框的中心坐标相较于该“bounding box”归属的“grid cell”左上角的偏移量,在0-1之间。如下图所示
在上图中,绿色虚线框代表grid cell,绿点表示该grid cell的左上角坐标,为(0,0);
红色和蓝色框代表该grid cell包含的两个bounding box,红点和蓝点表示这两个boung box的中心坐标。有一点很重要,bound box的中心坐标一定在该grid cell内部,因此,红点和蓝点的坐标可以归一化在0-1之间。再上图中,红点的坐标为(0.5,0.5),即x=y=0.5,蓝点的坐标为(0.9,0.9),即x=y=0.9。
w和h是指该bound box的宽和高,但也归一化到了0-1之间,表示相较于原始图像的宽和高(即448个像素)。比如该bounding box预测的框宽是44.8个像素,高也是44.8个像素,则w=0.1,h=0.1。
比如对于下面的这个例子:
红框的x=0.8,y=0.5,w=0.1,h=0.2。
那么,最后的c表示什么呢?c是置信度,表示的实际含义是:该bounding box 中含有目标的概率,在论文中表示为:
那么这个c实际是怎么求出来的呢?作者用bounding box与ground truth的IOU来代替c,即作者的思想是:用bounding box与ground truth的重合程度,来表示该bounding box中含有目标的概率,这显然是符合直觉的,也是说得通的。上面图片中的Pr(Object)非0即1,若ground truth的中心点落入该grid cell中,则Pr(Object)=1,否则Pr(Object)=0。
所以,对于一个bounding box,有x,y,w,h,c这五个参数,前四个参数而已确定bounding box的方框,最后的c可以该bounding box 中含有目标的概率。而对于一个grid cell有两个bounding box,因此是5x2。
OK,至此已经解释清楚了30=5x2 + 20中的前半部分,那么后面的20又是什么?
YOLOV1是在PASCAL VOC数据集上训练的,该数据集上有20个类别,因此这里的20表示的是条件概率:在该grid cell包含目标的条件下,该目标是某种类别的概率。在论文中作者用Pr(Classi | Object)表示。因为有20个类别,所以有20个条件概率。
这就是7x7x30中的30表示的具体含义。
另外,因为c表示的是该方框中存在目标的概率,后面的20表示的是条件概率:在该grid cell包含目标的条件下,该目标是某种类别的概率。所以用c乘以条件概率就可以得到全概率,如下图所示。全概率就表示该方框中包含目标的概率。
每个grid cell对应的两个bounding box的5个值在tensor中体现出来,组成前十维。后面二十维代表属于每一个类别的概率。
如上式所述,每个网格预测的类别概率乘以每个bbox的预测confidence,得到每个bbox的class-specific confidence score分数。对每个格子的每一个bounding box进行此运算,最后会得到7×7×2=98个scores,设置一个阈值,滤掉得分低的bboxes,对保留的bboxes进行NMS(Non Maximum Suppression)处理,最终得到目标检测结果。
最后得到第一个为最大的score值,找出针对dog这个种类预测出的对应框,记为bbox_max
。然后将它与其他分数较低的但不是0的框作对比,这种框记为bbox_cur
。将bbox_max
和bbox_cur
分别做IoU
计算,如果 IoU(bbox_max, bbox_cur) > 0.5
,那么将bbox_cur
对应的score
设为0
。例如:
然后接着遍历下一个score
,如果它不是最大的且不为0
,就和最大的score
对应的框座IoU
运算,若结果大于0.5
则,同上。否则它的score
不变,继续处理下一个bbox_cur
……直到最后一个score
,如图:
计算完一轮之后,假如得到score
序列:0.5、0、0.2、0.1 … 0、0、0、0
那么进行下一轮循环,从0.2
开始,将0.2
对应的框作为bbox_max
,继续循环计算后面的bbox_cur
与新的bbox_max
的IoU值,大于0.5
的设为0
,小于0.5
的score
不变。再这样一直计算比较到最后一个score
。
得到新的的score
序列为:0.5、0、0.2、0 … 0、0、0、0
即最后只得到两个score
不为0的框,如图:
经过这些NMS
算法的处理,会出现很多框针对某个class的预测的score为0的情况。
最后,针对每个bbox的20×1的张量,对20种class的预测score进行判断。例如,
1)先取出针对bbox3的所有20个scores,按照类别的默认顺序找出score最大的那个score的index索引号(根据此index可以找出所属的类别)记为class
;
2)然后找出bbox3的最大score分数,记为score
。
3)判断score是否大于0,如果是,就在图像中画出标有class的框。否则,丢弃此bbox。
如图:
接下来进行下一个bbox的筛选,如图,则是bbox1,流程同上。一直到最后一个bbox97,
最后得到的框如图:
1.bbox损失函数
bbox的四个指标(x,y,w,h)要计算与真实框的损失
2.confidence损失函数
分前景和背景两种情况:
我们看上面这张图,同样是差距1px,大图像感觉就无所谓,而小图像却差之毫厘谬以千里。因此我们加上一个根号。接着看
从开方函数图像很容易就知道对于较大的bbox来说两者之差是会被慢慢缩小的,即惩罚力度没有小bbox这么大。