Spaces:
Runtime error
Runtime error
# Copyright (c) OpenMMLab. All rights reserved. | |
import warnings | |
import numpy as np | |
import torch | |
import torch.nn as nn | |
from mmcv.cnn import ConvModule | |
from mmcv.runner import force_fp32 | |
from mmdet.core import (build_assigner, build_bbox_coder, | |
build_prior_generator, build_sampler, images_to_levels, | |
multi_apply, unmap) | |
from mmdet.core.utils import filter_scores_and_topk | |
from ..builder import HEADS, build_loss | |
from .base_dense_head import BaseDenseHead | |
from .dense_test_mixins import BBoxTestMixin | |
from .guided_anchor_head import GuidedAnchorHead | |
class SABLRetinaHead(BaseDenseHead, BBoxTestMixin): | |
"""Side-Aware Boundary Localization (SABL) for RetinaNet. | |
The anchor generation, assigning and sampling in SABLRetinaHead | |
are the same as GuidedAnchorHead for guided anchoring. | |
Please refer to https://arxiv.org/abs/1912.04260 for more details. | |
Args: | |
num_classes (int): Number of classes. | |
in_channels (int): Number of channels in the input feature map. | |
stacked_convs (int): Number of Convs for classification \ | |
and regression branches. Defaults to 4. | |
feat_channels (int): Number of hidden channels. \ | |
Defaults to 256. | |
approx_anchor_generator (dict): Config dict for approx generator. | |
square_anchor_generator (dict): Config dict for square generator. | |
conv_cfg (dict): Config dict for ConvModule. Defaults to None. | |
norm_cfg (dict): Config dict for Norm Layer. Defaults to None. | |
bbox_coder (dict): Config dict for bbox coder. | |
reg_decoded_bbox (bool): If true, the regression loss would be | |
applied directly on decoded bounding boxes, converting both | |
the predicted boxes and regression targets to absolute | |
coordinates format. Default False. It should be `True` when | |
using `IoULoss`, `GIoULoss`, or `DIoULoss` in the bbox head. | |
train_cfg (dict): Training config of SABLRetinaHead. | |
test_cfg (dict): Testing config of SABLRetinaHead. | |
loss_cls (dict): Config of classification loss. | |
loss_bbox_cls (dict): Config of classification loss for bbox branch. | |
loss_bbox_reg (dict): Config of regression loss for bbox branch. | |
init_cfg (dict or list[dict], optional): Initialization config dict. | |
""" | |
def __init__(self, | |
num_classes, | |
in_channels, | |
stacked_convs=4, | |
feat_channels=256, | |
approx_anchor_generator=dict( | |
type='AnchorGenerator', | |
octave_base_scale=4, | |
scales_per_octave=3, | |
ratios=[0.5, 1.0, 2.0], | |
strides=[8, 16, 32, 64, 128]), | |
square_anchor_generator=dict( | |
type='AnchorGenerator', | |
ratios=[1.0], | |
scales=[4], | |
strides=[8, 16, 32, 64, 128]), | |
conv_cfg=None, | |
norm_cfg=None, | |
bbox_coder=dict( | |
type='BucketingBBoxCoder', | |
num_buckets=14, | |
scale_factor=3.0), | |
reg_decoded_bbox=False, | |
train_cfg=None, | |
test_cfg=None, | |
loss_cls=dict( | |
type='FocalLoss', | |
use_sigmoid=True, | |
gamma=2.0, | |
alpha=0.25, | |
loss_weight=1.0), | |
loss_bbox_cls=dict( | |
type='CrossEntropyLoss', | |
use_sigmoid=True, | |
loss_weight=1.5), | |
loss_bbox_reg=dict( | |
type='SmoothL1Loss', beta=1.0 / 9.0, loss_weight=1.5), | |
init_cfg=dict( | |
type='Normal', | |
layer='Conv2d', | |
std=0.01, | |
override=dict( | |
type='Normal', | |
name='retina_cls', | |
std=0.01, | |
bias_prob=0.01))): | |
super(SABLRetinaHead, self).__init__(init_cfg) | |
self.in_channels = in_channels | |
self.num_classes = num_classes | |
self.feat_channels = feat_channels | |
self.num_buckets = bbox_coder['num_buckets'] | |
self.side_num = int(np.ceil(self.num_buckets / 2)) | |
assert (approx_anchor_generator['octave_base_scale'] == | |
square_anchor_generator['scales'][0]) | |
assert (approx_anchor_generator['strides'] == | |
square_anchor_generator['strides']) | |
self.approx_anchor_generator = build_prior_generator( | |
approx_anchor_generator) | |
self.square_anchor_generator = build_prior_generator( | |
square_anchor_generator) | |
self.approxs_per_octave = ( | |
self.approx_anchor_generator.num_base_priors[0]) | |
# one anchor per location | |
self.num_base_priors = self.square_anchor_generator.num_base_priors[0] | |
self.stacked_convs = stacked_convs | |
self.conv_cfg = conv_cfg | |
self.norm_cfg = norm_cfg | |
self.reg_decoded_bbox = reg_decoded_bbox | |
self.use_sigmoid_cls = loss_cls.get('use_sigmoid', False) | |
self.sampling = loss_cls['type'] not in [ | |
'FocalLoss', 'GHMC', 'QualityFocalLoss' | |
] | |
if self.use_sigmoid_cls: | |
self.cls_out_channels = num_classes | |
else: | |
self.cls_out_channels = num_classes + 1 | |
self.bbox_coder = build_bbox_coder(bbox_coder) | |
self.loss_cls = build_loss(loss_cls) | |
self.loss_bbox_cls = build_loss(loss_bbox_cls) | |
self.loss_bbox_reg = build_loss(loss_bbox_reg) | |
self.train_cfg = train_cfg | |
self.test_cfg = test_cfg | |
if self.train_cfg: | |
self.assigner = build_assigner(self.train_cfg.assigner) | |
# use PseudoSampler when sampling is False | |
if self.sampling and hasattr(self.train_cfg, 'sampler'): | |
sampler_cfg = self.train_cfg.sampler | |
else: | |
sampler_cfg = dict(type='PseudoSampler') | |
self.sampler = build_sampler(sampler_cfg, context=self) | |
self.fp16_enabled = False | |
self._init_layers() | |
def num_anchors(self): | |
warnings.warn('DeprecationWarning: `num_anchors` is deprecated, ' | |
'please use "num_base_priors" instead') | |
return self.square_anchor_generator.num_base_priors[0] | |
def _init_layers(self): | |
self.relu = nn.ReLU(inplace=True) | |
self.cls_convs = nn.ModuleList() | |
self.reg_convs = nn.ModuleList() | |
for i in range(self.stacked_convs): | |
chn = self.in_channels if i == 0 else self.feat_channels | |
self.cls_convs.append( | |
ConvModule( | |
chn, | |
self.feat_channels, | |
3, | |
stride=1, | |
padding=1, | |
conv_cfg=self.conv_cfg, | |
norm_cfg=self.norm_cfg)) | |
self.reg_convs.append( | |
ConvModule( | |
chn, | |
self.feat_channels, | |
3, | |
stride=1, | |
padding=1, | |
conv_cfg=self.conv_cfg, | |
norm_cfg=self.norm_cfg)) | |
self.retina_cls = nn.Conv2d( | |
self.feat_channels, self.cls_out_channels, 3, padding=1) | |
self.retina_bbox_reg = nn.Conv2d( | |
self.feat_channels, self.side_num * 4, 3, padding=1) | |
self.retina_bbox_cls = nn.Conv2d( | |
self.feat_channels, self.side_num * 4, 3, padding=1) | |
def forward_single(self, x): | |
cls_feat = x | |
reg_feat = x | |
for cls_conv in self.cls_convs: | |
cls_feat = cls_conv(cls_feat) | |
for reg_conv in self.reg_convs: | |
reg_feat = reg_conv(reg_feat) | |
cls_score = self.retina_cls(cls_feat) | |
bbox_cls_pred = self.retina_bbox_cls(reg_feat) | |
bbox_reg_pred = self.retina_bbox_reg(reg_feat) | |
bbox_pred = (bbox_cls_pred, bbox_reg_pred) | |
return cls_score, bbox_pred | |
def forward(self, feats): | |
return multi_apply(self.forward_single, feats) | |
def get_anchors(self, featmap_sizes, img_metas, device='cuda'): | |
"""Get squares according to feature map sizes and guided anchors. | |
Args: | |
featmap_sizes (list[tuple]): Multi-level feature map sizes. | |
img_metas (list[dict]): Image meta info. | |
device (torch.device | str): device for returned tensors | |
Returns: | |
tuple: square approxs of each image | |
""" | |
num_imgs = len(img_metas) | |
# since feature map sizes of all images are the same, we only compute | |
# squares for one time | |
multi_level_squares = self.square_anchor_generator.grid_priors( | |
featmap_sizes, device=device) | |
squares_list = [multi_level_squares for _ in range(num_imgs)] | |
return squares_list | |
def get_target(self, | |
approx_list, | |
inside_flag_list, | |
square_list, | |
gt_bboxes_list, | |
img_metas, | |
gt_bboxes_ignore_list=None, | |
gt_labels_list=None, | |
label_channels=None, | |
sampling=True, | |
unmap_outputs=True): | |
"""Compute bucketing targets. | |
Args: | |
approx_list (list[list]): Multi level approxs of each image. | |
inside_flag_list (list[list]): Multi level inside flags of each | |
image. | |
square_list (list[list]): Multi level squares of each image. | |
gt_bboxes_list (list[Tensor]): Ground truth bboxes of each image. | |
img_metas (list[dict]): Meta info of each image. | |
gt_bboxes_ignore_list (list[Tensor]): ignore list of gt bboxes. | |
gt_bboxes_list (list[Tensor]): Gt bboxes of each image. | |
label_channels (int): Channel of label. | |
sampling (bool): Sample Anchors or not. | |
unmap_outputs (bool): unmap outputs or not. | |
Returns: | |
tuple: Returns a tuple containing learning targets. | |
- labels_list (list[Tensor]): Labels of each level. | |
- label_weights_list (list[Tensor]): Label weights of each \ | |
level. | |
- bbox_cls_targets_list (list[Tensor]): BBox cls targets of \ | |
each level. | |
- bbox_cls_weights_list (list[Tensor]): BBox cls weights of \ | |
each level. | |
- bbox_reg_targets_list (list[Tensor]): BBox reg targets of \ | |
each level. | |
- bbox_reg_weights_list (list[Tensor]): BBox reg weights of \ | |
each level. | |
- num_total_pos (int): Number of positive samples in all \ | |
images. | |
- num_total_neg (int): Number of negative samples in all \ | |
images. | |
""" | |
num_imgs = len(img_metas) | |
assert len(approx_list) == len(inside_flag_list) == len( | |
square_list) == num_imgs | |
# anchor number of multi levels | |
num_level_squares = [squares.size(0) for squares in square_list[0]] | |
# concat all level anchors and flags to a single tensor | |
inside_flag_flat_list = [] | |
approx_flat_list = [] | |
square_flat_list = [] | |
for i in range(num_imgs): | |
assert len(square_list[i]) == len(inside_flag_list[i]) | |
inside_flag_flat_list.append(torch.cat(inside_flag_list[i])) | |
approx_flat_list.append(torch.cat(approx_list[i])) | |
square_flat_list.append(torch.cat(square_list[i])) | |
# compute targets for each image | |
if gt_bboxes_ignore_list is None: | |
gt_bboxes_ignore_list = [None for _ in range(num_imgs)] | |
if gt_labels_list is None: | |
gt_labels_list = [None for _ in range(num_imgs)] | |
(all_labels, all_label_weights, all_bbox_cls_targets, | |
all_bbox_cls_weights, all_bbox_reg_targets, all_bbox_reg_weights, | |
pos_inds_list, neg_inds_list) = multi_apply( | |
self._get_target_single, | |
approx_flat_list, | |
inside_flag_flat_list, | |
square_flat_list, | |
gt_bboxes_list, | |
gt_bboxes_ignore_list, | |
gt_labels_list, | |
img_metas, | |
label_channels=label_channels, | |
sampling=sampling, | |
unmap_outputs=unmap_outputs) | |
# no valid anchors | |
if any([labels is None for labels in all_labels]): | |
return None | |
# sampled anchors of all images | |
num_total_pos = sum([max(inds.numel(), 1) for inds in pos_inds_list]) | |
num_total_neg = sum([max(inds.numel(), 1) for inds in neg_inds_list]) | |
# split targets to a list w.r.t. multiple levels | |
labels_list = images_to_levels(all_labels, num_level_squares) | |
label_weights_list = images_to_levels(all_label_weights, | |
num_level_squares) | |
bbox_cls_targets_list = images_to_levels(all_bbox_cls_targets, | |
num_level_squares) | |
bbox_cls_weights_list = images_to_levels(all_bbox_cls_weights, | |
num_level_squares) | |
bbox_reg_targets_list = images_to_levels(all_bbox_reg_targets, | |
num_level_squares) | |
bbox_reg_weights_list = images_to_levels(all_bbox_reg_weights, | |
num_level_squares) | |
return (labels_list, label_weights_list, bbox_cls_targets_list, | |
bbox_cls_weights_list, bbox_reg_targets_list, | |
bbox_reg_weights_list, num_total_pos, num_total_neg) | |
def _get_target_single(self, | |
flat_approxs, | |
inside_flags, | |
flat_squares, | |
gt_bboxes, | |
gt_bboxes_ignore, | |
gt_labels, | |
img_meta, | |
label_channels=None, | |
sampling=True, | |
unmap_outputs=True): | |
"""Compute regression and classification targets for anchors in a | |
single image. | |
Args: | |
flat_approxs (Tensor): flat approxs of a single image, | |
shape (n, 4) | |
inside_flags (Tensor): inside flags of a single image, | |
shape (n, ). | |
flat_squares (Tensor): flat squares of a single image, | |
shape (approxs_per_octave * n, 4) | |
gt_bboxes (Tensor): Ground truth bboxes of a single image, \ | |
shape (num_gts, 4). | |
gt_bboxes_ignore (Tensor): Ground truth bboxes to be | |
ignored, shape (num_ignored_gts, 4). | |
gt_labels (Tensor): Ground truth labels of each box, | |
shape (num_gts,). | |
img_meta (dict): Meta info of the image. | |
label_channels (int): Channel of label. | |
sampling (bool): Sample Anchors or not. | |
unmap_outputs (bool): unmap outputs or not. | |
Returns: | |
tuple: | |
- labels_list (Tensor): Labels in a single image | |
- label_weights (Tensor): Label weights in a single image | |
- bbox_cls_targets (Tensor): BBox cls targets in a single image | |
- bbox_cls_weights (Tensor): BBox cls weights in a single image | |
- bbox_reg_targets (Tensor): BBox reg targets in a single image | |
- bbox_reg_weights (Tensor): BBox reg weights in a single image | |
- num_total_pos (int): Number of positive samples \ | |
in a single image | |
- num_total_neg (int): Number of negative samples \ | |
in a single image | |
""" | |
if not inside_flags.any(): | |
return (None, ) * 8 | |
# assign gt and sample anchors | |
expand_inside_flags = inside_flags[:, None].expand( | |
-1, self.approxs_per_octave).reshape(-1) | |
approxs = flat_approxs[expand_inside_flags, :] | |
squares = flat_squares[inside_flags, :] | |
assign_result = self.assigner.assign(approxs, squares, | |
self.approxs_per_octave, | |
gt_bboxes, gt_bboxes_ignore) | |
sampling_result = self.sampler.sample(assign_result, squares, | |
gt_bboxes) | |
num_valid_squares = squares.shape[0] | |
bbox_cls_targets = squares.new_zeros( | |
(num_valid_squares, self.side_num * 4)) | |
bbox_cls_weights = squares.new_zeros( | |
(num_valid_squares, self.side_num * 4)) | |
bbox_reg_targets = squares.new_zeros( | |
(num_valid_squares, self.side_num * 4)) | |
bbox_reg_weights = squares.new_zeros( | |
(num_valid_squares, self.side_num * 4)) | |
labels = squares.new_full((num_valid_squares, ), | |
self.num_classes, | |
dtype=torch.long) | |
label_weights = squares.new_zeros(num_valid_squares, dtype=torch.float) | |
pos_inds = sampling_result.pos_inds | |
neg_inds = sampling_result.neg_inds | |
if len(pos_inds) > 0: | |
(pos_bbox_reg_targets, pos_bbox_reg_weights, pos_bbox_cls_targets, | |
pos_bbox_cls_weights) = self.bbox_coder.encode( | |
sampling_result.pos_bboxes, sampling_result.pos_gt_bboxes) | |
bbox_cls_targets[pos_inds, :] = pos_bbox_cls_targets | |
bbox_reg_targets[pos_inds, :] = pos_bbox_reg_targets | |
bbox_cls_weights[pos_inds, :] = pos_bbox_cls_weights | |
bbox_reg_weights[pos_inds, :] = pos_bbox_reg_weights | |
if gt_labels is None: | |
# Only rpn gives gt_labels as None | |
# Foreground is the first class | |
labels[pos_inds] = 0 | |
else: | |
labels[pos_inds] = gt_labels[ | |
sampling_result.pos_assigned_gt_inds] | |
if self.train_cfg.pos_weight <= 0: | |
label_weights[pos_inds] = 1.0 | |
else: | |
label_weights[pos_inds] = self.train_cfg.pos_weight | |
if len(neg_inds) > 0: | |
label_weights[neg_inds] = 1.0 | |
# map up to original set of anchors | |
if unmap_outputs: | |
num_total_anchors = flat_squares.size(0) | |
labels = unmap( | |
labels, num_total_anchors, inside_flags, fill=self.num_classes) | |
label_weights = unmap(label_weights, num_total_anchors, | |
inside_flags) | |
bbox_cls_targets = unmap(bbox_cls_targets, num_total_anchors, | |
inside_flags) | |
bbox_cls_weights = unmap(bbox_cls_weights, num_total_anchors, | |
inside_flags) | |
bbox_reg_targets = unmap(bbox_reg_targets, num_total_anchors, | |
inside_flags) | |
bbox_reg_weights = unmap(bbox_reg_weights, num_total_anchors, | |
inside_flags) | |
return (labels, label_weights, bbox_cls_targets, bbox_cls_weights, | |
bbox_reg_targets, bbox_reg_weights, pos_inds, neg_inds) | |
def loss_single(self, cls_score, bbox_pred, labels, label_weights, | |
bbox_cls_targets, bbox_cls_weights, bbox_reg_targets, | |
bbox_reg_weights, num_total_samples): | |
# classification loss | |
labels = labels.reshape(-1) | |
label_weights = label_weights.reshape(-1) | |
cls_score = cls_score.permute(0, 2, 3, | |
1).reshape(-1, self.cls_out_channels) | |
loss_cls = self.loss_cls( | |
cls_score, labels, label_weights, avg_factor=num_total_samples) | |
# regression loss | |
bbox_cls_targets = bbox_cls_targets.reshape(-1, self.side_num * 4) | |
bbox_cls_weights = bbox_cls_weights.reshape(-1, self.side_num * 4) | |
bbox_reg_targets = bbox_reg_targets.reshape(-1, self.side_num * 4) | |
bbox_reg_weights = bbox_reg_weights.reshape(-1, self.side_num * 4) | |
(bbox_cls_pred, bbox_reg_pred) = bbox_pred | |
bbox_cls_pred = bbox_cls_pred.permute(0, 2, 3, 1).reshape( | |
-1, self.side_num * 4) | |
bbox_reg_pred = bbox_reg_pred.permute(0, 2, 3, 1).reshape( | |
-1, self.side_num * 4) | |
loss_bbox_cls = self.loss_bbox_cls( | |
bbox_cls_pred, | |
bbox_cls_targets.long(), | |
bbox_cls_weights, | |
avg_factor=num_total_samples * 4 * self.side_num) | |
loss_bbox_reg = self.loss_bbox_reg( | |
bbox_reg_pred, | |
bbox_reg_targets, | |
bbox_reg_weights, | |
avg_factor=num_total_samples * 4 * self.bbox_coder.offset_topk) | |
return loss_cls, loss_bbox_cls, loss_bbox_reg | |
def loss(self, | |
cls_scores, | |
bbox_preds, | |
gt_bboxes, | |
gt_labels, | |
img_metas, | |
gt_bboxes_ignore=None): | |
featmap_sizes = [featmap.size()[-2:] for featmap in cls_scores] | |
assert len(featmap_sizes) == self.approx_anchor_generator.num_levels | |
device = cls_scores[0].device | |
# get sampled approxes | |
approxs_list, inside_flag_list = GuidedAnchorHead.get_sampled_approxs( | |
self, featmap_sizes, img_metas, device=device) | |
square_list = self.get_anchors(featmap_sizes, img_metas, device=device) | |
label_channels = self.cls_out_channels if self.use_sigmoid_cls else 1 | |
cls_reg_targets = self.get_target( | |
approxs_list, | |
inside_flag_list, | |
square_list, | |
gt_bboxes, | |
img_metas, | |
gt_bboxes_ignore_list=gt_bboxes_ignore, | |
gt_labels_list=gt_labels, | |
label_channels=label_channels, | |
sampling=self.sampling) | |
if cls_reg_targets is None: | |
return None | |
(labels_list, label_weights_list, bbox_cls_targets_list, | |
bbox_cls_weights_list, bbox_reg_targets_list, bbox_reg_weights_list, | |
num_total_pos, num_total_neg) = cls_reg_targets | |
num_total_samples = ( | |
num_total_pos + num_total_neg if self.sampling else num_total_pos) | |
losses_cls, losses_bbox_cls, losses_bbox_reg = multi_apply( | |
self.loss_single, | |
cls_scores, | |
bbox_preds, | |
labels_list, | |
label_weights_list, | |
bbox_cls_targets_list, | |
bbox_cls_weights_list, | |
bbox_reg_targets_list, | |
bbox_reg_weights_list, | |
num_total_samples=num_total_samples) | |
return dict( | |
loss_cls=losses_cls, | |
loss_bbox_cls=losses_bbox_cls, | |
loss_bbox_reg=losses_bbox_reg) | |
def get_bboxes(self, | |
cls_scores, | |
bbox_preds, | |
img_metas, | |
cfg=None, | |
rescale=False): | |
assert len(cls_scores) == len(bbox_preds) | |
num_levels = len(cls_scores) | |
featmap_sizes = [featmap.size()[-2:] for featmap in cls_scores] | |
device = cls_scores[0].device | |
mlvl_anchors = self.get_anchors( | |
featmap_sizes, img_metas, device=device) | |
result_list = [] | |
for img_id in range(len(img_metas)): | |
cls_score_list = [ | |
cls_scores[i][img_id].detach() for i in range(num_levels) | |
] | |
bbox_cls_pred_list = [ | |
bbox_preds[i][0][img_id].detach() for i in range(num_levels) | |
] | |
bbox_reg_pred_list = [ | |
bbox_preds[i][1][img_id].detach() for i in range(num_levels) | |
] | |
img_shape = img_metas[img_id]['img_shape'] | |
scale_factor = img_metas[img_id]['scale_factor'] | |
proposals = self._get_bboxes_single( | |
cls_score_list, bbox_cls_pred_list, bbox_reg_pred_list, | |
mlvl_anchors[img_id], img_shape, scale_factor, cfg, rescale) | |
result_list.append(proposals) | |
return result_list | |
def _get_bboxes_single(self, | |
cls_scores, | |
bbox_cls_preds, | |
bbox_reg_preds, | |
mlvl_anchors, | |
img_shape, | |
scale_factor, | |
cfg, | |
rescale=False): | |
cfg = self.test_cfg if cfg is None else cfg | |
nms_pre = cfg.get('nms_pre', -1) | |
mlvl_bboxes = [] | |
mlvl_scores = [] | |
mlvl_confids = [] | |
mlvl_labels = [] | |
assert len(cls_scores) == len(bbox_cls_preds) == len( | |
bbox_reg_preds) == len(mlvl_anchors) | |
for cls_score, bbox_cls_pred, bbox_reg_pred, anchors in zip( | |
cls_scores, bbox_cls_preds, bbox_reg_preds, mlvl_anchors): | |
assert cls_score.size()[-2:] == bbox_cls_pred.size( | |
)[-2:] == bbox_reg_pred.size()[-2::] | |
cls_score = cls_score.permute(1, 2, | |
0).reshape(-1, self.cls_out_channels) | |
if self.use_sigmoid_cls: | |
scores = cls_score.sigmoid() | |
else: | |
scores = cls_score.softmax(-1)[:, :-1] | |
bbox_cls_pred = bbox_cls_pred.permute(1, 2, 0).reshape( | |
-1, self.side_num * 4) | |
bbox_reg_pred = bbox_reg_pred.permute(1, 2, 0).reshape( | |
-1, self.side_num * 4) | |
# After https://github.com/open-mmlab/mmdetection/pull/6268/, | |
# this operation keeps fewer bboxes under the same `nms_pre`. | |
# There is no difference in performance for most models. If you | |
# find a slight drop in performance, you can set a larger | |
# `nms_pre` than before. | |
results = filter_scores_and_topk( | |
scores, cfg.score_thr, nms_pre, | |
dict( | |
anchors=anchors, | |
bbox_cls_pred=bbox_cls_pred, | |
bbox_reg_pred=bbox_reg_pred)) | |
scores, labels, _, filtered_results = results | |
anchors = filtered_results['anchors'] | |
bbox_cls_pred = filtered_results['bbox_cls_pred'] | |
bbox_reg_pred = filtered_results['bbox_reg_pred'] | |
bbox_preds = [ | |
bbox_cls_pred.contiguous(), | |
bbox_reg_pred.contiguous() | |
] | |
bboxes, confids = self.bbox_coder.decode( | |
anchors.contiguous(), bbox_preds, max_shape=img_shape) | |
mlvl_bboxes.append(bboxes) | |
mlvl_scores.append(scores) | |
mlvl_confids.append(confids) | |
mlvl_labels.append(labels) | |
return self._bbox_post_process(mlvl_scores, mlvl_labels, mlvl_bboxes, | |
scale_factor, cfg, rescale, True, | |
mlvl_confids) | |