相关函数
1、torch.clamp()
torch.clamp(input, min, max, out=None) --> Tensor
将输入input Tensor中每个元素约束到【min,max】,返回一个截断后的new Tensor
例子:
input = torch.Tensor([2,1,0.5,-0.5])
output = torch.clamp(input,0,1)
print(output)
'''
output
Out[16]: tensor([1.000, 1.000, 0.500, 0.000])
'''
2、itertools.product( )
product(*iterables,repeat=1) --> product object
iterable是可迭代对象,repeat指定iterable重复几次,即product(A,repeat=3)等价于product(A,A,A)
该函数用于求输入迭代对象的笛卡尔集,相当于一个前天的for循环。product返回的是一个迭代器。
import itertools.product as product
list1=['a','b']
list2=['c','d']
for item in product(list1,list2):
print(item)
'''
...
('a','c')
('a','d')
('b','c')
('b','d')
'''
list1 = [1,2,3,4]
for item in product(list1,repeat=2):
print(item)
'''
用于生成笛卡尔坐标
(1,1)
(1,2)
(1,3)
(1,4)
...
(4,1)
(4,2)
(4,3)
(4,4)
'''
相关参数
# RefineDet CONFIGS
voc_refinedet = {
'320': {
'num_classes': 21,
'lr_steps': (80000, 100000, 120000),
'max_iter': 120000,
'feature_maps': [40, 20, 10, 5],
'min_dim': 320,
'steps': [8, 16, 32, 64],
'min_sizes': [32, 64, 128, 256],
'max_sizes': [],
'aspect_ratios': [[2], [2], [2], [2]],
'variance': [0.1, 0.2],
'clip': True,
'name': 'RefineDet_VOC_320',
},
'512': {
'num_classes': 21,
'lr_steps': (80000, 100000, 120000),
'max_iter': 120000,
'feature_maps': [64, 32, 16, 8],
'min_dim': 512,
'steps': [8, 16, 32, 64],
'min_sizes': [32, 64, 128, 256],
'max_sizes': [],
'aspect_ratios': [[2], [2], [2], [2]],
'variance': [0.1, 0.2],
'clip': True,
'name': 'RefineDet_VOC_320',
}
}
num_class为当前的数据集类别数+背景(voc为20+1)
feature_maps为FPN的特征图大小
steps特征图相对于输入图像的下采样率,用于计算当前特征图上某一位置处所有默认框中心坐标在输入图像的坐标
min_sizes&max_size为当前特征层的默认尺寸,个人感觉这里直接写出来的意思是表示该层的anchor大小在这两个值之间。
aspect_ratios anchor的长宽比
代码解读
class PriorBox(object):
"""Compute priorbox coordinates in center-offset form for each source
feature map.
"""
def __init__(self, cfg):
super(PriorBox, self).__init__()
self.image_size = cfg['min_dim']
# number of priors for feature map location (either 4 or 6)
self.num_priors = len(cfg['aspect_ratios'])
self.variance = cfg['variance'] or [0.1] # [0.1, 0.2]
self.feature_maps = cfg['feature_maps'] #[64, 32, 16, 8]
self.min_sizes = cfg['min_sizes'] #[32, 64, 128, 256]
self.max_sizes = cfg['max_sizes'] #[]
self.steps = cfg['steps'] #[8, 16, 32, 64]
self.aspect_ratios = cfg['aspect_ratios'] #[[2],[2],[2],[2]]
self.clip = cfg['clip'] # True
self.version = cfg['name'] # RefineDet_VOC_512
for v in self.variance:
if v <= 0:
raise ValueError('Variances must be greater than 0')
def forward(self):
mean = []
for k, f in enumerate(self.feature_maps): #遍历4个特征图,每个特征图分别生成anchor
for i, j in product(range(f), repeat=2):#针对每个特征图遍历所有坐标
'''
将特征图的坐标对应回原图坐标,然后缩放到0~1的相对距离
原始公式应该为cx = (j+0.5)* step /min_dim,这里拆成两步计算
'''
f_k = self.image_size / self.steps[k]
# unit center x,y
cx = (j + 0.5) / f_k
cy = (i + 0.5) / f_k
# aspect_ratio: 1
# rel size: min_size
s_k = self.min_sizes[k]/self.image_size
mean += [cx, cy, s_k, s_k]
# aspect_ratio: 1
# rel size: sqrt(s_k * s_(k+1))
if self.max_sizes:
s_k_prime = sqrt(s_k * (self.max_sizes[k]/self.image_size))
mean += [cx, cy, s_k_prime, s_k_prime]
# rest of aspect ratios
for ar in self.aspect_ratios[k]:
mean += [cx, cy, s_k*sqrt(ar), s_k/sqrt(ar)]
mean += [cx, cy, s_k/sqrt(ar), s_k*sqrt(ar)]
# back to torch land将产生的anchor转化成n行4列的标准格式
output = torch.Tensor(mean).view(-1, 4)
if self.clip:
output.clamp_(max=1, min=0)
return output