pytorch SSD 源码阅读:PriorBox

PriorBox是根据特征图大小与其所对应的宽高比例计算的四个数(cx, cy, sw, sh),也就是( 中心点坐标x, 中心点中标y, 宽, 高 ),其在训练过程中,一旦设置好了每个特征图的比例,就不会再动了,所以PriorBoxs再网络(ssd)初始化时就已经计算完成。PriorBox的作用是与ground truth相比较,找到overlap大于阈值的框,然后计算这些框预测的4个值与 ground truthsmooth_l1_loss ,计算置信度loss同理。

voc = {
    'num_classes': 21,
    'lr_steps': (80000, 100000, 120000),
    'max_iter': 120000,
    'feature_maps': [38, 19, 10, 5, 3, 1],
    'min_dim': 300,
    'steps': [8, 16, 32, 64, 100, 300],
    'min_sizes': [30, 60, 111, 162, 213, 264],
    'max_sizes': [60, 111, 162, 213, 264, 315],
    'aspect_ratios': [[2], [2, 3], [2, 3], [2, 3], [2], [2]],
    'variance': [0.1, 0.2],
    'clip': True,
    'name': 'VOC',
}

feature_maps : 特征图大小,用来遍历生成每一个点的坐标并加上0.5作为先验框的坐标中心。
min_dim:图片大小
steps :代码中用于将先验框中心坐标归一化,除以图片大小,使得求出来的大小与image_size有关,与feature_map_size无关
min_sizes:用于计算每一个先验框的长与宽,self.min_sizes[k]/self.image_size。与论文中的默认框(先验框)的宽高与图片大小的比例有关,如下公式:

论文中smin = 0.2 , smax = 0.9 但是m = 5,也就是说第一个特征图的先验框是单独设置的为0.1,其乘以300 等于30。
max_sizes: 是为了对应一个特例,1′ 的宽与高比例的大小,如下公式:

aspect_ratios:代码中已经显示的定义了[1, 1']大小的默认框,还差[2, 3, 1/2, 1/3] 宽高比的定义。针对6个特征图[38, 19 ,10 ,5 ,3 , 1],在实际上并不是每一个特征图的每个点都用了6个比例的框,而是[4, 6, 6, 6, 4, 4]。
clip :output.clamp_(max=1, min=0) , 把小于0 和大于1 的值分别置为0,和1

from __future__ import division
from math import sqrt as sqrt
from itertools import product as product
import torch


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]
        self.feature_maps = cfg['feature_maps']
        self.min_sizes = cfg['min_sizes']
        self.max_sizes = cfg['max_sizes']
        self.steps = cfg['steps']
        self.aspect_ratios = cfg['aspect_ratios']
        self.clip = cfg['clip']
        self.version = cfg['name']
        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):
            for i, j in product(range(f), repeat=2):
                f_k = self.image_size / self.steps[k]  # f_k : 比例
                # unit center x,y
                cx = (j + 0.5) / f_k  # 求出来的大小与image_size有关,与feature_map_size无关
                cy = (i + 0.5) / f_k

                # aspect_ratio: 1
                # rel size: min_size
                s_k = self.min_sizes[k]/self.image_size  # 求出来的大小与image_size有关,与feature_map_size无关
                mean += [cx, cy, s_k, s_k]

                # aspect_ratio: 1
                # rel size: sqrt(s_k * s_(k+1))
                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
        output = torch.Tensor(mean).view(-1, 4)
        if self.clip:
            output.clamp_(max=1, min=0)
        return output




除非注明,否则均为一叶呼呼原创文章,转载必须以链接形式标明本文链接

本文链接:https://www.yiyehu.tech/archives/2020/04/01/ssd-sourcecode-priorbox