本文就faster rcnn中anchors的函数generate_anchors.py为例,介绍anchors的生成过程。
首先看下主函数入口。论文中提到anchor两个参数:ratios和scales,长宽比和尺度变换都需要有个基础anchor的大小,也就是base_size的由来,至于16的由来,则等于网络的输入大小 / 特征图大小(生成anchor的feature map层)
def generate_anchors(base_size=16, ratios=[0.5, 1, 2],
scales=2**np.arange(3, 6))这样," base_anchor = np.array([1, 1, base_size, base_size]) - 1 "就表示基础anchor的大小了。
其次,看下如何生成长宽比不同的anchors。这里是对anchor的宽高都进行了改变,具体是将宽变为,高变为
,这样长宽比就变为ratios了。此时生成3个长宽比不同的anchors。
def _ratio_enum(anchor, ratios):
"""
Enumerate a set of anchors for each aspect ratio wrt an anchor.
"""
w, h, x_ctr, y_ctr = _whctrs(anchor) #基础anchor(0, 0, 15, 15)的宽高中心点坐标
size = w * h #anchor面积
size_ratios = size / ratios #面积比例w**2/ratios
ws = np.round(np.sqrt(size_ratios)) #对宽度进行变换,得到w/sqrt(ratios)
hs = np.round(ws * ratios) #由于ws=w/sqrt(ratios), 所以hs=w*sqrt(ratios)
anchors = _mkanchors(ws, hs, x_ctr, y_ctr)
return anchors再者,看下如何生成尺度不同的anchors,将anchor的宽和高分别进行尺度变换即可。
def _scale_enum(anchor, scales):
"""
Enumerate a set of anchors for each scale wrt an anchor.
"""
w, h, x_ctr, y_ctr = _whctrs(anchor)
ws = w * scales #对anchor的宽进行尺度变换
hs = h * scales #对anchor的高进行尺度变换
anchors = _mkanchors(ws, hs, x_ctr, y_ctr)
return anchors最后就是两个函数的理解了,np.hstack和np.vstack,可以通过_mkanchors函数理解前者,得到3行4列的anchors,然后利用np.vstack函数再得到9行4列的元素。
def _mkanchors(ws, hs, x_ctr, y_ctr):
"""
Given a vector of widths (ws) and heights (hs) around a center
(x_ctr, y_ctr), output a set of anchors (windows).
"""
ws = ws[:, np.newaxis] #增加新的维度,由(3, )变为(3, 1)
hs = hs[:, np.newaxis]
anchors = np.hstack((x_ctr - 0.5 * (ws - 1),
y_ctr - 0.5 * (hs - 1),
x_ctr + 0.5 * (ws - 1),
y_ctr + 0.5 * (hs - 1))) #依次堆叠ws和hs水平方向上对应元素生成的值
return anchors这样最终得到一个点上生成的anchor,对应论文图3中的k anchor boxes.

整个计算流程如下:
>>> base_size=16
>>> ratios=[0.5, 1, 2]
>>> scales=2**np.arange(3, 6)
>>> base_anchor = np.array([1, 1, base_size, base_size]) - 1
>>> ratio_anchors = _ratio_enum(base_anchor, ratios)
>>> scale_anchors_0 =_scale_enum(ratio_anchors[0, :], scales)
>>> ratio_anchors.shape
(3, 4)
>>> scale_anchors_0.shape
(3, 4)
>>> ratio_anchors
array([[-3.5, 2. , 18.5, 13. ],
[ 0. , 0. , 15. , 15. ],
[ 2.5, -3. , 12.5, 18. ]])
>>> scale_anchors_0
array([[ -84., -40., 99., 55.],
[-176., -88., 191., 103.],
[-360., -184., 375., 199.]])
>>> anchors = np.vstack([_scale_enum(ratio_anchors[i, :], scales) for i in xrange(ratio_anchors.shape[0])])
>>> anchors.shape
(9, 4)
>>> anchors
array([[ -84., -40., 99., 55.],
[-176., -88., 191., 103.],
[-360., -184., 375., 199.],
[ -56., -56., 71., 71.],
[-120., -120., 135., 135.],
[-248., -248., 263., 263.],
[ -36., -80., 51., 95.],
[ -80., -168., 95., 183.],
[-168., -344., 183., 359.]])参考文献:
版权声明:本文为hzhj2007原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。