目标检测中anchor的生成过程理解

Anchor Box : 预定义边框就是一组预设的边框,在训练时,以真实的边框位置相对于预设边框的偏移来构建。预设边框先大致在可能的位置“框“出来目标,然后再在这些预设边框的基础上进行调整

一个Anchor Box可以由:边框的纵横比和边框的面积(尺度)来定义,相当于一系列预设边框的生成规则,根据Anchor Box,可以在图像的任意位置,生成一系列的边框。

由于Anchor box 通常是以CNN提取到的Feature Map 的点为中心位置,生成边框,所以一个Anchor box不需要指定中心位置。

  • 使用CNN提取的Feature Map的点,来定位目标的位置。
  • 使用Anchor box的Scale来表示目标的大小
  • 使用Anchor box的Aspect Ratio来表示目标的形状

常用的Anchor Box定义

  • Faster R-CNN 定义三组纵横比ratio = [0.5,1,2]和三种尺度scale = [8,16,32],可以组合处9种不同的形状和大小的边框。
  • YOLO V2 V3 则不是使用预设的纵横比和尺度的组合,而是使用k-means聚类的方法,从训练集中学习得到不同的Anchor
  • SSD 固定设置了5种不同的纵横比ratio=[1,2,3,1/2,1/3],由于使用了多尺度的特征,对于每种尺度只有一个固定的scale

Anchor 的意义

Anchor Box的生成是以CNN网络最后生成的Feature Map上的点为中心的(映射回原图的坐标),以Faster R-CNN为例,使用VGG网络对对输入的图像下采样了16倍,也就是Feature Map上的一个点对应于输入图像上的一个16×16

的正方形区域(感受野)。根据预定义的Anchor,Feature Map上的一点为中心 就可以在原图上生成9种不同形状不同大小的边框,如下图:

从上图也可以看出为什么需要Anchor。根据CNN的感受野,一个Feature Map上的点对应于原图的16×16的正方形区域,仅仅利用该区域的边框进行目标定位,其精度无疑会很差,甚至根本“框”不到目标。 而加入了Anchor后,一个Feature Map上的点可以生成9中不同形状不同大小的框,这样“框”住目标的概率就会很大,就大大的提高了检查的召回率;再通过后续的网络对这些边框进行调整,其精度也能大大的提高。

1. Faster R-CNN的Anchor Box

Faster R-CNN中的Anchor有3种不同的尺度128×128,256×256,512×512 ,3种形状也就是不同的长宽比W:H=1:1,1:2,2:1,这样Feature Map中的点就可以组合出来9个不同形状不同尺度的Anchor Box。

Faster R-CNN进行Anchor Box生成的Feature Map是原图下采样16倍得到的,这样不同的长宽比实际上是将面积为16×16

的区域,拉伸为不同的形状,如下图:

不同的ratio生成的边框的面积是相同的,具有相同的大小。三种不同的面积(尺度),实际上是将上述面积为16×16

的区域进行放大或者缩小。
128×128是16×16放大8倍;256×256是放大16倍;512×512

则是放大32倍。如下图:

Anchor 计算

这里先计算每个Anchor的长和宽,至于其中心位置是Feature Map的每个点在原图上的映射,是固定,可以先不考虑。

从上面可以知道,任意的形状和大小的Anchor的宽和高都可以从最基础的宽和高16×16变换而来。首先看三种ratio的变换。

设矩形框的面积s=16×16,矩形框的宽w,高为h,则有:

所以最终得到,

不同尺度的是在基础的尺度上的缩放,设尺度为scale,则缩放后的面积为scale?s。当然也可以从宽高的缩放比例来看,基础的面积为16×16。(128*128 / 16*16 = 8*8)

