【目标检测】 YOLO

YOLO v1

论文

前言

这周的目标是把目标检测的算法复习一下,同时研读下CVPR2019目标检测的新文章。

首先我们明确下 目标检测要完成一个什么样的任务。目标检测顾名思义就是检测图像中哪里有我们要检测的物体,这些物体是什么。“哪里有我们要检测的物体”,进一步抽象就是定位,确定物体在哪里;“这些物体是什么”,进一步抽象就是分类,确定物体的类别。看图说话 \downarrow

定位就是把物体框出来,分类就是确定物体的类别。

根据目标检测要完成的任务,目标检测的方法也主要分两类,one-stage和two-stage。one-stage是一步解决定位和分类的问题,主要网络YOLO、SSD、YOLO-v2、YOLO-v3等;two-stage是定位,分类两步走,主要网络是R-CNN家族,有R-CNN、Fast R-CNN、Faster R-CNN、Mask R-CNN等。本周回顾one-stage的方法。

YOLO目标检测的思路

YOLO全称是 You Only Look Once。

第一步,将图像划分成 S × S S×S S×S个网格,图片中物体的中心落在某一个网格上,那么该物体与该网格建立关系,该网格对该物体负责!每个物体都能找到对应的网格。

第二步,每个网格预测B个框框(bounding boxes)的位置和每个框框对应的置信度(confidence)。表示一个框框需要4个参数,中心点坐标( x , y x,y x,y)和框框的宽高( w , h w,h w,h)。这里的置信度指该框框圈住物体的可信程度。在测试阶段,它直接表示预测框体的可信度,用来执行NMS算法;在训练阶段,它需要制作标签以用于训练。计算包括两项,一是框框对应的网格包含物体的可能性 P r ( O b j e c t ) Pr(Object) Pr(Object);二是框框和物体真实框框的重叠程度,用IoU度量。因此置信度的计算公式为 P r ( O b j e c t ) I o U Pr(Object)\cdot IoU Pr(Object)IoU。如果该网格不包含任何物体,那么 P r ( O b j e c t ) = 0 Pr(Object)=0 Pr(Object)=0,该框框的置信度也为0;如果该网格包含物体,那么 P r ( O b j e c t ) = 1 Pr(Object)=1 Pr(Object)=1,则该框框的置信度为IoU的值。

第三步,预测包含物体的网格所属的类别,即计算网格属于各个类别的条件概率, P r ( C l a s s i O b j e c t ) Pr(Class_i|Object) Pr(ClassiObject)。结合第二步得到的置信度,我们可以得到每一个框框对每一个类别的置信度。
P r ( C l a s s i O b j e c t ) P r ( O b j e c t ) I o U = P r ( c l a s s i ) I o U Pr(Class_i|Object) \cdot Pr(Object) \cdot IoU = Pr(class_i) \cdot IoU Pr(ClassiObject)Pr(Object)IoU=Pr(classi)IoU

第二步完成物体的定位,第三步完成了物体的分类。其实第二、第三步是在一次性完成,此处只是为了便于理解,分点说明。

按照YOLO的检测思路,总结一下我们的网络应该输出什么内容。先看第二步,一个网格需要B个框框,而一个框框需要 x , y , w , h x,y,w,h x,y,w,h四个参数定位参数和一个置信度,共计5个参数,因此共计 S S B 5 S \cdot S \cdot B \cdot 5 SSB5;再看第三步,一个网格要预测 C C C个类别,共计 S S C S \cdot S \cdot C SSC。所以!最终的输出的维度是 S S ( B 5 + C ) S \cdot S \cdot (B\cdot 5 + C) SS(B5+C)

网络结构

网络结构比较常规,毕竟本文关键在于思路!想法!
连续的卷积池化,最后接两个全连接层。设置的参数 S = 7 , B = 2 C = 20 S=7, B=2, C=20 S=7,B=2C=20,因此模型的输出为 7 × 7 × 30 7×7×30 7×7×30

损失函数

