|
|
import unittest |
|
|
|
|
|
import torch |
|
|
from mmengine.config import ConfigDict |
|
|
from mmengine.structures import InstanceData |
|
|
from parameterized import parameterized |
|
|
|
|
|
from mmdet.models.dense_heads import RepPointsHead |
|
|
from mmdet.structures import DetDataSample |
|
|
|
|
|
|
|
|
class TestRepPointsHead(unittest.TestCase): |
|
|
|
|
|
@parameterized.expand(['moment', 'minmax', 'partial_minmax']) |
|
|
def test_head_loss(self, transform_method='moment'): |
|
|
cfg = ConfigDict( |
|
|
dict( |
|
|
num_classes=2, |
|
|
in_channels=32, |
|
|
point_feat_channels=10, |
|
|
num_points=9, |
|
|
gradient_mul=0.1, |
|
|
point_strides=[8, 16, 32, 64, 128], |
|
|
point_base_scale=4, |
|
|
loss_cls=dict( |
|
|
type='FocalLoss', |
|
|
use_sigmoid=True, |
|
|
gamma=2.0, |
|
|
alpha=0.25, |
|
|
loss_weight=1.0), |
|
|
loss_bbox_init=dict( |
|
|
type='SmoothL1Loss', beta=1.0 / 9.0, loss_weight=0.5), |
|
|
loss_bbox_refine=dict( |
|
|
type='SmoothL1Loss', beta=1.0 / 9.0, loss_weight=1.0), |
|
|
use_grid_points=False, |
|
|
center_init=True, |
|
|
transform_method=transform_method, |
|
|
moment_mul=0.01, |
|
|
init_cfg=dict( |
|
|
type='Normal', |
|
|
layer='Conv2d', |
|
|
std=0.01, |
|
|
override=dict( |
|
|
type='Normal', |
|
|
name='reppoints_cls_out', |
|
|
std=0.01, |
|
|
bias_prob=0.01)), |
|
|
train_cfg=dict( |
|
|
init=dict( |
|
|
assigner=dict( |
|
|
type='PointAssigner', scale=4, pos_num=1), |
|
|
allowed_border=-1, |
|
|
pos_weight=-1, |
|
|
debug=False), |
|
|
refine=dict( |
|
|
assigner=dict( |
|
|
type='MaxIoUAssigner', |
|
|
pos_iou_thr=0.5, |
|
|
neg_iou_thr=0.4, |
|
|
min_pos_iou=0, |
|
|
ignore_iof_thr=-1), |
|
|
allowed_border=-1, |
|
|
pos_weight=-1, |
|
|
debug=False)), |
|
|
test_cfg=dict( |
|
|
nms_pre=1000, |
|
|
min_bbox_size=0, |
|
|
score_thr=0.05, |
|
|
nms=dict(type='nms', iou_threshold=0.5), |
|
|
max_per_img=100))) |
|
|
reppoints_head = RepPointsHead(**cfg) |
|
|
s = 256 |
|
|
img_metas = [{ |
|
|
'img_shape': (s, s), |
|
|
'scale_factor': (1, 1), |
|
|
'pad_shape': (s, s), |
|
|
'batch_input_shape': (s, s) |
|
|
}] |
|
|
x = [ |
|
|
torch.rand(1, 32, s // 2**(i + 2), s // 2**(i + 2)) |
|
|
for i in range(5) |
|
|
] |
|
|
|
|
|
|
|
|
|
|
|
gt_instances = InstanceData() |
|
|
gt_instances.bboxes = torch.empty((0, 4)) |
|
|
gt_instances.labels = torch.LongTensor([]) |
|
|
gt_bboxes_ignore = None |
|
|
|
|
|
reppoints_head.train() |
|
|
forward_outputs = reppoints_head.forward(x) |
|
|
empty_gt_losses = reppoints_head.loss_by_feat(*forward_outputs, |
|
|
[gt_instances], |
|
|
img_metas, |
|
|
gt_bboxes_ignore) |
|
|
|
|
|
|
|
|
for key, losses in empty_gt_losses.items(): |
|
|
for loss in losses: |
|
|
if 'cls' in key: |
|
|
self.assertGreater(loss.item(), 0, |
|
|
'cls loss should be non-zero') |
|
|
elif 'pts' in key: |
|
|
self.assertEqual( |
|
|
loss.item(), 0, |
|
|
'there should be no reg loss when no ground true boxes' |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
gt_instances = InstanceData() |
|
|
gt_instances.bboxes = torch.Tensor( |
|
|
[[23.6667, 23.8757, 238.6326, 151.8874]]) |
|
|
gt_instances.labels = torch.LongTensor([2]) |
|
|
one_gt_losses = reppoints_head.loss_by_feat(*forward_outputs, |
|
|
[gt_instances], img_metas, |
|
|
gt_bboxes_ignore) |
|
|
|
|
|
self.assertTrue( |
|
|
all([loss.item() > 0 for loss in one_gt_losses['loss_cls']])) |
|
|
|
|
|
cnt_non_zero = 0 |
|
|
for loss in one_gt_losses['loss_pts_init']: |
|
|
if loss.item() != 0: |
|
|
cnt_non_zero += 1 |
|
|
self.assertEqual(cnt_non_zero, 1) |
|
|
|
|
|
|
|
|
cnt_non_zero = 0 |
|
|
for loss in one_gt_losses['loss_pts_init']: |
|
|
if loss.item() != 0: |
|
|
cnt_non_zero += 1 |
|
|
self.assertEqual(cnt_non_zero, 1) |
|
|
|
|
|
|
|
|
samples = DetDataSample() |
|
|
samples.set_metainfo(img_metas[0]) |
|
|
samples.gt_instances = gt_instances |
|
|
reppoints_head.loss(x, [samples]) |
|
|
|
|
|
reppoints_head.eval() |
|
|
reppoints_head.predict(x, [samples], rescale=True) |
|
|
|