通过上面的计算,实际只是得到了9种不同的可以放在任意位置矩形框(因为矩形框的中心位置还没有确定)。 边框的中心位置,是将Feature map上的点映射回原图得到的,Feature map任一点对应的是原图的一块正方形区域,其中心位置就落在改区域的中心位置。以Feature map上(0,0)点为例,其对应于原图的(0,0,15,15)(左上角坐标,右下角坐标),则在改点生成Anchor box的中心点就是原图的(7.5,7.5),Feature Map上其余位置在原图对应的中心点在此基础上进行平移即可得到。例如Feature Map上(0,0)的点在原图上对应区域的的中心点为(7.5,7.5),则(0,1)对应的中心点为(7.5,7.5 + 16),依次类推(x,y)对应的中心点为(x * 16 + 7.5 ,y * 16 + 7.5)。如果是以(左上角坐标,右下角坐标)表示的矩形框,则将(左上角坐标,右下角坐标)平移相应的距离即可。

代码如下:

base_size=16。这个参数指定了feature map上一点对应到原图的大小为16x16的区域。也可以根据需要自己设置。

第一句代码表示最基本的一个大小为16x16的区域,四个值,分别代表这个区域的左上角和右下角的点的坐标。

这一句是将前面的16x16的区域进行ratio变化,也就是输出三种宽高比的anchors,这里调用了_ratio_enum函数,其定义如下:

进行完上面的宽高比变换之后,接下来执行的是面积的scale变换:

这里最重要的是_scale_enum函数,该函数定义如下,对上一步得到的ratio_anchors中的三种宽高比的anchor,再分别进行三种scale的变换,也就是三种宽高比,搭配三种scale,最终会得到9种宽高比和scale 的anchors。这就是论文中每一个点对应的9种anchors。

这个函数中又调用了一个_whctrs函数,这个函数定义如下,其主要作用是将输入的anchor的四个坐标值转化成(宽,高,中心点横坐标,中心点纵坐标)的形式。

_scale_enum函数中也是首先将宽高比变换后的每一个ratio_anchor转化成(宽,高,中心点横坐标,中心点纵坐标)的形式,再对宽和高均进行scale倍的放大,然后再转换成四个坐标值的形式。最终经过宽高比和scale变换得到的9种尺寸的anchors的坐标如下:

下面这个表格对比了9种尺寸的anchor的变换:

base_anchor ratios (宽,高,中心点横坐标,中心点纵坐标) 坐标
16x16

23x12

(2:1)

[184,96,7.5,7.5] scale=8

[ -84. -40. 99. 55.]

[368,192,7.5,7.5] scale=16

[-176. -88. 191. 103.]

[736,384,7.5,7.5] scale=32

[-360. -184. 375. 199.]

16x16

(1:1)

[128,128,7.5,7.5] scale=8

[ -56. -56. 71. 71.]

[256,256,7.5,7.5] scale=16

[-120. -120. 135. 135.]

[512,512,7.5,7.5] scale=32

[-248. -248. 263. 263.]

11x22

(1:2)

[88,176,7.5,7.5] scale=8 [ -36. -80. 51. 95.]
[176,352,7.5,7.5] scale=16

[ -80. -168. 95. 183.]

[352,704,7.5,7.5] scale=32 [-168. -344. 183. 359.]

2. YOLO 的Anchor Box

YOLO v2,v3的Anchor Box 的大小和形状是通过对训练数据的聚类得到的。 采用标准的k-means方法

官方的 V2,V3的Anchor

1
2
3
anchors = 0.57273, 0.677385, 1.87446, 2.06253, 3.33843, 5.47434, 7.88282, 3.52778, 9.77052, 9.16828 // yolo v2

anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326 // yolo v3

需要注意的是 anchor计算的尺度问题。 yolo v2的是相对最后一个Feature Map (13×13)来的,yolo v3则是相对于原输入图像的416×416的。 这也是在计算目标检测中,边框计算中需要注意的问题,就是计算的边框究竟在相对于那个尺度得出的。

参考: https://blog.csdn.net/sinat_33486980/article/details/81099093