个人觉得损失函数部分是这篇文章的精髓之处,表达式如下:
λ <mtext>  coord  </mtext> <munderover> i = 0 S 2 </munderover> <munderover> j = 0 B </munderover> l i j o b j [ ( x i <mover accent="true"> x ^ </mover> i ) 2 + ( y i <mover accent="true"> y ^ </mover> i ) 2 ] + λ <mtext>  coord  </mtext> <munderover> i = 0 S 2 </munderover> <munderover> j = 0 B </munderover> l i j o b j [ ( w i <mover accent="true"> w ^ </mover> i ) 2 + ( h i <mover accent="true"> h ^ </mover> i ) 2 ] + <munderover> i = 0 S 2 </munderover> <munderover> j = 0 B </munderover> l i j o b j ( C i <mover accent="true"> C ^ </mover> i ) 2 + λ <mtext>  noobj  </mtext> <munderover> i = 0 S 2 </munderover> <munderover> j = 0 B </munderover> l i j <mtext>  noobj  </mtext> ( C i <mover accent="true"> C ^ </mover> i ) 2 + <munderover> i = 0 S 2 </munderover> l i o b j <munder> c <mtext>  classes  </mtext> </munder> ( p i ( c ) <mover accent="true"> p ^ </mover> i ( c ) ) 2 \lambda_{\text { coord }} \sum_{i=0}^{S^{2}} \sum_{j=0}^{B} \mathbb{l}_{i j}^{\mathrm{obj}}\left[\left(x_{i}-\hat{x}_{i}\right)^{2}+\left(y_{i}-\hat{y}_{i}\right)^{2}\right] \\ +\lambda_{\text { coord }} \sum_{i=0}^{S^{2}} \sum_{j=0}^{B} \mathbb{l}_{i j}^{\mathrm{obj}}\left[\left(\sqrt{w_{i}}-\sqrt{\hat{w}_{i}}\right)^{2}+\left(\sqrt{h_{i}}-\sqrt{\hat{h}_{i}}\right)^{2}\right] \\ +\sum_{i=0}^{S^{2}} \sum_{j=0}^{B} \mathbb{l}_{i j}^{\mathrm{obj}}\left(C_{i}-\hat{C}_{i}\right)^{2}\\ +\lambda_{\text { noobj }} \sum_{i=0}^{S^{2}} \sum_{j=0}^{B} \mathbb{l}_{i j}^{\text { noobj }}\left(C_{i}-\hat{C}_{i}\right)^{2}\\ +\sum_{i=0}^{S^{2}} \mathbb{l}_{i}^{\mathrm{obj}} \sum_{c \in \text { classes }}\left(p_{i}(c)-\hat{p}_{i}(c)\right)^{2} λ coord i=0S2j=0Blijobj[(xix^i)2+(yiy^i)2]+λ coord i=0S2j=0Blijobj[(wi w^i )2+(hi h^i )2]+i=0S2j=0Blijobj(CiC^i)2+λ noobj i=0S2j=0Blij noobj (CiC^i)2+i=0S2liobjc classes (pi(c)p^i(c))2

损失函数共有三部分,框***置损失(第一二项),框体置信度损失(第三四项),网格类别损失(第五项)。接下一个一个看。

框***置损失

先看第一项:
λ <mtext>  coord  </mtext> <munderover> i = 0 S 2 </munderover> <munderover> j = 0 B </munderover> l i j o b j [ ( x i <mover accent="true"> x ^ </mover> i ) 2 + ( y i <mover accent="true"> y ^ </mover> i ) 2 ] \lambda_{\text { coord }} \sum_{i=0}^{S^{2}} \sum_{j=0}^{B} \mathbb{l}_{i j}^{\mathrm{obj}}\left[\left(x_{i}-\hat{x}_{i}\right)^{2}+\left(y_{i}-\hat{y}_{i}\right)^{2}\right] λ coord i=0S2j=0Blijobj[(xix^i)2+(yiy^i)2]
这一项计算框体中心点坐标损失。

  • λ c o o r d \lambda_{coord} λcoord是赋予该项损失的权重,权重越大,表明我们希望该项能优化的更好
  • i = 0 S 2 j = 0 B \sum_{i=0}^{S^{2}} \sum_{j=0}^{B} i=0S2j=0B表示每一个预测框体都要计算损失,总共要计算 S 2 B S^2\cdot B S2B个框体的损失
  • l i j o b j \mathbb{l}_{i j}^{\mathrm{obj}} lijobj表示哪些预测结果需要计算loss。作者定义了一类预测框体,如果有物体的中心落在网格 i i i中,并且第 j j j个预测框体是 B B B个预测框体中与实际框体IoU最大的框体,那么称 j j j框体对该网格负责(reasonable),对应地 l i j o b j = 1 \mathbb{l}_{i j}^{\mathrm{obj}}=1 lijobj=1;否则为0。
  • x i , y i x_i,y_i xi,yi是物体框体中心点坐标的实际值,是经过归一化的的。归一化的方法如图所示。

图中的网格划分是 3 × 3 3×3 3×3,框体的中心落在中间的网格。 x , y x,y x,y是框体中心点在中间网格中的相对位置,值介于 0 , 1 0,1 0,1之间。

