https://arxiv.org/abs/1808.01244
在目标检测中使用anchor box的两个缺点:(1)在检测过程中会生成大量anchor box并计算每个anchor box和ground truth box的IoU。其中大部分的anchor box都是负样本而被丢弃。这个机制减慢了训练速度,增加了计算开销。 (2)anchor机制引入了更多的超参数,比如anchor box的大小、长宽比等,这增加了系统设计的复杂度。
提出一个新的one-stage但不需要anchor box的目标检测算法,通过预测bbox的左上角点坐标和右下角点坐标,得到目标的bbox定位。同时提出一个新的corner pooling操作,帮助卷积网络更好地定位bbox的角点。
将hourglass network的最后一个卷积层的输出分别输入到两个分支,分别用于预测左上角点和右上角点的heatmaps,embeddings,offsets。
使用heatmap去检测定位角点。heatmaps有C个通道,对应C个类别(不包含背景类),本质上第k个通道都是一个针对第k类的二值掩码,在该通道上的每个位置的值可以理解为是第k类的bbox的左上(右下)角点的概率。
在训练时,考虑到角点在真值角点的附近时,依然可以形成一个和真值bbox的IoU接近1的bbox,所以当预测的角点在真值角点的某个半径的范围内时,可以适当减少损失。
半径的确定:处于真值(左上、右下)角点的半径范围内的预测(左上、右下)角点构成的bbox和真值bbox的IoU至少为t(论文中为0.3)
# 根据预测到的bbox计算半径
def gaussian_radius(det_size, min_overlap):
height, width = det_size
a1 = 1
b1 = (height + width)
c1 = width * height * (1 - min_overlap) / (1 + min_overlap)
sq1 = np.sqrt(b1 ** 2 - 4 * a1 * c1)
r1 = (b1 - sq1) / (2 * a1)
a2 = 4
b2 = 2 * (height + width)
c2 = (1 - min_overlap) * width * height
sq2 = np.sqrt(b2 ** 2 - 4 * a2 * c2)
r2 = (b2 - sq2) / (2 * a2)
a3 = 4 * min_overlap
b3 = -2 * min_overlap * (height + width)
c3 = (min_overlap - 1) * width * height
sq3 = np.sqrt(b3 ** 2 - 4 * a3 * c3)
r3 = (b3 + sq3) / (2 * a3)
return min(r1, r2, r3)
def gaussian2D(shape, sigma=1):
m, n = [(ss - 1.) / 2. for ss in shape]
y, x = np.ogrid[-m:m+1,-n:n+1]
h = np.exp(-(x * x + y * y) / (2 * sigma * sigma))
h[h < np.finfo(h.dtype).eps * h.max()] = 0
return h
def draw_gaussian(heatmap, center, radius, k=1):
diameter = 2 * radius + 1
gaussian = gaussian2D((diameter, diameter), sigma=diameter / 6)
x, y = center
height, width = heatmap.shape[0:2]
left, right = min(x, radius), min(width - x, radius + 1)
top, bottom = min(y, radius), min(height - y, radius + 1)
masked_heatmap = heatmap[y - top:y + bottom, x - left:x + right]
masked_gaussian = gaussian[radius - top:radius + bottom, radius - left:radius + right]
np.maximum(masked_heatmap, masked_gaussian * k, out=masked_heatmap)
角点位置预测的损失函数:
N为图片中真值bbox的个数。pcij为第c个通道的位置(i, j)处为角点的概率。ycij为标签,表示第c个通道的位置(i, j)处为角点的概率值,以ycij=1的(i, j)位置为中心点,形成一个概率的高斯分布,预测的角点越靠近ycij=1的(i, j)点,其损失越小。
许多网络对输入进行下采样获取全局信息并减少显存占用,输出时的规格比输入的原始图片要小。所以在预测bbox时,角点从原始图像映射到更小规格的heatmap上,在按比例缩小的过程中,导致了坐标精度的损失,影响定位效果。为了解决这个问题,增加一个位置偏移预测,通过预测偏移矫正角点的定位。
n是下采样系数。损失函数:
使用了smoothL1损失函数,增强对噪声的鲁棒性。
在一副图片上检测到多个左上角点和右下角点后,需要将属于同一个bbox的左上角点和右下角点进行配对,忽略多余的角点。神经网络为每一个被检测的角点预测一个embedding vector。属于同一个bbox的左上角点和右下角点的embedding vector的欧式距离应该尽可能小,不属于同一个bbox的左上角点和右下角点的embedding vector的欧式距离要尽量大。在预测时就可以通过计算各个角点的embedding vector的距离进行配对。
损失函数:
etk为左上角点的embedding vector,ebk是右下角点的embedding vector。ek为etk和ebk的平均值
由于角点的位置没有视觉上的显示,所以为了定位左上角点,需要在特征图的水平方向上从左向右找到bbox的上边界,在特征图的垂直方向从上向下找到bbox的左边界,通过两条边界确定左上角点(右下角点同理)。所以提出了corner pooling的新池化方法用于更好地定位角点。
垂直方向上corner pooling的公式:
t(i+1)j表示在第j列上,第i+1行到第H行的值中最大的值,实际上就是一个动态规划。
水平方向上corner pooling公式(同理):
Corner pooling在网络中的使用:
虚线框中的两个灰块分别是对水平方向和垂直方向的corner pooling
沙漏网络首先通过max pooling进行多次下采样,然后多次上采样后恢复到原始分辨率,并通过跳跃连接恢复丢失的细节。多个沙漏网络能够堆叠构成一个更大的网络,适合目标检测。本文网络由两个沙漏网络堆叠而成,并对网络结构做了一些修改,比如把max pooling改为stride=2的卷积层、将特征分辨率减小5倍并增加了特征通道数、添加中间监督训练等等(具体看原文)。
MS COCO
以上实验结果说明了corner pooling的有效性,根据bbox的大小确定损失减小半径的有效性以及沙漏网络的有效性。
对于corner pooling仍然有点不明白为什么要这样做。为什么这样的pooling能够对角点的定位有效果?如果把corner pooling换成其他的操作,比如卷积层,是否效果会变差?