【目标检测入门】锚框先验框

锚框/先验框

什么是先验框

先验框是提前设定好的一系列检测框(大小和尺寸都是提前定好了的)

为什么要设置先验框?之前目标检测基本概念中介绍了目标检测的一个基本思路:先确立众多候选框,再对候选框进行分类和微调,从而完成目标检测。这就是设置先验框的原因。

设置不同尺度的先验框

为了覆盖更多可能的情况,在图中的同一个位置,会设置几个不同尺度的先验框,这里的不同尺度指大小与长宽比
在这里插入图片描述
显然,设置不同尺度的先验框,出现与目标物体较为匹配(高IoU)的先验框的概率更高

先验框与特征图对应

另外,先验框要设置在图片中不同位置上。

如果遍历原图所有像素,假设一个224x224的图片,每个像素位置设置3个先验框,一共需要设置224x224x3=150528个先验框。如果是遍历原图下采样得到的feature map,则会大大减少先验框的数量。
在这里插入图片描述

先验框类别信息的确定

要给出设置的先验框的类别信息,才能让模型学着去预测每个先验框是否对应着一个目标物体。

对于类别信息的确定,方法是设置一个IoU阈值,与目标框IoU小于阈值的先验框类别设置为背景;大于等于阈值的设置为目标先验框。这样就得到了ground truth的类别信息。
在这里插入图片描述

先验框的生成

VGG16得到的特征图大小为7*7,每个位置设置三种尺度与三种长宽比共9种候选框,以代码为例:

"""
设置细节介绍:
1. 离散程度 fmap_dims = 7: VGG16最后的特征图尺寸为 7*7
2. 在上面的举例中我们是假设了三种尺寸的先验框,然后遍历坐标。在先验框生成过程中,先验框的尺寸是提前设置好的,
   特征图上每一个cell定义了共9种不同大小和形状的候选框(3种尺度*3种长宽比=9)

生成过程:
0. cx, cy表示中心点坐标
1. 遍历特征图上每一个cell,i+0.5是为了从坐标点移动至cell中心,/fmap_dims目的是将坐标在特征图上归一化
2. 这个时候我们已经可以在每个cell上各生成一个框了,但是这个不是我们需要的,我们称之为base_prior_bbox基准框。
3. 根据我们在每个cell上得到的长宽比1:1的基准框,结合我们设置的3种尺度obj_scales和3种长宽比aspect_ratios就得到了每个cell的9个先验框。
4. 最终结果保存在prior_boxes中并返回。

需要注意的是,这个时候我们的到的先验框是针对特征图的尺寸并归一化的,因此要映射到原图计算IOU或者展示,需要:
img_prior_boxes = prior_boxes * 图像尺寸
"""

def create_prior_boxes():
        """
        VGG16最后的特征图尺寸为 7*7
        特征图上每一个cell定义了共9种不同大小和形状的候选框(3种尺度*3种长宽比=9)
        因此总的候选框个数 = 7 * 7 * 9 = 441
        :return: prior boxes in center-size coordinates, a tensor of dimensions (441, 4)
        """
        fmap_dims = 7 
        obj_scales = [0.2, 0.4, 0.6] 
        aspect_ratios = [1., 2., 0.5] 

        prior_boxes = []
        for i in range(fmap_dims):
            for j in range(fmap_dims):
                cx = (j + 0.5) / fmap_dims  # 归一化cell中心点x坐标
                cy = (i + 0.5) / fmap_dims # 归一化cell中心点y坐标

                for obj_scale in obj_scales:
                    for ratio in aspect_ratios:
                        prior_boxes.append([cx, cy, obj_scale * sqrt(ratio), obj_scale / sqrt(ratio)]) #直接用sqrt(),这里假设原图宽高相同

        prior_boxes = torch.FloatTensor(prior_boxes).to(device)  # (441, 4)
        prior_boxes.clamp_(0, 1)  # (441, 4)

        return prior_boxes

进行可视化:

1.obj_scales = [0.1,0.2,0.3]
在这里插入图片描述
2.obj_scales = [0.2,0.4,0.6]
在这里插入图片描述
先验框超出图片界限时,一般用图片尺寸将越界的先验框进行截断,比如某个先验框左上角坐标是(-5, -9),那么就截断为(0,0),某个先验框右下角坐标是(324,134),当图片大小为(224,224)时,就将其截断为(224,134)。

prior_boxes.clamp_(0, 1)

上面这一行在代码中就实现了截断的功能(进行了归一化,使用0-1截断)

参考

动手学CV-Pytorch

猜你喜欢

转载自blog.csdn.net/i0o0iW/article/details/111409885