下面借这篇blog记录一些阅读笔记,如果问题,恳请指出。
paper:CornerNet: Detecting Objects as Paired Keypoints
内容重点:舍去了生成anchor的思想,取而代之的是使用了关键点检测。将对象边界框检测为一对关键点(左上角和右下角)。消除了生成anchor所带来的的正负样本不均的问题。同时介绍了一种新的池化层corner pooling,使得网络可以更好的定位到两个关键点。
1. Introdution
在One-step的目标检测网络中,通常会大量的使用anchor box,依次使得准确度能够媲美Two-steps检测网络。但是由于anchor box是由一些利用的不同的面积与比例预测对象框,这意味着需要在特征矩阵上进行密集的使用。然后再通过分类网络与回归网络细化坐标或者进行筛选。
但是使用anchor的概念会带来两个缺点:
1)需要生产非常多的anchor boxes。在DSSD中需要40k+,而在RetinaNet中需要100k+。这是因为检测器被训练来分类每个anchor box是否与ground truth充分重叠,并且需要大量的anchor box来确保与大多数ground truth充分重叠。因此,只有一小部分anchor box会与ground truth重叠;这造成了正负样本(positive and negative anchor boxes)之间的巨大不平衡,减缓了训练。
2)anchor boxes的使用会导致非常多的超参数与设计的选择。仅仅对于anchor boxes,就设计到多少的boxes,什么尺寸,什么比例。这些选择需要慢慢试探。而当与多尺度体系结构相结合的时候会变得更加的复杂,比如结合FPN结构。在网络中会有多个预测特征层,需要在每个预测特征层上进行单独预测。由于每层的预测特征层拥有不同的分辨率,所以需要分别生成各组的anchor boxes。
基于以上考虑,CornerNet中没有使用基于anchor的方法。而是通过获取图像的一堆关键点(目标的左上角与右下角)来进行目标检测。
创新点: 1)利用左上角与右下角这么一对关键点进行目标检测。关键点的获取通过一个卷积神经网络生成heatmap与embedding来获取,为了提高准确度额外生成一个offsets减少偏移损失。在下文会对headmap与embedding进行详细讲解。 2)使用了一种新的池化层称为:corner pooling。有助于卷积网络更好地定位边界框的角点。 3)使用了Hourglass作为特征提取网络
利用一对关键点进行目标检测比利用anchor进行检测更加有效的可能原因是:
1)anchor的中心依赖于检测对象的4条边界,而定位一个corner只需要检测对象的两条边界,所以corner比anchor更容易定位。而在针对corner检测的cornor pooling辅助下,corner的定位会更加的容易。因为corner pooling可以获取corner定义的一些先验知识。
2)使用corner能更高效地计算boxes的离散空间位置:使用corner只要O(wh)计算复杂度就能得到所有的可能anchor boxes,但是使用anchor boxes需要O(w2h2)的复杂度。
2. CornerNet
下面会分别对CornerNet的思路,创新点等方面进行讲解。
2.1 Overview
在CornerNet中,我们将对象检测为一对关键点——边界框的左上角和右下角。通过卷积网络预测生成两组heatmap去代表不同对象类别的角点位置。其中一组用于左上角点的预测,而另外一组用与右下角点的预测。
此外,为每个预测到的角点还会提供一个embedding vetor,当来自同一个目标对象的两个角点的两个embedding vetor应该是比较相识的。也就是这两个embedding vetor之间的距离是比较小的。 同时,为了让预测的边界框更加的准确,网络还预测了offset vector,来微调预测得到的corner。所以,通过网络预测heatmaps,embedding vetor与offset,再经过检测的后处理,得到最终的预测边界框。
完整的结构如图所示: 在CornerNet中,使用了hourglass network作为骨干网络,但是这里没有多层的预测特征层,也就没有不同比例的特征,所以直接在最后一层的输出特征图上进行后续处理。
在特征提取之后,会接两个预测模块,其中一个用于左上角点的预测,令一个模块用于右下角点的预测。对于每个单独的模块,经过角点池化模块之后,都有自己的预测heatmap,embedding vetor与offset矩阵。
每组hetmap都有C通道,其中C是类别数,大小为H ×W,注意这里没有背景类别。每个channel都是一个binary mask,表明一个类的位置所在处。
以上就是CornerNet的大致过程。
2.2 Detecting Corners
对于每一个角点,都有一个ground-truth positive的位置,而其他的位置都是negative。在训练过程中,不是同等地惩罚负位置,而是在正位置的一定半径范围内减少对负位置的惩罚。
这是因为尽管某一对关键点的检测错误,但是如果他们仍然靠近各自的ground truth位置时,这对错误的关键点仍然可以产生与ground truth充分重叠的面积。这里上述半径的值设置为能使处于这个半径范围内的一对corner能够与GT有足够的IoU,文中阈值为0.3。给定半径后,半径内corner减少的惩罚量通过一个以正样本corner为中心的非归一化的二维高斯函数得到:
e
?
x
2
+
y
2
2
σ
2
e^{-\frac{x^{2} + y^{2}}{2\sigma^{2}}}
e?2σ2x2+y2?.(其中:
σ
=
1
3
?
r
\sigma = \frac{1}{3}·r
σ=31??r)
让pcij表示heatmaps第c个channel上(i,j)位置的corner表示物体为类c的得分,ycij表示由高斯增强后的ground-truth heatmap值。
检测损失:
L
D
e
t
=
?
1
N
∑
c
=
1
C
∑
i
=
1
H
∑
j
=
1
W
{
(
1
?
p
c
i
j
)
α
l
o
g
(
p
c
i
j
)
if?
y
c
i
j
?=?1
(
1
?
y
c
i
j
)
β
(
p
c
i
j
)
α
l
o
g
(
1
?
p
c
i
j
)
otherwise
L_{Det} = -\frac{1}{N}\sum_{c=1}^{C}\sum_{i=1}^{H}\sum_{j=1}^{W} \begin{cases} (1 - p_{cij})^{α}log(p_{cij}) && \text{if $y_{cij}$ = 1} \\ (1 - y_{cij})^{β}(p_{cij})^{α}log(1-p_{cij}) && \text{otherwise} \end{cases}
LDet?=?N1?c=1∑C?i=1∑H?j=1∑W?{(1?pcij?)αlog(pcij?)(1?ycij?)β(pcij?)αlog(1?pcij?)??if?ycij??=?1otherwise?
分析: 先忽略ycij,可以看见这个损失函数是在交叉熵损失函数的基础上改变而来。对于正样本预测时,会执行上半式子。此时,pcij是一个比较大的值,也说明预测得比较容易,所以通过参数
(
1
?
p
c
i
j
)
α
(1-p_{cij})^{α}
(1?pcij?)α来控制其损失权重,使得权重不至于太大。对于负样本预测时,会执行下半式子。此时,pcij会正确预测此时的类别不正确,所以pcij会是一个比较小的数值。同样的,通过
(
p
c
i
j
)
α
(p_{cij})^{α}
(pcij?)α来控制其损失权重,使得权重不至于太大。
考虑ycij,当对正样本进行预测时,如果ycij=1,(i,j)位置与ground truth物体的(i,j)位置相比的一个分值,即若刚好为ground truth位置。而如果是其他的情况时,此时表示(i,j)点不是类别c的目标角点,也就是预测错误。但是这里由于使用了ground truth角点的高斯分布计算,所以如果是距离ground truth比较近的(i,j)点的ycij值也会接近于1,这部分通过β参数控制,使得
(
1
?
y
c
i
j
)
β
(1-y_{cij})^{β}
(1?ycij?)β来控制其损失权重,使得权重不至于太大。
Figure5是关于对不同负样本点的损失函数采取不同权重值的原因。红色实线框是ground truth;橘色圆圈是根据ground truth的左上角角点、右下角角点和设定的半径值画出来的,半径是根据圆圈内的角点组成的框和ground truth的IOU值大于0.7而设定的,圆圈内的点的数值是以圆心往外呈二维的高斯分布;白色虚线是一个预测框,可以看出这个预测框的两个角点和ground truth并不重合,但是该预测框基本框住了目标,因此是有用的预测框,所以要有一定权重的损失返回,这就是为什么要对不同负样本点的损失函数采取不同权重值的原因。 而且,对于一般的卷积神经网络为了提取全局的信息,一般会不断的进行下采样这样会导致输出的特征矩阵与输入的特征矩阵不一致,通常输出的特征矩阵会比输入的特征矩阵的尺度要小。
假设缩小倍数是n,那么输入图像上的(x,y)点对应到特征图为
(
[
x
n
,
y
n
]
)
([\frac{x}{n},\frac{y}{n}])
([nx?,ny?]),式子中的符号是向下取整。当我们将热图中的位置重新映射到输入图像时,可能会失去一些精度,这可能会极大地影响带有地面真相的小边界框的IoU。为了解决这个问题,我们预测位置偏移,以便在将角位置重新映射到输入分辨率之前稍微调整它们。
偏移量
o
k
=
(
x
k
n
?
[
x
k
n
]
,
y
k
n
?
[
y
k
n
]
)
o_{k} = (\frac{x_{k}}{n}-[\frac{x_{k}}{n}],\frac{y_{k}}{n}-[\frac{y_{k}}{n}])
ok?=(nxk???[nxk??],nyk???[nyk??]),其中
x
k
,
y
k
x_{k},y_{k}
xk?,yk?分别是角点的x,y坐标。所以现在,预测了所有类别的左上角共享的一组偏移,以及右下角共享的另一组偏移。然后在训练的时候,通过smooth L1损失函数监督学习该参数,和常见的目标检测算法中的回归支路类似。
偏移损失公式:
L
o
f
f
=
1
N
∑
k
=
1
N
S
m
o
o
t
h
L
1
L
o
s
s
(
o
k
,
o
^
k
)
L_{off} = \frac{1}{N}\sum_{k=1}^{N}SmoothL1Loss(o_{k},\hat{o}_{k})
Loff?=N1?k=1∑N?SmoothL1Loss(ok?,o^k?)
2.3 Grouping Corners
图像中可能出现多个对象,因此可能检测到多个左上角和右下角。我们需要确定一对左上角和右下角是否来自同一个边界框。
这里作者借鉴了Newell等人提出的用于多人姿态估计任务的关联嵌入方法的启发。Newell等人检测所有的人类关节,并为每个检测到的关节生成一个嵌入。他们根据嵌入物之间的距离对关节进行分组。
关联嵌入的思想也适用于目标检测任务。该网络预测每个检测到的角的嵌入向量(Embedding vector),使得如果左上角和右下角属于同一边界框,则它们的嵌入之间的距离应该比较小。然后,我们可以根据左上角和右下角的嵌入之间的距离来对角进行分组。Embedding的实际值并不重要。重要的是一对corners相似就行。
embedding损失包含两部分,etk表示第k个目标的左上角角点的embedding vector,ebk表示第k个目标的右下角角点的embedding vector,ek表示etk和ebk的均值。pull loss用来缩小属于同一个目标(第k个目标)的两个角点的embedding vector(etk和ebk)距离。push loss用来扩大不属于同一个目标的两个角点的embedding vector距离,令Δ=1。
embedding距离损失公式:
L
p
u
l
l
=
1
N
∑
k
=
1
N
[
(
e
t
k
?
e
k
)
2
+
(
e
b
k
?
e
k
)
2
]
L_{pull} = \frac{1}{N}\sum_{k=1}^{N}[(e_{tk}-e_{k})^{2}+(e_{bk}-e_{k})^{2}]
Lpull?=N1?k=1∑N?[(etk??ek?)2+(ebk??ek?)2]
L
p
u
s
h
=
1
N
(
N
?
1
)
∑
k
=
1
N
∑
j
=
1
&
j
≠
k
N
m
a
x
(
0
,
△
?
∣
e
k
?
e
j
∣
)
L_{push} = \frac{1}{N(N-1)}\sum_{k=1}^{N}\sum_{j=1\&j≠k}^{N}max(0,△-|e_{k}-e_{j}|)
Lpush?=N(N?1)1?k=1∑N?j=1&j?=k∑N?max(0,△?∣ek??ej?∣)
2.4 Corner Pooling
corner pooling layer来帮助更好的定位物体bounding box的对角。因为有时物体bounding box的两个对角处会没有信息。 这种情况下corner就很难通过局部特征进行定位。那么为了确定某个像素点是否有一个top-left corner,我们就需要从该点出发向其水平有方向去看看,以及向其垂直向下方向看看。那么这就是corner pooling layer要做的工作,它输入两个特征层,第一个特征层,在每个像素点做该点水平右边所有像素的最大池化得到该点的一个值,第二个特征层则对每个像素点做该点垂直下面所有像素的最大池化,最后将两个池化结果相加。如下图: 这一步可以用数学公式来表示,这是一个递归的公式:
t
i
j
=
{
m
a
x
(
f
t
i
j
,
t
(
i
+
1
)
j
)
i
<
H
f
t
H
j
otherwise
l
i
j
=
{
m
a
x
(
f
l
i
j
,
l
i
(
j
+
1
)
)
j
<
W
f
l
i
W
otherwise
t_{ij} = \begin{cases} max(f_{t_{ij}},t_{(i+1)j})& \text{$i < H$}\\ f_{t_{H_{j}}}& \text{otherwise} \end{cases} \\ l_{ij} = \begin{cases} max(f_{l_{ij}},l_{i(j+1)})& \text{$j < W$}\\ f_{l_{i_{W}}}& \text{otherwise} \end{cases}
tij?={max(ftij??,t(i+1)j?)ftHj????i<Hotherwise?lij?={max(flij??,li(j+1)?)fliW????j<Wotherwise? 其中ft为用于水平方向的特征图,fl为用于垂直方向的特征图。图像的尺寸为H×W。水平方向那个特征图上tij的值等于ft特征图上(i, j) 到 (i, H) 所有点的最大值。同理,垂直方向lij则为特征图fl上(i, j) 到 (W, j)所有点的最大值。 该池化操作是可以通过下面方式高效计算: 从右到左做max求每个点值得到水平特征图,从下到上求每个点值得到垂直特征图,最后相加即可。
2.5 prediction module
该模块的第一部分是residual block的修改版本 最开始的结构讲到backbone之后连接两个prediction module,分别预测两个corner。这里详细介绍prediction module内部结构,以左上角corner(top-left corner)对应module为例。
backbone之接着两个3×3的卷积module(灰色的 3×3 Conv-BN-ReLU),这两个module各自输出1个feature map分别作为上文中提到的ft和fl传到Corner pooling做池化操作,然后pooling最后输出的结果再经过一个3×3 Conv-BN layer,然后再和shortcut相加后relu激活,激活结果紧跟一个卷积module,然后再跟着3个3×3 Conv-ReLU-Conv分支分别对应heatmaps, embeddings 和offset的预测。
2.6 Hourglass Network
Hourglass Network结构如下: CornerNet采用 Hourglass Network做骨干网,Hourglass Network是一个全卷积网络,由一个或多个hourglass module组成。每个hourglass module首先通过卷积c层和max pooling layer下采样输入特征层,然后通过一系列的上采样操作和卷积层上采样回原resolution。但是max pooling layer会丢失很多细节,于是增加了skip layer来补上细节。这样Hourglass Network就能同时捕获全局和局部特征。
hourglass module结构示意图如下: CornerNet采用了2个Hourglass组成的Hourglass Network,作者在使用Hourglass时做了一些小调整,包括:
-
Hourglass在下采样时不再进行max-pooling,而是在卷积时通过stride=2进行下采样。下采样的卷积进行5次,输出feature maps的通道数分别为(256, 384, 384, 384, 512) -
在每个skip connection,有两个residual modules。 -
图片进入Hourglass前,进行了2次下采样。使用一个kernel size=7*7,stride=2,channel=128的卷积和一个stride=2,channel=256的residual block,将width和height缩小为以前的1/4。
3. Experiments
3.1 Training Details
网络在PyTorch的默认设置下随机初始化,不需要对任何外部数据集进行预处理。在训练期间,作者将网络的输入分辨率设置为511 × 511,这导致输出分辨率为128 × 128。作者使用了多种数据增加来避免过拟合,而且在输入图片之前会使用PCA预处理。
总的损失函数公式:
L
=
L
d
e
t
+
α
L
p
u
l
l
+
β
L
p
u
s
h
+
γ
L
o
f
f
L = L_{det} + αL_{pull} + βL_{push} + γL_{off}
L=Ldet?+αLpull?+βLpush?+γLoff? 其中,α、β和γ分别是embedding距离损失公式和偏置损耗的权重。将α和β都设置为0.1,γ为1。发现1或更大的α和β值会导致较差的性能。
3.2 Testing Details
0)使用simple post-processing算法从Heatmaps, Embeddings, Offsets生成边界框。 1)在得到预测角点后,会对这些角点做NMS操作,选择前100个左上角角点和100个右下角角点。 2)计算左上角和右下角角点的embedding vector的距离时采用L1范数,距离大于0.5或者两个点来自不同类别的目标的都不能构成一对。 3)测试图像采用0值填充方式得到指定大小作为网络的输入,而不是采用resize,另外同时测试图像的水平翻转图并融合二者的结果。 4)最后通过soft-nms操作去除冗余框,只保留前100个预测框。
4. Result
-
backbone与corner的作用 -
corner pooling的作用 -
有无heatmaps与offset的对比 -
与其他SOTA算法对比
总结: 想法比较新颖,通过一对关键点来实现预测边界框,同时使用corner pooling来辅助预测关键点。
不过看完论文之后,感觉还有很多细节没有弄懂,只是了解了大概的处理过程,完全弄懂可能得看一下代码了。
参考资料:
- https://blog.csdn.net/edward_zcl/article/details/100858681
- https://blog.csdn.net/u014380165/article/details/83032273
- https://blog.csdn.net/yanghao201607030101/article/details/110118751
|