from __future__ import print_function
import numpy as np
try:
xrange # Python 2
except NameError:
xrange = range # Python 3
# 注:anchors在這個.py中,表示形式都是x1y1x2y2。wh只是過渡
# 第1個調用函數
def generate_anchors(base_size=16, ratios=[0.5, 1, 2],
scales=2**np.arange(3, 6)):
# base_size=16 代表feature map上一個點對應原圖16×16的區域,經歷了4次pool
# ratios=[0.5,1,2] 代表的是anchors框的長寬比1:2,1:1,2:1
# base_size/根號ratios 即可得出base_size有3種框23:12,16:16,11:22
# scales 代表在base_size的anchor框基礎上需要放大的倍數[8,16,32]
# base_size×scales 即(16*8)*(16*8)=128*128,(16*16)*(16*16)=256*256,(16*32)*(16*32)=512*512,這是原圖上框的尺寸。這麼定義的原因是考慮到在base_size基礎上擴大以覆蓋全圖
"""
Generate anchor (reference) windows by enumerating aspect ratios X
scales wrt a reference (0, 0, 15, 15) window.
"""
base_anchor = np.array([1, 1, base_size, base_size]) - 1
# [0,0,15,15],代表這個區域左上角和右下角座標
ratio_anchors = _ratio_enum(base_anchor, ratios) #參數16,[0.5, 1, 2]
# 返回一個scale下三種ratio的anchor
# ratio_anchors=
#[[ -3.5 2. 18.5 13. ]
# [ 0. 0. 15. 15. ]
# [ 2.5 -3. 12.5 18. ]]
# ratio_anchors.shape[0]=3
anchors = np.vstack(
[ _scale_enum(ratio_anchors[i, :], scales) for i in xrange(ratio_anchors.shape[0])]
) # 豎直方向上疊加
# [[ -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.]]
return anchors
# 第2個調用函數
def _whctrs(anchor): # 把anchor的x1y1x2y2換算成了wh和中心座標
"""
Return width, height, x center, and y center for an anchor (window).
"""
w = anchor[2] - anchor[0] + 1
h = anchor[3] - anchor[1] + 1
x_ctr = anchor[0] + 0.5 * (w - 1)
y_ctr = anchor[1] + 0.5 * (h - 1)
return w, h, x_ctr, y_ctr
# 第3個調用函數
def _ratio_enum(anchor, ratios): # [0,0,15,15],[0.5, 1, 2]
"""
Enumerate a set of anchors for each aspect ratio wrt an anchor.
"""
w, h, x_ctr, y_ctr = _whctrs(anchor)
# _whctrs函數把anchor的x1y1x2y2換算成了wh和中心座標
size = w * h #size:16*16=256
size_ratios = size / ratios #256/ratios[0.5,1,2]=[512,256,128]
# 相當於w/根號ratios
ws = np.round(np.sqrt(size_ratios)) #np.round()四捨五入,np.sqrt()開方ws:[23 16 11]
hs = np.round(ws * ratios) #hs:[12 16 22],ws和hs一一對應。23&12
#給定一組寬高向量,輸出各個預測窗口,也就是將(寬,高,中心點橫座標,中心點縱座標)的形式,轉成
#四個座標值的形式
anchors = _mkanchors(ws, hs, x_ctr, y_ctr)
# 將whx_cy_c變量座標變成一組x1y1x2y2,這一組的w×h是相同的
return anchors #返回到generate_anchors函數
# 第4個調用函數
def _mkanchors(ws, hs, x_ctr, y_ctr):
# ws=[23 16 11] hs=[12 16 22]
"""
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] # np.newaxis相當於None,相當於增加了一維
# ws=[23 16 11] ws=[[23], [16], [11]]
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) ))
# anchors= [[-3.5,2,18.5,13]
# [0,0,15,15]
# [2.5,-3,12.5,18]]
return anchors #x1y1x2y2
# 第5個調用函數,調用重複3次,3次後generate也完成了工作
def _scale_enum(anchor, scales):
"""
Enumerate a set of anchors for each scale wrt an anchor.
"""
# anchor=[ -3.5 2. 18.5 13. ] scales=[8,16,32]
# 每次_scale_enum函數完成的是:給定框寬高比ratio,返回這種比例所有scale的框
w, h, x_ctr, y_ctr = _whctrs(anchor)
ws = w * scales # [ 184. 368. 736.]
hs = h * scales # [ 96. 192. 384.]
anchors = _mkanchors(ws, hs, x_ctr, y_ctr)
# [[ -84. -40. 99. 55.]
# [-176. -88. 191. 103.]
# [-360. -184. 375. 199.]]
return anchors
if __name__ == '__main__':
import time
t = time.time()
a = generate_anchors() # 入口
print(time.time() - t)
print(a)
from IPython import embed; embed()
待補充。。