再看第二项:
λ <mtext>  coord  </mtext> <munderover> i = 0 S 2 </munderover> <munderover> j = 0 B </munderover> l i j o b j [ ( w i <mover accent="true"> w ^ </mover> i ) 2 + ( h i <mover accent="true"> h ^ </mover> i ) 2 ] \lambda_{\text { coord }} \sum_{i=0}^{S^{2}} \sum_{j=0}^{B} \mathbb{l}_{i j}^{\mathrm{obj}}\left[\left(\sqrt{w_{i}}-\sqrt{\hat{w}_{i}}\right)^{2}+\left(\sqrt{h_{i}}-\sqrt{\hat{h}_{i}}\right)^{2}\right] λ coord i=0S2j=0Blijobj[(wi w^i )2+(hi h^i )2]
这一项计算框体宽高的损失。

  • w i , h i w_i,h_i wi,hi同样是经过归一化的值,归一化的方法是除以图片的宽和高
  • 此处对宽和高取平方根是因为同样的损失对于大小不同的框体精度的影响不一致。大框体收到的影响小于小框体。例如原来w=10,h=20,预测出来w=8,h=22,跟原来w=3,h=5,预测出来w1,h=7相比,损失大小都是 2 2 + 2 2 = 8 2^2+2^2=8 22+22=8,但其实前者的误差比后者小。加上根号后,前者: ( 10 8 ) 2 + ( 20 22 ) 2 = 0.159 (\sqrt{10}-\sqrt{8})^2 + (\sqrt{20}-\sqrt{22})^2=0.159 (10 8 )2+(20 22 )2=0.159, 后者: ( 3 1 ) 2 + ( 5 7 ) 2 = 0.704 (\sqrt{3}-\sqrt{1})^2 + (\sqrt{5}-\sqrt{7})^2=0.704 (3 1 )2+(5 7 )2=0.704,前者比后者小,能正确度量!

框体置信度损失

先看第一项
<munderover> i = 0 S 2 </munderover> <munderover> j = 0 B </munderover> l i j o b j ( C i <mover accent="true"> C ^ </mover> i ) 2 \sum_{i=0}^{S^{2}} \sum_{j=0}^{B} \mathbb{l}_{i j}^{\mathrm{obj}}\left(C_{i}-\hat{C}_{i}\right)^{2} i=0S2j=0Blijobj(CiC^i)2

  • l i j o b j \mathbb{l}_{i j}^{\mathrm{obj}} lijobj表示的含义和上一项一致。
  • C i C_i Ci是框体的置信度真实值,大小等于预测框体与实际框体的IoU。
  • 这一项计算的是对网格负责的框体的损失。

再看第二项
λ <mtext>  noobj  </mtext> <munderover> i = 0 S 2 </munderover> <munderover> j = 0 B </munderover> l i j <mtext>  noobj  </mtext> ( C i <mover accent="true"> C ^ </mover> i ) 2 \lambda_{\text { noobj }} \sum_{i=0}^{S^{2}} \sum_{j=0}^{B} \mathbb{l}_{i j}^{\text { noobj }}\left(C_{i}-\hat{C}_{i}\right)^{2} λ noobj i=0S2j=0Blij noobj (CiC^i)2

  • 这一项计算的是不对网格负责的框体的损失
  • 由于不对网格负责的框体的数量一般来说都大于对网格负责框体的损失,因此为它增加一个权重 λ n o o b j \lambda_{noobj} λnoobj,文中取值为0.5

类别预测损失
<munderover> i = 0 S 2 </munderover> l i o b j <munder> c <mtext>  classes  </mtext> </munder> ( p i ( c ) <mover accent="true"> p ^ </mover> i ( c ) ) 2 \sum_{i=0}^{S^{2}} \mathbb{l}_{i}^{\mathrm{obj}} \sum_{c \in \text { classes }}\left(p_{i}(c)-\hat{p}_{i}(c)\right)^{2} i=0S2liobjc classes (pi(c)p^i(c))2

  • i = 0 S 2 l i o b j \sum_{i=0}^{S^{2}} \mathbb{l}_{i}^{\mathrm{obj}} i=0S2liobj 只计算有物体中心的网格。
  • p i ( c ) p_i(c) pi(c)网格所属类别对应的独热编码,0或1.
  • 这里没有采用交叉熵,将它当成回归问题,直接差值的平方作为损失。

算法优缺点

优点

  • 快。将物体检测问题作为回归问题进行求解,网络结构简单,在保证检测准确率的情况下,能达到45FPS的检测速度(TianX)
  • 背景误检率低。YOLO在训练和推理过程中能‘看到’整张图像的整体信息,而基于region proposal的物体检测方法(如rcnn/fast rcnn),在检测过程中,只‘看到’候选框内的局部图像信息。因此,若当图像背景(非物体)中的部分数据被包含在候选框中送入检测网络进行检测时,容易被误检测成物体。测试证明,YOLO对于背景图像的误检率低于fast rcnn误检率的一半。

缺点

  • 由于YOLO默认同一个网格中框体属于同一种物体,因此当网格内出现不同物体时,效果差;
  • 由于YOLO一个网格只能预测两个物体,因此网格中出现多余两个物体时,效果差
  • 定位精度较差,模型召回率较低。
全部评论

相关推荐

11-28 17:58
门头沟学院 Java
美团 JAVA开发 n×15.5
牛客786276759号:百度现在晋升很难的 而且云这块的业务没美团好 你看百度股价都跌成啥样了
点赞 评论 收藏
分享
努力学习的小绵羊:我反倒觉得这种挺好的,给不到我想要的就别浪费大家时间了
点赞 评论 收藏
分享
11-04 14:10
东南大学 Java
_可乐多加冰_:去市公司包卖卡的
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务