前言:
在RPN中需要生成拥有不同步长(stride)不同大小(size)以及不同长环比(ratio)的anchor, 在maskrcnn_benchmark中,这一工作由anchor_generator.py完成。anchor_generator.py生成所需的不同特征图上的anchor,需要注意的是,如果在backbone中采用了FPN的话,需要保证,stride个数,size个数以及FPN的层数相同。其详细代码为:
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
import math
import numpy as np
import torch
from torch import nn
from maskrcnn_benchmark.structures.bounding_box import BoxList
# todo 把anchors转换成buffer的list
class BufferList(nn.Module):
"""
Similar to nn.ParameterList, but for buffers
"""
def __init__(self, buffers=None):
super(BufferList, self).__init__()
# 如果存在anchor,则把他保存为buffer格式
if buffers is not None:
self.extend(buffers)
def extend(self, buffers):
offset = len(self)
# 循环的把各个大小尺度下不同窗宽比anchor,保存为buffer
for i, buffer in enumerate(buffers):
self.register_buffer(str(offset + i), buffer)
return self
def __len__(self):
return len(self._buffers)
def __iter__(self):
return iter(self._buffers.values())
class AnchorGenerator(nn.Module):
"""
For a set of image sizes and feature maps, computes a set
of anchors
"""
def __init__(
self,
sizes=(128, 256, 512),
aspect_ratios=(0.5, 1.0, 2.0),
anchor_strides=(8, 16, 32),
straddle_thresh=0,
):
super(AnchorGenerator, self).__init__()
# 如果只从一个特征图上提取特征,即不使用rpn
if len(anchor_strides) == 1:
# 获得anchor滑动步长
anchor_stride = anchor_strides[0]
cell_anchors = [
generate_anchors(anchor_stride, sizes, aspect_ratios).float()
]
else:
# 如果anchor滑动步长列表与anchor大小的列表长度不同则报错
if len(anchor_strides) != len(sizes):
raise RuntimeError("FPN should have #anchor_strides == #sizes")
# 循环的得到不同大小尺度不同步长情况下不同长宽比的anchor
cell_anchors = [
generate_anchors(
anchor_stride,
size if isinstance(size, (tuple, list)) else (size,),
aspect_ratios
).float()
for anchor_stride, size in zip(anchor_strides, sizes)
]
self.strides = anchor_strides