single_level.py 3.94 KB
Newer Older
Kai Chen's avatar
Kai Chen committed
1
2
3
4
5
6
from __future__ import division

import torch
import torch.nn as nn

from mmdet import ops
7
from mmdet.core import bbox_assign, bbox_sampling
Kai Chen's avatar
Kai Chen committed
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54


class SingleLevelRoI(nn.Module):
    """Extract RoI features from a single level feature map. Each RoI is
    mapped to a level according to its scale."""

    def __init__(self,
                 roi_layer,
                 out_channels,
                 featmap_strides,
                 finest_scale=56):
        super(SingleLevelRoI, self).__init__()
        self.roi_layers = self.build_roi_layers(roi_layer, featmap_strides)
        self.out_channels = out_channels
        self.featmap_strides = featmap_strides
        self.finest_scale = finest_scale

    @property
    def num_inputs(self):
        return len(self.featmap_strides)

    def init_weights(self):
        pass

    def build_roi_layers(self, layer_cfg, featmap_strides):
        cfg = layer_cfg.copy()
        layer_type = cfg.pop('type')
        assert hasattr(ops, layer_type)
        layer_cls = getattr(ops, layer_type)
        roi_layers = nn.ModuleList(
            [layer_cls(spatial_scale=1 / s, **cfg) for s in featmap_strides])
        return roi_layers

    def map_roi_levels(self, rois, num_levels):
        """Map rois to corresponding feature levels (0-based) by scales.

        scale < finest_scale: level 0
        finest_scale <= scale < finest_scale * 2: level 1
        finest_scale * 2 <= scale < finest_scale * 4: level 2
        scale >= finest_scale * 4: level 3
        """
        scale = torch.sqrt(
            (rois[:, 3] - rois[:, 1] + 1) * (rois[:, 4] - rois[:, 2] + 1))
        target_lvls = torch.floor(torch.log2(scale / self.finest_scale + 1e-6))
        target_lvls = target_lvls.clamp(min=0, max=num_levels - 1).long()
        return target_lvls

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
    def sample_proposals(self, proposals, gt_bboxes, gt_crowds, gt_labels,
                         cfg):
        proposals = proposals[:, :4]
        assigned_gt_inds, assigned_labels, argmax_overlaps, max_overlaps = \
            bbox_assign(proposals, gt_bboxes, gt_crowds, gt_labels,
            cfg.pos_iou_thr, cfg.neg_iou_thr, cfg.pos_iou_thr, cfg.crowd_thr)

        if cfg.add_gt_as_proposals:
            proposals = torch.cat([gt_bboxes, proposals], dim=0)
            gt_assign_self = torch.arange(
                1,
                len(gt_labels) + 1,
                dtype=torch.long,
                device=proposals.device)
            assigned_gt_inds = torch.cat([gt_assign_self, assigned_gt_inds])
            assigned_labels = torch.cat([gt_labels, assigned_labels])

        pos_inds, neg_inds = bbox_sampling(
            assigned_gt_inds, cfg.roi_batch_size, cfg.pos_fraction,
            cfg.neg_pos_ub, cfg.pos_balance_sampling, max_overlaps,
            cfg.neg_balance_thr)

        pos_proposals = proposals[pos_inds]
        neg_proposals = proposals[neg_inds]
        pos_assigned_gt_inds = assigned_gt_inds[pos_inds] - 1
        pos_gt_bboxes = gt_bboxes[pos_assigned_gt_inds, :]
        pos_gt_labels = assigned_labels[pos_inds]

        return (pos_proposals, neg_proposals, pos_assigned_gt_inds, pos_gt_bboxes, pos_gt_labels)

Kai Chen's avatar
Kai Chen committed
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
    def forward(self, feats, rois):
        """Extract roi features with the roi layer. If multiple feature levels
        are used, then rois are mapped to corresponding levels according to
        their scales.
        """
        if len(feats) == 1:
            return self.roi_layers[0](feats[0], rois)

        out_size = self.roi_layers[0].out_size
        num_levels = len(feats)
        target_lvls = self.map_roi_levels(rois, num_levels)
        roi_feats = torch.cuda.FloatTensor(rois.size()[0], self.out_channels,
                                           out_size, out_size).fill_(0)
        for i in range(num_levels):
            inds = target_lvls == i
            if inds.any():
                rois_ = rois[inds, :]
                roi_feats_t = self.roi_layers[i](feats[i], rois_)
                roi_feats[inds] += roi_feats_t
        return roi_feats