赞
踩
随着深度学习的发展,基于深度学习的目标检测方法因其优异的性能已经得到广泛的使用。目前经典的目标检测方法主要包括单阶段(YOLO、SSD、RetinaNet,还有基于关键点的检测方法等)和多阶段方法(Fast RCNN、Faster RCNN、Cascade RCNN等)。下面主要介绍单阶段的目标检测方法(SSD、YOLO系列、RetinaNet等)、多阶段目标检测方法(RCNN系列)以及其他方法(FPN、关键点等)。分析粗中有细,适合小白入门学习(需要多看代码)以及大佬回顾。
单阶段目标检测方法是指只需一次提取特征即可实现目标检测,其速度相比多阶段的算法快,一般精度稍微低一些。
YOLO目标检测算法是2016年CVPR《You Only Look Once: Unified, Real-Time Object Detection》,其直接完成从特征到分类、回归的预测,分类和回归使用同一个全连接层实现,其框架图如下:
YOLO v2来源于这篇论文《YOLO9000: Better, Faster, Stronger》。这篇论文介绍很多涨点的方法,同时也是针对YOLO v1的改进。
YOLO v3来自此论文《YOLOv3: An Incremental Improvement》(论文看起来像实验报告,细节说的不清楚,还是需要看代码)。YOLO v3主要提出新的BackBone,特征金字塔结构用于不同尺度目标检测、采用Leaky ReLU等。
YOLO v4《YOLOv4: Optimal Speed and Accuracy of Object Detection》并不是之前YOLO的作者了。作者用了各种trick在YOLO v3的基础上进行改进,主要从**Bag of freebies(改变训练过程,不改变计算量)和Bag of specials(稍微增加一点计算量)**两个方面进行分析,基本把目标检测上面的trick都用了一遍。
SSD来源于此篇论文《SSD: Single Shot MultiBox Detector》,整个网络是全卷积网络,即经过VGG16进行特征提取后,提取38×38、19×19、10×10、5×5、3×3、1×1共六层不同尺度特征用于分类和回归。每一个特征层输出为: H×W×(N×(classes+4)),其中N表示这一层中的Anchor数量、classes表示类别数目、4表示(x,y,w,h)相对于Anchor的四个偏移量。下图表示整个网络的结构。
RetinaNet来源于《Focal Loss for Dense Object Detection》这篇论文。主要提出的问题是单阶段目标检测相比多阶段目标检测算法性能较差的原因在于正负样本的筛选不均衡。多阶段目标检测过程中,通过Selective Search、RPN等方式可以过滤掉大量的背景框,然后通过筛选正负样本(如1:3)的方式进行训练。但是单阶段的目标检测算法无法过滤这些背景框,导致正负样本严重不均衡(SSD上面提到了,选择loss最大的top-k,使得正负样本比例1:3左右)!因此提出Focal loss在训练的时候自适应调整损失权重,使得模型关注难样本的训练,同时提出RetinaNet目标检测框架。
RCNN是比较早的利用CNN进行目标检测的算法。其思想是使用selective search提取2000个左右的预选框,然后resize到统一的尺度(因为后面接FC分类)进行CNN特征提取,最后用FC进行分类。具体流程如下:
Fast RCNN相比RCNN而言只需要对整幅图像进行一次特征提取,并且直接利用FC进行分类和回归,实现end-to-end的多任务协同优化。具体过程是图像先经过Backbone网络提取图像的feature map;利用selective search搜索的预选框到特征上提取RoI的特征;通过RoI Pooling将RoI的特征转化为固定的大小;最后输入到分类和回归头分别进行分类和回归。
RoI(Region of Interest)
RoI仍然是通过Selective Search进行搜索得到的一个个预选框;
RoI Pooling
(1)RoI Pooling的有两个输入,一个是feature map,即整个图像经过Backbone提取的特征;另一个是RoI的坐标5维,[idx,x1,y1,x2,y2]表示左上角和右下角的坐标。坐标尺度是相对原图的尺度,而在feature上根据图像下采样的比例(即feature/原图尺度)找到对应的坐标。
(2)将映射后的区域划分为相同大小的区间(比如7×7),这样就可以从不同大小的RoI中获得固定大小的feature map,最终输出[H,W,C]维度的特征图,C表示通道个数,然后进行分类和回归处理。
值得注意的是: 当proposal在特征图上的尺度大于7×7时(比如RoI Pooling输出的是7×7),比较好理解,直接计算特征图到7×7映射的每个bin的最大值;当proposal小于7×7咋办呢?其实还是一样的,仍然这样强行处理,只不过会有一部分值是重复的。参考 在Mask RCNN中对RoI Pooling进行了修改,采用线性插值的方式来做的。
损失函数
损失函数分为分类和回归损失函数,与RCNN不同的是这里直接用FC进行分类和回归,分类损失函数Cross Entropy和Smooth L1。
分类共有N+1类,+1表示背景类;
回归用Smooth L1损失,对[x,y,w,h]进行回归,其中回归的约束目标仍然是中心点和长宽的相对值,与RCNN相似。Smooth L1损失:
当回归损失较大时,梯度是1,将回归损失较小时梯度是x;这样损失较大梯度大,下降快;损失较小,梯度小,损失下降慢。
参考:《Fast R-CNN》
Fast RCNN的RoI仍然是通过Selective Search的方式进行搜索,其速度较慢。Faster RCNN在Fast RCNN的基础上提出RPN(Region Proposal Network)自动生成RoI,极大的提高了预选框生成的效率。RPN过程如下:
图像经过Backbone网络之后得到feature map;将feature map输入到RPN网络中获得预选框(proposal);后续过程处理与Fast RCNN一致。
Cascade RCNN可以说是基于Faster RCNN进行改进的版本。Faster RCNN是通过RPN网络预测出Proposal然后利用分类头和回归头完成分类和定位,但是存在一个问题,训练时我们知道Ground Truth,可以直接筛选高质量的Proposal用于最后的分类和回归,但是在测试阶段,我们并不知道Ground Truth,导致所有的Proposal都进行最后的分类和定位,这就是训练和测试阶段的不匹配问题。直接暴力提高IoU的阈值,则会导致性能下降(召回率),经过实验发现当训练和测试时Proposal自身的阈值与训练的阈值接近时(就是训练和测试时后面检测头接收的proposal差不多),效果才会好。Cascade RCNN提出级联多个检测头来解决这个问题,如下图:
Mask RCNN是一个实例分割的算法,是在Faster RCNN目标检测+FCN的基础上进行分割。过程图如下:
旋转目标检测这里只介绍一个RoI Transformer吧!《Learning RoI Transformer for Oriented Object Detection in Aerial Images》旋转目标检测与水平目标检测不同的是需要检测目标的方向,在遥感图像目标检测、文字检测等任务中比较常见。预测的结果包含类别、位置坐标、长宽、角度。
RoI Transformer基于Faster RCNN检测算法,加上一个旋转RoI特征提取模块(Rotated RoI),整个过程分为两个阶段:
(1)第一阶段,即Faster RCNN算法,经过RPN、水平RoI预测一个粗略的旋转框(利用水平RoI特征预测{x,y,w,h,θ},这里θ表示一个旋转角度);
(2)第二阶段,基于第一阶段的粗略旋转框,提取旋转RoI的特征,再进行精确的{x’,y’,w’,h’,θ’},即在第一阶段的结果上进行修正。
整个思路过程大致如下:
(3)旋转RoI,旋转RoI特征提取是基于RoIAlign实现的,即在水平RoIAlign的基础上,每一个采样点(x,y)都根据角度θ进行坐标偏移得到(x’,y’),最终实现旋转RoI特征提取。偏移计算公式如下:
(4)预测目标,这里预测的坐标需要考虑角度的偏差,即:
t
x
′
=
1
/
w
r
(
(
x
′
−
x
r
)
c
o
s
θ
r
+
(
y
′
−
y
r
)
s
i
n
θ
r
)
t
y
′
=
1
/
h
r
(
(
y
′
−
y
r
)
c
o
s
θ
r
+
(
x
′
−
x
r
)
s
i
n
θ
r
)
t
w
′
=
l
o
g
(
w
′
/
w
r
)
;
t
h
′
=
l
o
g
(
h
′
/
h
r
)
t
θ
′
=
(
(
θ
′
−
θ
r
)
m
o
d
2
π
)
/
2
π
t'_x=1/w_r((x'-x_r)cosθ_r+(y'-y_r)sinθ_r)\\ t'_y=1/h_r((y'-y_r)cosθ_r+(x'-x_r)sinθ_r)\\ t'_w=log(w'/w_r);t'_h=log(h'/h_r)\\ t'_θ=((θ'-θ_r)mod2π)/2π
tx′=1/wr((x′−xr)cosθr+(y′−yr)sinθr)ty′=1/hr((y′−yr)cosθr+(x′−xr)sinθr)tw′=log(w′/wr);th′=log(h′/hr)tθ′=((θ′−θr)mod2π)/2π
分类损失函数是Cross Entropy Loss,回归损失是Smooth L1 Loss。最终的损失由RPN(分类、回归)+水平框损失(分类、回归)+选择框损失(分类、回归)。
(5)这里旋转目标检测有一点不一样的是需要计算旋转目标的IoU,计算的时候用shapely这个包计算的多边形IoU。
这一部分介绍一下FPN的一些变体结构吧(FPN、PAFPN、ASFF、CARAFE)!今年的一篇CVPR2021论文《You Only Look One-level Feature》提到FPN网络提高检测性能的主要原因在于不同尺度的分治,对于自顶向下的特征融合对于性能影响不大!(其实这个也比较好理解,分治的作用肯定比融合特征性能提升的多)。
本人研究Anchor Free相关的算法比较少(YOLO v1是比较早的Anchor Free算法了),这里主要介绍几篇关于关键点检测的算法。FCOS、CenterNet等。
目标检测中的损失函数主要分为分类损失函数和回归损失函数。在检测任务中用的分类损失函数基本都是Cross Entropy Loss,关于分类任务这方面的变体比较多;在回归任务中,基本都是L1、L2、Smooth L1以及IoU相关的损失。下面就简单介绍下相关的损失函数。
关于回归损失主要是L1、L2、Smooth L1和IoU的变体,下面逐一介绍。
最后强烈安利mmdetection目标检测框架,由pytorch开发,目前很多经典算法都有集成,可以快速上手,成为一个快乐的调包侠。
最后对所有引用的论文、博客、知乎等各位大佬们表示衷心的感谢!你们是推动科研进步的主力军!
未完待续
应该写的差不多了,若有错误,欢迎各位大佬批评指正!感谢!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。