anchor_size, aspect_ratio, anchors以及torchvision 中 AnchorGenerator 解读

文章介绍了AnchorGenerator在目标检测算法中的功能,它是用于生成不同大小的anchors,以适应多尺寸目标。AnchorGenerator的初始化需要指定基础大小和宽高比,通过forward函数结合特征图和步长计算出原图上的anchor点。测试部分展示了如何在图像上生成anchors。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基本释义

在一些目标检测的算法中,常常会看到关于如何生成 anchors 的描述,涉及到多尺寸目标检测的时候,就需要有不同大小的anchors作为proposal。

他们之间的关系是
在这里插入图片描述

转换后的 width_b, height_b 满足以下关系
w i d t h _ b / h e i g h t _ b = w i d t h / h e i g h t ∗ a s p e c t _ r a t i o width\_b/height\_b = width/height * aspect\_ratio width_b/height_b=width/heightaspect_ratio

AnchorGenerator

torchvision.models.detection.anchor_utils.py
这个模块的主要功能(调用forward函数)最终生成的结果是在原图基础上,给定feature_map 表达的采样倍数下,在原图尺寸生成的 anchors.这里要注意的就是 feature_map 只是一个倍数参考。
比如原图为 (800, 800), 给定feature_map的H/W 为 25/25, 则说明采样比例为 800/25 = 32.
那么 anchors 的中心点的 x/y 坐标值就会分布在(0, 32, 64, …)

首先来看 AnchorGenerator 类的基本结构
在这里插入图片描述

初始化

输入参数:

  • sizes 最后生成的 anchors 的大小基础
  • aspect_ratios: 参考上面的释义,指的就是 宽度/高度 的比值
def __init__(
        self,
        sizes=((128, 256, 512),),
        aspect_ratios=((0.5, 1.0, 2.0),),
    ):
        super(AnchorGenerator, self).__init__()

        if not isinstance(sizes[0], (list, tuple)):
            # TODO change this
            sizes = tuple((s,) for s in sizes)
        if not isinstance(aspect_ratios[0], (list, tuple)):
            aspect_ratios = (aspect_ratios,) * len(sizes)

        assert len(sizes) == len(aspect_ratios)

        self.sizes = sizes
        self.aspect_ratios = aspect_ratios
        self.cell_anchors = [self.generate_anchors(size, aspect_ratio)
                             for size, aspect_ratio in zip(sizes, aspect_ratios)]

generate_anchors

功能是生成 zero_centered 的所有 anchor.
相当于以 (0,0) 为anchor 中心生成对应的anchor.

def generate_anchors(self, scales: List[int], aspect_ratios: List[float], dtype: torch.dtype = torch.float32,
                         device: torch.device = torch.device("cpu")):
        scales = torch.as_tensor(scales, dtype=dtype, device=device)
        aspect_ratios = torch.as_tensor(aspect_ratios, dtype=dtype, device=device)
        h_ratios = torch.sqrt(aspect_ratios)
        w_ratios = 1 / h_ratios

        ws = (w_ratios[:, None] * scales[None, :]).view(-1)
        hs = (h_ratios[:, None] * scales[None, :]).view(-1)

        base_anchors = torch.stack([-ws, -hs, ws, hs], dim=1) / 2
        return base_anchors.round()

grid_anchors

功能是对每个需要生成 anchor 的中心点生成 anchor, 可以理解为将上面 generate_anchors 得到的anchors 放到每个点上。

# torchvision.models.detection.anchor_utils.py  --> AnchorGenerator   --> grid_anchors
# For every (base anchor, output anchor) pair,
# offset each zero-centered base anchor by the center of the output anchor.
anchors.append(
    (shifts.view(-1, 1, 4) + base_anchors.view(1, -1, 4)).reshape(-1, 4)
)

forward

给定 image,和对应的 feature_map, 计算需要生成anchors 的点。

grid_sizes 为 feature_map 的 H, W.
stride 为 image 和 feature_map H,W 的倍数
grid_sizes 中的每个点和 stride相乘就得到了原image中需要生成anchors的点。

def forward(self, image_list: ImageList, feature_maps: List[Tensor]) -> List[Tensor]:
    grid_sizes = [feature_map.shape[-2:] for feature_map in feature_maps]
    image_size = image_list.tensors.shape[-2:]
    ...
    strides = [[torch.tensor(image_size[0] // g[0], dtype=torch.int64, device=device),
                torch.tensor(image_size[1] // g[1], dtype=torch.int64, device=device)] for g in grid_sizes]
  	...
    anchors_over_all_feature_maps = self.grid_anchors(grid_sizes, strides)
  
    return anchors

测试 AnchorGenerator 的调用

import numpy as np
import torch
from torchvision.models.detection.anchor_utils import AnchorGenerator
from torchvision.models.detection.image_list import ImageList

if __name__ == "__main__":
    # 对一幅图上的每一个点,生成我任意想要生成的 anchors.
    
    ## 读取现有的图像
    img = np.load("/root/autodl-tmp/datasets/pannuke/hvi_format/test_sample/0.npy") # 
    # print(img)
    image = np.transpose(img[..., :3], (2, 0, 1))/255
    image = torch.tensor(image, dtype=torch.float32)
    image_sizes = image.shape[-2:]

    im = ImageList(image, image_sizes)
    feature_maps = list(torch.rand(1, 1280, 25, 25))

    anchor_gen = AnchorGenerator()
    anchor_gen(im, feature_maps)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RessCris

老铁门多支持!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值