目录
前言
图像分类任务的内容是识别图像中目标的类别,而目标检测的任务是在此基础上,确定目标在图中的位置,与分类任务不同,目标检测任务的图像中往往存在多个目标。
在深度学习兴起之前,传统的目标检测算法依赖手工提取特征,在性能、精度方面均比不上如今基于深度学习的方法。而基于深度学习的算法大致可分为两类:1)基于锚框 (Anchor Based) 的方法,以及2)不基于锚框 (Anchor free) 的方法。
本文将记录目标检测任务中基础的概念并尝试介绍基于锚框方法中常见的算法,包括RCNN、fast RCNN、YOLO系列等。基于锚框的算法也可以分为两类:1)一阶段(One-stage)的方法和2)二阶段(Two-stage)的方法。
一、基础概念
边界框
边界框(bounding box),顾名思义就是用来描述图片中目标位置的矩形框。边界框可以由一个四维的向量来描述,常见的做法是用左上角和右下角的 x x x轴与 y y y轴坐标来确定(用中心坐标 ( x , y ) (x,y) (x,y)加上框的宽 w w w和高 h h h也是常见的做法)。
锚框
基于锚框(anchor box)的目标检测算法通常在输入图像上进行采样,通过生成大量的锚框选中大量区域,然后判断这些区域是否包含目标,对包含目标的锚框大小、位置进行调整,从而得到接近真实边界框(ground truth bounding box)的预测。
一个简单的锚框生成方案是对图像的每个像素都生成若干个形状不同的锚框。具体而言,对于高和宽为h和w的图像,我们用s∈(0,1]来限制锚框的大小,r>0来确定高宽比。那么锚框的尺寸为: w s r × h s / r ws\sqrt{r} \times hs/\sqrt{r} wsr×hs/r
那么对于一组
s
1
,
.
.
.
s
n
s_1,...s_n
s1,...sn 和
r
1
,
.
.
.
r
m
r_1,...r_m
r1,...rm我们一共得到
w
h
n
m
whnm
whnm个锚框,对于动辄2k的图像来说,这样生成的锚框数量是巨大的。因此,通常只选择保留这里面的一小部分,例如,只保留包含
s
1
s_1
s1 或
r
1
r_1
r1的锚框。
(
s
1
,
r
1
)
,
(
s
1
,
r
2
)
,
.
.
.
,
(
s
1
,
r
m
)
,
(
s
2
,
r
1
)
,
(
s
3
,
r
1
)
,
.
.
.
,
(
s
n
,
r
1
)
(s_1,r_1), (s_1,r_2),...,(s_1,r_m),(s_2,r_1),(s_3,r_1),...,(s_n,r_1)
(s1,r1),(s1,r2),...,(s1,rm),(s2,r1),(s3,r1),...,(sn,r1)
这样,锚框的数量就降低到了 w h ( n + m − 1 ) wh(n+m-1) wh(n+m−1),但其实这样还是很多,也存在相邻像素生成的锚框基本重合等问题,因此不同的目标检测算法常常在锚框生成上有不同的方案。
交并比
为了衡量算法提出的锚框与真实边界框之间的差距,我们用交并比(IOU)来量化两个框之间的相似度。
J
(
A
,
B
)
=
∣
A
∩
B
∣
∣
A
∪
B
∣
J(A, B)=\frac{|A \cap B|}{|A \cup B|}
J(A,B)=∣A∪B∣∣A∩B∣
非极大值抑制
非极大值抑制(nonmaximum suppression,NMS)顾名思义就是抑制不是极大值的元素,搜索局部的极大值。这个局部代表的是一个邻域,邻域有两个参数可变,一是邻域的维数,二是邻域的大小。其基本原理如下
- 对于一组预测框 A 1 , . . . , A n A_1,...,A_n A1,...,An、 B 1 , . . . , B m B_1,...,B_m B1,...,Bm、 C 1 , . . . , C k C_1,...,C_k C1,...,Ck,计算每个框对不同类别的预测概率 p p p(置信度)。
- 对某一个预测类别,将预测框按对该类的预测概率降序排列,将置信度最高的预测框 A 1 A_1 A1作为基准,将 A 1 A_1 A1与其它每个框比较(算IOU),删除IOU高于某个阈值(超参数)的框。
- 从列表中选择置信度第二高的预测框 B 1 B_1 B1,以 B 1 B_1 B1为基准,重复2。
- 重复3,直到输出列表中所有预测框之间的IOU均小于阈值,即每个框之间都不太相似。
标注训练集的锚框
一个标注好的图像包含两类标签:1)包含目标的边界框;2)此边界框对应的目标类别;但这样来说,样本数量就过少了,且只有正样本。因此我们需要根据一张标注好的图像构建一个更大的训练集。
常见的方法是,对一张图像生成若干锚框,将一个锚框视为一个训练样本,我们标注这些锚框的1)包含的目标种类;2)真实边界框相对锚框的偏移量(offset)。
标注类别的方法如下:
- 假设图像中生成的锚框分别为 A 1 , . . . , A n A_1,...,A_n A1,...,An ,真实边界框分别为 B 1 , . . . , B m B_1,...,B_m B1,...,Bm 。定义矩阵 X ∈ R n × m X∈R^{n\times m } X∈Rn×m,其中 X i j X_{ij} Xij为锚框 A i A_i Ai与边界框 B j B_j Bj的交并比。
- 选出 X X X中最大的元素 X i 1 j 1 X_{i_1j_1} Xi1j1,删除矩阵的第 i 1 i_1 i1行和第 j 1 j_1 j1列。我们将边界框 B i 1 B_{i_1} Bi1分配给锚框 A i 1 A_{i_1} Ai1,这样就为锚框 A i 1 A_{i_1} Ai1标注好了它的类别。
- 在 X X X剩下的元素中重复2.,直到所有的边界框均被分配出去。
- 接下来,就剩下
m
−
n
m-n
m−n个锚框尚未分配,我们遍历它们,去看与真实边界框之间的IOU,根据设定好的阈值(超参数)来确定是否为它们分配边界框。所有被分配到边界框的锚框均为正样本,反之则被标记为“背景”,为负样本。
接下来就需要为正样本标注与真实边界框之间的偏移量:
- 由于训练集中的锚框大小尺寸各异,我们不太方便直接量化它们与边界框之间的位置差异,因此需要引入一些变化。常见的方案是将锚框
A
A
A的偏移量标记为
( x b − x a w a − μ x σ x , y b − y a h a − μ y σ y , log w b w a − μ w σ w , log h b h a − μ h σ h ) \left(\frac{\frac{x_{b}-x_{a}}{w_{a}}-\mu_{x}}{\sigma_{x}}, \frac{\frac{y_{b}-y_{a}}{h_{a}}-\mu_{y}}{\sigma_{y}}, \frac{\log \frac{w_{b}}{w_{a}}-\mu_{w}}{\sigma_{w}}, \frac{\log \frac{h_{b}}{h_{a}}-\mu_{h}}{\sigma_{h}}\right) (σxwaxb−xa−μx,σyhayb−ya−μy,σwlogwawb−μw,σhloghahb−μh) - 其中, A A A的中心坐标为 ( x a , y a ) (x_{a},y_{a}) (xa,ya),边界框 B B B的中心坐标为 ( x b , y b ) (x_{b},y_{b}) (xb,yb)。以上常数的默认值为 μ x = μ y = μ w = μ h = 0 , σ x = σ y = 0.1 , σ w = σ h = 0.2 \mu_{x}=\mu_{y}=\mu_{w}=\mu_{h}=0, \sigma_{x}=\sigma_{y}=0.1, \quad \sigma_{w}=\sigma_{h}=0.2 μx=μy=μw=μh=0,σx=σy=0.1,σw=σh=0.2。
- 当然,不同模型所采用的损失函数各有不同,对锚框与真实边界框之间偏移量的定义也有所不同。
二、RCNN系列
区域卷积神经网络(Region-based CNN)开创性地将深度学习应用到目标检测任务中,在RCNN基础上的faster RCNN至今任是精度最高的模型。本小节介绍RCNN系列均属于二阶段算法。
所谓二阶段,就是指算法可分为两步:1)提出目标可能在的区域;2)对区域进行分类和边界框预测。因此,“二阶段”又称基于**候选区域(Region proposal)**的目标检测。对应地,“单阶段算法”是指算法不需要先提出候选区域,直接预测目标位置和分类,也称为Region-free方法。
RCNN
首先来介绍系列的开山之作RCNN。RCNN由以下四个步骤构成。
- 生成候选区域(类似生成锚框):采用选择性搜索(Selective Search)方法,一张图片可生成1K~2K个候选区域。
- 特征抽取:将每个候选区域输入一个预训练的深度卷积神经网络提取特征。
- 类别判断:将从每个区域抽取的特征连同其标注的类别作为样本,训练多个支持向量机(SVM)。其中每个SVM用于判断样本是否属于某一个类别。
- 位置修正:将从每个区域抽取的特征连同其标注的边界框作为样本,训练线性回归模型来进行预测。
在这个过程中,有一个疑惑:在类别判断时为什么要用多个SVM来一类一类地判断,而不是直接在CNN后接softmax直接训练呢?
这个是因为SVM训练和CNN训练过程的正负样本定义方式各有不同,导致最后采用CNN softmax输出比采用SVM精度还低。具体而言,cnn在训练的时候,对训练数据做了比较宽松的标注,比如一个bounding box可能只包含物体的一部分,那么我也把它标注为正样本,用于训练cnn;采用这个方法的主要原因在于因为CNN容易过拟合,所以需要大量的训练数据,所以在CNN训练阶段我们是对Bounding box的位置限制条件限制的比较松(IOU只要大于0.5都被标注为正样本了);然而svm训练的时候,因为SVM适用于少样本训练,所以对于训练样本数据的IOU要求比较严格,我们只有当bounding box把整个物体都包含进去了,我们才把它标注为物体类别。1
虽然RCNN算法取得了很大进展,但缺点也很明显:重叠框(一张图片大2000多个候选框)特征的冗余计算使得整个网络的检测速度变得很慢(使用GPU的情况下检测一张图片大约需要14S)2。
Fast RCNN
1)ROI池化
在介绍Fast RCNN前,需要先介绍一下兴趣区域池化(region of interest pooling, ROI)。ROI Pooling的作用是将不同尺寸的特征块输入,转化为相同尺寸的特征块输出。
假设需要输出的特征块尺寸为
n
×
m
n \times m
n×m,那么对任意输入,都将它“平均”分割成
n
×
m
n \times m
n×m个区域,取每个区域中的最大值输出,这样就得到了相同尺寸的输出。
如上图所示,实际操作中难以保证输入正正好好能被平均分割成
n
×
m
n \times m
n×m,在这种情况下,分割时会进行“取整”。
2)网络结构
下面开始介绍fast RCNN对RCNN的改进和网络结构。导致RCNN速度很慢的原因在于RCNN需要对每个锚框独立地进行特征抽取,而这里面许多锚框是存在大量重叠的,可想而知RCNN进行了大量冗余的计算。以及,训练的空间需求大。因为RCNN中,独立的分类器和回归器需要很多的特征作为训练。RCNN中提取候选框,提取特征和分类回归是分开的,可独立3。
所以,fast RCNN主要的改进是只对整个图像做一次特征抽取,同时,损失函数使用了多任务损失函数(multi-task loss),将边框回归直接加入到CNN网络中训练。它的计算步骤如下
- 从输入图像中抽取特征(CNN)
- 生成锚框:选择性搜索提出 n n n个兴趣区域
- 将锚框映射到特征图上,输入ROI Pooling层
- 输入全连接层,进行分类和边界框预测
需要注意的是,这里预测类别和预测边界框是同时进行的,是一个多任务模型,两个任务能够共享卷积特征,并相互促进。
Faster RCNN
顾名思义,faster RCNN在计算速度上又比fast RCNN做了一些提高。faste RCNN通过选择性搜素(selective search)提出1K~2K个锚框,faster RCNN提出用区域提议网络(region proposal network,RPN) 来代替选择性搜索,在减少锚框数量的同时,保证目标检测精度。
从图中可以看到,与fast RCNN相比,除了提出锚框的方法改为了RPN,其它部分均保持不变。RPN的具体步骤如下4
- 用填充为1的 3 × 3 3 \times 3 3×3卷积层变换CNN的输出,这样做是为了保持输出与输入矩阵尺寸的一致。
- 以特征图每个单元为中心,生成多个不同尺寸、高宽比的锚框(大量,但低质量)。
- 用中心的特征分别预测锚框的二元类别(softmax,含目标还是背景)和边界框。
- 用NMS输出。
可以说,RNP就是一个小的、粗糙的目标检测网络,提出一些相对粗糙但比选择性搜索更好的锚框。整个网络最终的结果是,能学习到如何生成高质量的提议区域,从而提高在较少提议区域数量的同时,保证预测精度。
三、单发多框检测
单发多框检测(single shot multibox detection, SSD)属于基于锚框的单阶段方法,它的网络设计思想对后续研究广泛的影响(特别是YOLO3)。SSD由一个基础网络块和若干个多尺度特征块串联而成。其中,基础网络块用于抽取图像的特征(可以用VGG或者ResNet等),不同尺度的特征块用于提供不同尺寸的锚框。
这样做的原因在于,通过卷积抽取后,输出特征图的尺寸往往小于输入的尺寸,因而图上每一个像素的感受野就变大,同时,在更小的特征图上生成的锚框数量也更少,因此,小的特征图适合检测尺寸大的目标,反之,大的特征图适合检测尺寸小的目标。
如下图中展示的,越靠近输入图片的特征块尺寸越大,所提出的锚框对尺寸小的目标往往有很好的效果。因此,SSD有多个不同的检测分支,不同的检测分支可以检测多个尺度的目标,所以SSD在多尺度目标检测的精度上有了很大的提高,对小目标检测效果要好很多。
四、YOLO系列
对于YOLO系列的网络,本文会介绍地稍微详细一些。
YOLO全名是You Only Look Once,其含义是,相比RCNN这样的二阶段算法,YOLO不需要先获得候选框,而是直接预测边界框。YOLO最大的优点就是快,虽然精度不如RCNN系列,但是因为其运算速度快,广泛应用于各种现实场景中(RCNN凭借更高的精度目前也并未被淘汰)。
YOLO v1
在RCNN中,最终的预测是由候选的锚框偏移、缩放而来的,YOLO的思想就是直接在输出层预测锚框的位置和类别。即,将图像分类网络的输出向量设置为 ( x , y , h , w , c ) (x, y, h, w, c) (x,y,h,w,c),其中, x , y , h , w x, y, h, w x,y,h,w分别表示锚框的中心坐标、高和宽, c c c表示置信度(confidence)。这样,一个分类网络就变成了一个检测网络5。
- 这里有一个小疑问,为什么之前的网络不采用这种直接预测的方式呢?
答:应该是受到算力的限制。 在RCNN和YOLO1的年代,卷积还没有被推广,RCNN使用的网络也只是vgg16。试想,要求模型直接回归预测出一个框,这个框可能出现在图片的任何位置、大小也是任意的,相当于需要在一个相当大的解空间中进行预测,这样做效果应当较差(YOLO这么做也牺牲了一定的精度)。
当然,这只是一个相当简单的雏形,还需要有很多细节需要补充。有三个问题需要解决:
- 需要检测多个目标;
- 需要检测多类目标;
- 需要检测尺寸不同的目标。
1.检测多个目标:
应对多个目标检测的方法很简单——多加几个框就好啦。YOLO的思想是对将图片平均分成
n
×
m
n\times m
n×m个区域(grid),在每个区域中去搜索
k
k
k个框,这样全图就能生成
n
×
m
×
k
n\times m \times k
n×m×k个框,也就能最多检测
n
×
m
×
k
n\times m \times k
n×m×k个目标。
- 为什么不直接生成
n
×
m
×
k
n\times m \times k
n×m×k个框在全图范围搜索,而要划分区域呢?
答:这样做的好处就是能够避免大量的重复计算。不同区域之间没有重叠,这样就也不会产生过多的重复计算(同一个区域内搜索 k k k个框,因此还是有,但比不划分区域少了很多)。 - 为什么每个区域内要搜索
k
k
k个框?
答:当一个区域内有多个物体时,就需要多个框进行搜索(YOLOv1 的版本中 k = 1 k = 1 k=1,在后续版本中每个grid中搜索多个框,这样可以在每个区域中检测出多个目标)。
在输出框中,难免会有一些框存在重合,这时就掏出前面介绍过的NMS方法,筛去重合度较高的框。
2.检测多类目标:
如上图所示,如果我们同时需要检测狗、单车、汽车,那么预测出边界框是不够的,我们还需要对框进行分类。这个好解决,只需要套用分类问题的方案,加上一个one-hot编码就行。
3.检测不同尺寸的目标:
网络对较小尺寸的目标检测效果差。这和前面SSD中说到的原因是一样的——在靠近输出端的特征图中每个元素的感受野大,是更适合检测大尺寸目标的。YOLOv1对这个问题的解决方案就是多加一组神经元来专门检测小目标,但效果也并没有很好。
置信度(confidence)
这是前面略过没讲,但蛮重要的一个概念。在图像分类问题中,我们直接用softmax输出的“概率”作为分类准确的置信度。但在YOLO中,置信度由以下公式定义
c
o
n
f
i
d
e
n
c
e
=
Pr
(
o
b
j
)
×
I
O
U
t
r
u
t
h
pred
confidence=\operatorname{Pr}(o b j) \times I O U_{t r u t h}^{\text {pred }}
confidence=Pr(obj)×IOUtruthpred
IOU表示真实边界框与预测边界框的交并比,Pr的含义是“目标的中心是否落在此边界框中”。这样做的效果就是,对于一个目标,YOLO只让1个grid去预测目标的边界框。
小结
在YOLOv1的原始论文中,采用的参数是:将输入的图片划分为
7
×
7
7 \times7
7×7个grid,每个grid预测一个目标,也就是说最多可检测49个目标(每一个grid最多检测1个目标),需要98个框(两个框对应一个类,可以是大目标,也可以是小目标)。同时,可以识别20个不同的类。
YOLO v2
YOLO v2 是在v1上的改进版本,主要从两个方面进行了改动:
- 增加每个每个grid中预测的边界框数目(即 k > 1 k > 1 k>1);
- 基于锚框去预测偏移量,而不是直接预测边界框的位置。
增加每个grid中预测的边界框数目很好理解,就是为了应对“多个目标出现在同一个grid中的情况”。至于第二点的改动,主要是为了避免模型在训练前期的不稳定(约束了位置预测的范围,参数就更容易学习,模型就更稳定),下面具体介绍一下。
上公式
b
x
=
σ
(
t
x
)
+
c
x
b
y
=
σ
(
t
y
)
+
c
y
b
w
=
p
w
e
t
w
b
h
=
p
h
e
t
h
\begin{aligned} b_{x} & =\sigma\left(t_{x}\right)+c_{x} \\ b_{y} & =\sigma\left(t_{y}\right)+c_{y} \\ b_{w} & =p_{w} e^{t_{w}} \\ b_{h} & =p_{h} e^{t_{h}} \end{aligned}
bxbybwbh=σ(tx)+cx=σ(ty)+cy=pwetw=pheth
其中,σ是激活函数,
b
x
,
b
y
,
b
w
,
b
h
b_{x}, b_{y},b_{w},b_{h}
bx,by,bw,bh是最终边界框的中心坐标、宽和高;
t
x
,
t
y
,
t
w
,
t
h
t_{x}, t_{y},t_{w},t_{h}
tx,ty,tw,th是模型要预测的值(偏移量);
c
x
,
c
y
c_{x},c_{y}
cx,cy为grid左上角坐标;
p
w
,
p
h
p_{w},p_{h}
pw,ph为锚框的宽和高。
可以看到,最后的输出的边界框中心坐标是由grid位置变换得来的,宽和长是由anchor的宽和长变换来的。所以,模型通过学习基于Anchor框的宽和高和grid的先验位置的偏移量,得到最终目标的位置,这种方法也叫作location prediction。
- 为什么要使用锚框呢?
答:在YOLO v2中,作者观察了很多图片的所有Ground Truth,发现:比如车,GT都是矮胖的长方形,再比如行人,GT都是瘦高的长方形,且宽高比具有相似性。根据这一点,作者从数据集中预先准备几个几率比较大的bounding box,再以它们为基准进行预测。
YOLOv2为每个grid提供了5个锚框作为基准。
那么锚框是怎么来的呢?为什么是5个呢?
对于任意一个数据集,就比如说COCO吧(紫色的anchor),先对训练集的GT bounding box进行聚类,聚成几类呢?作者进行了实验之后发现5类的recall vs. complexity比较好,现在聚成了5类,当然9类的mAP最好,预测的最全面,但是在复杂度上升很多的同时对模型的准确度提升不大,所以采用了一个比较折中的办法选取了5个聚类簇,即使用5个先验框6。
YOLO v3
虽然v2做了许多改进,整体性能大幅度提升,但是对于小目标的检测依旧不理想。直到ResNet的提出,使得网络可以更深更强,加上SSD的设计思想,v3在小目标的检测上出现了重大突破。
从网络结构上来看,YOLOv3最大的改进就是用不同尺度的特征块检测不同尺寸的目标。下图能更好地展示这个结构6,v3的检测头分为了大、中、小三个部分:
- N 1 : 13 × 13 × 3 × ( 4 + 1 + 80 ) N_1:13 \times13 \times3 \times(4+1+80) N1:13×13×3×(4+1+80)
- N 2 : 26 × 26 × 3 × ( 4 + 1 + 80 ) N_2:26 \times26 \times3 \times(4+1+80) N2:26×26×3×(4+1+80)
- N 3 : 52 × 52 × 3 × ( 4 + 1 + 80 ) N_3:52 \times52 \times3 \times(4+1+80) N3:52×52×3×(4+1+80)
以
N
1
N_1
N1为例,输入图像被平均分割为
13
×
13
13 \times13
13×13个grid,每个grid有3个框,每个框对应4维坐标、1维置信度以及80个类别。
与v2类似地,v3页有一些(9个)先验框(从训练集聚类而来)。
对于网络结构,还需要解释一下两个点:
- 特征图拼接(concat):将特征图直接按照通道维度进行拼接(特征融合),这里涉及到维度不同的问题,就需要进行“上采样”操作。
- 上采样(upsample):以小尺寸的特征图生成大尺寸的特征图,可以用转置卷积等方法,论文中作者采用最近邻插值算法。
YOLOv3的训练策略如下7
- 预测框一共分为三种情况:正例(positive)、负例(negative)、忽略样例(ignore)。
- 正例:任取一个ground truth,与4032个框全部计算IOU,IOU最大的预测框,即为正例。并且一个预测框,只能分配给一个ground truth。例如第一个ground truth已经匹配了一个正例检测框,那么下一个ground truth,就在余下的4031个检测框中,寻找IOU最大的检测框作为正例。ground truth的先后顺序可忽略。正例产生置信度loss、检测框loss、类别loss。预测框为对应的ground truth box标签(需要反向编码,使用真实的 x , y , w , h x,y,w,h x,y,w,h计算出 t x , t y , t w , t h t_x,t_y,t_w,t_h tx,ty,tw,th);类别标签对应类别为1,其余为0;置信度标签为1。
- 忽略样例:正例除外,与任意一个ground truth的IOU大于阈值(论文中使用0.5),则为忽略样例。忽略样例不产生任何loss。
- 负例:正例除外(与ground truth计算后IOU最大的检测框,但是IOU小于阈值,仍为正例),与全部ground truth的IOU都小于阈值(0.5),则为负例。负例只有置信度产生loss,置信度标签为0。