clw5180 / remote_sensing_object_detection_2019

2019年遥感图像稀疏表征与智能分析竞赛-初赛排名26/605
MIT License
63 stars 24 forks source link

我个人有个比较困惑的地方,关于anchor_size,希望有朋友可以解答一下 #3

Open clw5180 opened 5 years ago

clw5180 commented 5 years ago

对于FPN版本,作者推荐的anchor size为[2, 4, 8, 16, 32],和maskrcnn_benchmark默认的anchor size [32, 64, 128, 256, 512]差别较大,我看了一下生成anchor部分的代码还是有一定区别:

原始RPN:

def generate_anchors(
    stride=16, sizes=(32, 64, 128, 256, 512), aspect_ratios=(0.5, 1, 2)
):
    """Generates a matrix of anchor boxes in (x1, y1, x2, y2) format. Anchors
    are centered on stride / 2, have (approximate) sqrt areas of the specified
    sizes, and aspect ratios as given.
    """
    return _generate_anchors(
        stride,
        np.array(sizes, dtype=np.float) / stride,
        np.array(aspect_ratios, dtype=np.float),
    )

而对于RRPN,这里sizes少除了一个stride:

def generate_anchors(
    stride=16, sizes=(8, 16, 32), aspect_ratios=(0.5, 1, 2), angle=(-30.0, 0.0, 30.0, 60.0, 90.0, 120.0)
):
    """Generates a matrix of anchor boxes in (x, y, w, h, theta) format. Anchors
    are centered on stride / 2, have (approximate) sqrt areas of the specified
    sizes, and aspect ratios as given.
    """
    return generate_Ranchors(
        stride,
        aspect_ratios,
        sizes,
        angle
    )

而在函数内部, 对于RPN:

def _generate_anchors(base_size, scales, aspect_ratios):
    """Generate anchor (reference) windows by enumerating aspect ratios X
    scales wrt a reference (0, 0, base_size - 1, base_size - 1) window.
    """
    anchor = np.array([1, 1, base_size, base_size], dtype=np.float) - 1
    anchors = _ratio_enum(anchor, aspect_ratios)
    anchors = np.vstack(
        [_scale_enum(anchors[i, :], scales) for i in range(anchors.shape[0])]
    )
    return torch.from_numpy(anchors)

RRPN:

def generate_Ranchors(base_size=16, ratios=[0.2, 0.5, 1.0],
                     scales=2 ** np.arange(3, 6), angle=[-30.0, 0.0, 30.0, 60.0, 90.0, 120.0]):
    ######################################
    # Parameter:
    ######################################
    # ratio: [0.5, 1, 2]
    # scales: 2^3, 2^4, 2^5
    # angle: [-45, 0, 45]
    ######################################
    # (project in original patch)
    ######################################

    # [x_ctr, y_ctr, height, width, theta] anti-clock-wise angle

    base_anchor = np.array([base_size / 2 - 1, base_size / 2 - 1, base_size, base_size, 0], dtype=np.float32)
    ratio_anchors = _ratio_enum(base_anchor, ratios)
    scale_anchors = np.vstack([_scale_enum(ratio_anchors[i, :], scales) for i in range(ratio_anchors.shape[0])])
    anchors = np.vstack([_angle_enum(scale_anchors[i, :], angle) for i in range(scale_anchors.shape[0])])

    # discard
    # anchors[:, 2:4] = anchors[:, 3:1:-1]

    return torch.from_numpy(anchors)

对于RPN的写法,generate_anchors相当于传入的是size / stride,即[8, 8, 8, 8, 8],即每个feature map上的size,如果换算到原图就要乘以各自层的stride,得到[32, 64, 128, 256, 512] 而对于RRPN这种写法,generate_anchors相当于传入的是size本身,即[2, 4, 8, 16, 32],换算到原图的实际anchor_size应该也要乘一个stride,变成[8, 32, 128, 512, 2048]。不知这样理解是否正确?

wnynotfaker commented 4 years ago

你好,我也发现了这个问题,跟您想的差不多。我对代码进行了修改,使得每个特征图上对应一个尺度的anchor,即RPN的写法

tiny-cold-hands commented 4 years ago

你好,我也发现了这个问题,跟您想的差不多。我对代码进行了修改,使得每个特征图上对应一个尺度的anchor,即RPN的写法

你好,请问是将倒数第二行改为size/stride吗?配置文件的anchor参数如何设置呢? def generate_anchors( stride=16, sizes=(8, 16, 32), aspect_ratios=(0.5, 1, 2), angle=(-30.0, 0.0, 30.0, 60.0, 90.0, 120.0) ): """Generates a matrix of anchor boxes in (x, y, w, h, theta) format. Anchors are centered on stride / 2, have (approximate) sqrt areas of the specified sizes, and aspect ratios as given. """ return generate_Ranchors( stride, aspect_ratios, sizes, angle )