def test_bbox_head_loss(): """ Tests bbox head loss when truth is empty and non-empty """ self = BBoxHead(in_channels=8, roi_feat_size=3) num_imgs = 1 feat = torch.rand(1, 1, 3, 3) # Dummy proposals proposal_list = [torch.Tensor([[23.6667, 23.8757, 228.6326, 153.8874]])] target_cfg = mmcv.Config({"pos_weight": 1}) def _dummy_bbox_sampling(proposal_list, gt_bboxes, gt_labels): """ Create sample results that can be passed to BBoxHead.get_target """ assign_config = { "type": "MaxIoUAssigner", "pos_iou_thr": 0.5, "neg_iou_thr": 0.5, "min_pos_iou": 0.5, "ignore_iof_thr": -1, } sampler_config = { "type": "RandomSampler", "num": 512, "pos_fraction": 0.25, "neg_pos_ub": -1, "add_gt_as_proposals": True, } bbox_assigner = build_assigner(assign_config) bbox_sampler = build_sampler(sampler_config) gt_bboxes_ignore = [None for _ in range(num_imgs)] sampling_results = [] for i in range(num_imgs): assign_result = bbox_assigner.assign(proposal_list[i], gt_bboxes[i], gt_bboxes_ignore[i], gt_labels[i]) sampling_result = bbox_sampler.sample(assign_result, proposal_list[i], gt_bboxes[i], gt_labels[i], feats=feat) sampling_results.append(sampling_result) return sampling_results # Test bbox loss when truth is empty gt_bboxes = [torch.empty((0, 4))] gt_labels = [torch.LongTensor([])] sampling_results = _dummy_bbox_sampling(proposal_list, gt_bboxes, gt_labels) bbox_targets = self.get_target(sampling_results, gt_bboxes, gt_labels, target_cfg) labels, label_weights, bbox_targets, bbox_weights = bbox_targets # Create dummy features "extracted" for each sampled bbox num_sampled = sum(len(res.bboxes) for res in sampling_results) dummy_feats = torch.rand(num_sampled, 8 * 3 * 3) cls_scores, bbox_preds = self.forward(dummy_feats) losses = self.loss(cls_scores, bbox_preds, labels, label_weights, bbox_targets, bbox_weights) assert losses.get("loss_cls", 0) > 0, "cls-loss should be non-zero" assert losses.get("loss_bbox", 0) == 0, "empty gt loss should be zero" # Test bbox loss when truth is non-empty gt_bboxes = [torch.Tensor([[23.6667, 23.8757, 238.6326, 151.8874]])] gt_labels = [torch.LongTensor([2])] sampling_results = _dummy_bbox_sampling(proposal_list, gt_bboxes, gt_labels) bbox_targets = self.get_target(sampling_results, gt_bboxes, gt_labels, target_cfg) labels, label_weights, bbox_targets, bbox_weights = bbox_targets # Create dummy features "extracted" for each sampled bbox num_sampled = sum(len(res.bboxes) for res in sampling_results) dummy_feats = torch.rand(num_sampled, 8 * 3 * 3) cls_scores, bbox_preds = self.forward(dummy_feats) losses = self.loss(cls_scores, bbox_preds, labels, label_weights, bbox_targets, bbox_weights) assert losses.get("loss_cls", 0) > 0, "cls-loss should be non-zero" assert losses.get("loss_bbox", 0) > 0, "box-loss should be non-zero"
def test_ga_anchor_head_loss(): """Tests anchor head loss when truth is empty and non-empty.""" s = 256 img_metas = [{ 'img_shape': (s, s, 3), 'scale_factor': 1, 'pad_shape': (s, s, 3) }] cfg = mmcv.Config( dict(assigner=dict(type='MaxIoUAssigner', pos_iou_thr=0.7, neg_iou_thr=0.3, min_pos_iou=0.3, match_low_quality=True, ignore_iof_thr=-1), sampler=dict(type='RandomSampler', num=256, pos_fraction=0.5, neg_pos_ub=-1, add_gt_as_proposals=False), ga_assigner=dict(type='ApproxMaxIoUAssigner', pos_iou_thr=0.7, neg_iou_thr=0.3, min_pos_iou=0.3, ignore_iof_thr=-1), ga_sampler=dict(type='RandomSampler', num=256, pos_fraction=0.5, neg_pos_ub=-1, add_gt_as_proposals=False), allowed_border=-1, center_ratio=0.2, ignore_ratio=0.5, pos_weight=-1, debug=False)) head = GuidedAnchorHead(num_classes=4, in_channels=4, train_cfg=cfg) # Anchor head expects a multiple levels of features per image if torch.cuda.is_available(): head.cuda() feat = [ torch.rand(1, 4, s // (2**(i + 2)), s // (2**(i + 2))).cuda() for i in range(len(head.approx_anchor_generator.base_anchors)) ] cls_scores, bbox_preds, shape_preds, loc_preds = head.forward(feat) # Test that empty ground truth encourages the network to predict # background gt_bboxes = [torch.empty((0, 4)).cuda()] gt_labels = [torch.LongTensor([]).cuda()] gt_bboxes_ignore = None empty_gt_losses = head.loss(cls_scores, bbox_preds, shape_preds, loc_preds, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore) # When there is no truth, the cls loss should be nonzero but there # should be no box loss. empty_cls_loss = sum(empty_gt_losses['loss_cls']) empty_box_loss = sum(empty_gt_losses['loss_bbox']) assert empty_cls_loss.item() > 0, 'cls loss should be non-zero' assert empty_box_loss.item() == 0, ( 'there should be no box loss when there are no true boxes') # When truth is non-empty then both cls and box loss should be nonzero # for random inputs gt_bboxes = [ torch.Tensor([[23.6667, 23.8757, 238.6326, 151.8874]]).cuda(), ] gt_labels = [torch.LongTensor([2]).cuda()] one_gt_losses = head.loss(cls_scores, bbox_preds, shape_preds, loc_preds, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore) onegt_cls_loss = sum(one_gt_losses['loss_cls']) onegt_box_loss = sum(one_gt_losses['loss_bbox']) assert onegt_cls_loss.item() > 0, 'cls loss should be non-zero' assert onegt_box_loss.item() > 0, 'box loss should be non-zero'
def test_ld_head_loss(): """Tests vfnet head loss when truth is empty and non-empty.""" s = 256 img_metas = [{ 'img_shape': (s, s, 3), 'scale_factor': 1, 'pad_shape': (s, s, 3) }] train_cfg = mmcv.Config( dict(assigner=dict(type='ATSSAssigner', topk=9, ignore_iof_thr=0.1), allowed_border=-1, pos_weight=-1, debug=False)) self = LDHead(num_classes=4, in_channels=1, train_cfg=train_cfg, loss_ld=dict(type='KnowledgeDistillationKLDivLoss', loss_weight=1.0), loss_cls=dict(type='QualityFocalLoss', use_sigmoid=True, beta=2.0, loss_weight=1.0), loss_bbox=dict(type='GIoULoss', loss_weight=2.0), anchor_generator=dict(type='AnchorGenerator', ratios=[1.0], octave_base_scale=8, scales_per_octave=1, strides=[8, 16, 32, 64, 128])) teacher_model = GFLHead(num_classes=4, in_channels=1, train_cfg=train_cfg, loss_cls=dict(type='QualityFocalLoss', use_sigmoid=True, beta=2.0, loss_weight=1.0), loss_bbox=dict(type='GIoULoss', loss_weight=2.0), anchor_generator=dict(type='AnchorGenerator', ratios=[1.0], octave_base_scale=8, scales_per_octave=1, strides=[8, 16, 32, 64, 128])) feat = [ torch.rand(1, 1, s // feat_size, s // feat_size) for feat_size in [4, 8, 16, 32, 64] ] cls_scores, bbox_preds = self.forward(feat) rand_soft_target = teacher_model.forward(feat)[1] # Test that empty ground truth encourages the network to predict # background gt_bboxes = [torch.empty((0, 4))] gt_labels = [torch.LongTensor([])] gt_bboxes_ignore = None empty_gt_losses = self.loss(cls_scores, bbox_preds, gt_bboxes, gt_labels, rand_soft_target, img_metas, gt_bboxes_ignore) # When there is no truth, the cls loss should be nonzero, ld loss should # be non-negative but there should be no box loss. empty_cls_loss = sum(empty_gt_losses['loss_cls']) empty_box_loss = sum(empty_gt_losses['loss_bbox']) empty_ld_loss = sum(empty_gt_losses['loss_ld']) assert empty_cls_loss.item() > 0, 'cls loss should be non-zero' assert empty_box_loss.item() == 0, ( 'there should be no box loss when there are no true boxes') assert empty_ld_loss.item() >= 0, 'ld loss should be non-negative' # When truth is non-empty then both cls and box loss should be nonzero # for random inputs gt_bboxes = [ torch.Tensor([[23.6667, 23.8757, 238.6326, 151.8874]]), ] gt_labels = [torch.LongTensor([2])] one_gt_losses = self.loss(cls_scores, bbox_preds, gt_bboxes, gt_labels, rand_soft_target, img_metas, gt_bboxes_ignore) onegt_cls_loss = sum(one_gt_losses['loss_cls']) onegt_box_loss = sum(one_gt_losses['loss_bbox']) assert onegt_cls_loss.item() > 0, 'cls loss should be non-zero' assert onegt_box_loss.item() > 0, 'box loss should be non-zero' gt_bboxes_ignore = gt_bboxes # When truth is non-empty but ignored then the cls loss should be nonzero, # but there should be no box loss. ignore_gt_losses = self.loss(cls_scores, bbox_preds, gt_bboxes, gt_labels, rand_soft_target, img_metas, gt_bboxes_ignore) ignore_cls_loss = sum(ignore_gt_losses['loss_cls']) ignore_box_loss = sum(ignore_gt_losses['loss_bbox']) assert ignore_cls_loss.item() > 0, 'cls loss should be non-zero' assert ignore_box_loss.item() == 0, 'gt bbox ignored loss should be zero' # When truth is non-empty and not ignored then both cls and box loss should # be nonzero for random inputs gt_bboxes_ignore = [torch.randn(1, 4)] not_ignore_gt_losses = self.loss(cls_scores, bbox_preds, gt_bboxes, gt_labels, rand_soft_target, img_metas, gt_bboxes_ignore) not_ignore_cls_loss = sum(not_ignore_gt_losses['loss_cls']) not_ignore_box_loss = sum(not_ignore_gt_losses['loss_bbox']) assert not_ignore_cls_loss.item() > 0, 'cls loss should be non-zero' assert not_ignore_box_loss.item( ) > 0, 'gt bbox not ignored loss should be non-zero'
def test_restorer_wrapper(): try: import onnxruntime as ort from mmedit.core.export.wrappers import (ONNXRuntimeEditing, ONNXRuntimeRestorer) except ImportError: pytest.skip('ONNXRuntime is not available.') onnx_path = 'tmp.onnx' scale = 4 train_cfg = None test_cfg = None cfg = dict( model=dict( type='BasicRestorer', generator=dict( type='SRCNN', channels=(3, 4, 2, 3), kernel_sizes=(9, 1, 5), upscale_factor=scale), pixel_loss=dict(type='L1Loss', loss_weight=1.0, reduction='mean')), train_cfg=train_cfg, test_cfg=test_cfg) cfg = mmcv.Config(cfg) pytorch_model = build_model( cfg.model, train_cfg=cfg.train_cfg, test_cfg=cfg.test_cfg) # prepare data inputs = torch.rand(1, 3, 2, 2) targets = torch.rand(1, 3, 8, 8) data_batch = {'lq': inputs, 'gt': targets} pytorch_model.forward = pytorch_model.forward_dummy with torch.no_grad(): torch.onnx.export( pytorch_model, inputs, onnx_path, input_names=['input'], output_names=['output'], export_params=True, keep_initializers_as_inputs=False, verbose=False, opset_version=11) wrap_model = ONNXRuntimeEditing(onnx_path, cfg, 0) # os.remove(onnx_path) assert isinstance(wrap_model.wrapper, ONNXRuntimeRestorer) if ort.get_device() == 'GPU': data_batch = {'lq': inputs.cuda(), 'gt': targets.cuda()} with torch.no_grad(): outputs = wrap_model(**data_batch, test_mode=True) assert isinstance(outputs, dict) assert 'output' in outputs output = outputs['output'] assert isinstance(output, torch.Tensor) assert output.shape == targets.shape
def test_selsa_bbox_head_loss(): """Tests selsa_bbox_head loss when truth is empty and non-empty.""" selsa_bbox_head_config = dict(num_shared_fcs=2, in_channels=8, fc_out_channels=16, roi_feat_size=3, aggregator=dict(type='SelsaAggregator', in_channels=16, num_attention_blocks=4)) self = SelsaBBoxHead(**selsa_bbox_head_config) # Dummy proposals proposal_list = [ torch.Tensor([[23.6667, 23.8757, 228.6326, 153.8874]]), ] target_cfg = mmcv.Config(dict(pos_weight=1)) # Test bbox loss when truth is empty gt_bboxes = [torch.empty((0, 4))] gt_labels = [torch.LongTensor([])] sampling_results = _dummy_bbox_sampling(proposal_list, gt_bboxes, gt_labels) bbox_targets = self.get_targets(sampling_results, gt_bboxes, gt_labels, target_cfg) labels, label_weights, bbox_targets, bbox_weights = bbox_targets # Create dummy features "extracted" for each sampled bbox num_sampled = sum(len(res.bboxes) for res in sampling_results) rois = bbox2roi([res.bboxes for res in sampling_results]) dummy_feats = torch.rand(num_sampled, 8, 3, 3) ref_dummy_feats = torch.rand(2 * num_sampled, 8, 3, 3) cls_scores, bbox_preds = self.forward(dummy_feats, ref_dummy_feats) losses = self.loss(cls_scores, bbox_preds, rois, labels, label_weights, bbox_targets, bbox_weights) assert losses.get('loss_cls', 0) > 0, 'cls-loss should be non-zero' assert losses.get('loss_bbox', 0) == 0, 'empty gt loss should be zero' # Test bbox loss when truth is non-empty gt_bboxes = [ torch.Tensor([[23.6667, 23.8757, 238.6326, 151.8874]]), ] gt_labels = [torch.LongTensor([2])] sampling_results = _dummy_bbox_sampling(proposal_list, gt_bboxes, gt_labels) rois = bbox2roi([res.bboxes for res in sampling_results]) bbox_targets = self.get_targets(sampling_results, gt_bboxes, gt_labels, target_cfg) labels, label_weights, bbox_targets, bbox_weights = bbox_targets # Create dummy features "extracted" for each sampled bbox num_sampled = sum(len(res.bboxes) for res in sampling_results) dummy_feats = torch.rand(num_sampled, 8, 3, 3) ref_dummy_feats = torch.rand(2 * num_sampled, 8, 3, 3) cls_scores, bbox_preds = self.forward(dummy_feats, ref_dummy_feats) losses = self.loss(cls_scores, bbox_preds, rois, labels, label_weights, bbox_targets, bbox_weights) assert losses.get('loss_cls', 0) > 0, 'cls-loss should be non-zero' assert losses.get('loss_bbox', 0) > 0, 'box-loss should be non-zero'
def test_autoassign_head_loss(): """Tests autoassign head loss when truth is empty and non-empty.""" s = 256 img_metas = [{ 'img_shape': (s, s, 3), 'scale_factor': 1, 'pad_shape': (s, s, 3) }] train_cfg = mmcv.Config( dict(assigner=None, allowed_border=-1, pos_weight=-1, debug=False)) self = AutoAssignHead(num_classes=4, in_channels=1, train_cfg=train_cfg, loss_cls=dict(type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0), loss_bbox=dict(type='GIoULoss', loss_weight=1.3)) feat = [ torch.rand(1, 1, s // feat_size, s // feat_size) for feat_size in [4, 8, 16, 32, 64] ] self.init_weights() cls_scores, bbox_preds, objectnesses = self(feat) # Test that empty ground truth encourages the network to predict background gt_bboxes = [torch.empty((0, 4))] gt_labels = [torch.LongTensor([])] gt_bboxes_ignore = None empty_gt_losses = self.loss(cls_scores, bbox_preds, objectnesses, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore) # When there is no truth, the cls loss should be nonzero but there should # be no box loss. empty_pos_loss = empty_gt_losses['loss_pos'] empty_neg_loss = empty_gt_losses['loss_neg'] empty_center_loss = empty_gt_losses['loss_center'] assert empty_neg_loss.item() > 0, 'cls loss should be non-zero' assert empty_pos_loss.item() == 0, ( 'there should be no box loss when there are no true boxes') assert empty_center_loss.item() == 0, ( 'there should be no box loss when there are no true boxes') # When truth is non-empty then both cls and box loss should be nonzero for # random inputs gt_bboxes = [ torch.Tensor([[23.6667, 23.8757, 238.6326, 151.8874]]), ] gt_labels = [torch.LongTensor([2])] one_gt_losses = self.loss(cls_scores, bbox_preds, objectnesses, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore) onegt_pos_loss = one_gt_losses['loss_pos'] onegt_neg_loss = one_gt_losses['loss_neg'] onegt_center_loss = one_gt_losses['loss_center'] assert onegt_pos_loss.item() > 0, 'cls loss should be non-zero' assert onegt_neg_loss.item() > 0, 'box loss should be non-zero' assert onegt_center_loss.item() > 0, 'box loss should be non-zero' n, c, h, w = 10, 4, 20, 20 mlvl_tensor = [torch.ones(n, c, h, w) for i in range(5)] results = levels_to_images(mlvl_tensor) assert len(results) == n assert results[0].size() == (h * w * 5, c) cls_scores = [torch.ones(2, 4, 5, 5)] bbox_preds = [torch.ones(2, 4, 5, 5)] iou_preds = [torch.ones(2, 1, 5, 5)] mlvl_anchors = [torch.ones(5 * 5, 2)] img_shape = None scale_factor = [0.5, 0.5] cfg = mmcv.Config( dict(nms_pre=1000, min_bbox_size=0, score_thr=0.05, nms=dict(type='nms', iou_threshold=0.6), max_per_img=100)) rescale = False self._get_bboxes(cls_scores, bbox_preds, iou_preds, mlvl_anchors, img_shape, scale_factor, cfg, rescale=rescale)
def test_pisa_retinanet_head_loss(): """Tests pisa retinanet head loss when truth is empty and non-empty.""" s = 256 img_metas = [{ 'img_shape': (s, s, 3), 'scale_factor': 1, 'pad_shape': (s, s, 3) }] cfg = mmcv.Config( dict(assigner=dict(type='MaxIoUAssigner', pos_iou_thr=0.7, neg_iou_thr=0.3, min_pos_iou=0.3, match_low_quality=True, ignore_iof_thr=-1), sampler=dict(type='RandomSampler', num=256, pos_fraction=0.5, neg_pos_ub=-1, add_gt_as_proposals=False), isr=dict(k=2., bias=0.), carl=dict(k=1., bias=0.2), allowed_border=0, pos_weight=-1, debug=False)) self = PISARetinaHead(num_classes=4, in_channels=1, train_cfg=cfg) # Anchor head expects a multiple levels of features per image feat = [ torch.rand(1, 1, s // (2**(i + 2)), s // (2**(i + 2))) for i in range(len(self.anchor_generator.strides)) ] cls_scores, bbox_preds = self.forward(feat) # Test that empty ground truth encourages the network to predict background gt_bboxes = [torch.empty((0, 4))] gt_labels = [torch.LongTensor([])] gt_bboxes_ignore = None empty_gt_losses = self.loss(cls_scores, bbox_preds, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore) # When there is no truth, the cls loss should be nonzero but there should # be no box loss. empty_cls_loss = empty_gt_losses['loss_cls'].sum() empty_box_loss = empty_gt_losses['loss_bbox'].sum() assert empty_cls_loss.item() > 0, 'cls loss should be non-zero' assert empty_box_loss.item() == 0, ( 'there should be no box loss when there are no true boxes') # When truth is non-empty then both cls and box loss should be nonzero for # random inputs gt_bboxes = [ torch.Tensor([[23.6667, 23.8757, 238.6326, 151.8874]]), ] gt_labels = [torch.LongTensor([2])] one_gt_losses = self.loss(cls_scores, bbox_preds, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore) onegt_cls_loss = one_gt_losses['loss_cls'].sum() onegt_box_loss = one_gt_losses['loss_bbox'].sum() assert onegt_cls_loss.item() > 0, 'cls loss should be non-zero' assert onegt_box_loss.item() > 0, 'box loss should be non-zero'
def test_basicvsr_model(): model_cfg = dict( type='BasicVSR', generator=dict(type='BasicVSRNet', mid_channels=64, num_blocks=30, spynet_pretrained=None), pixel_loss=dict(type='MSELoss', loss_weight=1.0, reduction='sum'), ) train_cfg = dict(fix_iter=1) train_cfg = mmcv.Config(train_cfg) test_cfg = None # build restorer restorer = build_model(model_cfg, train_cfg=train_cfg, test_cfg=test_cfg) # test attributes assert restorer.__class__.__name__ == 'BasicVSR' assert isinstance(restorer.generator, BasicVSRNet) assert isinstance(restorer.pixel_loss, MSELoss) # prepare data inputs = torch.rand(1, 5, 3, 64, 64) targets = torch.rand(1, 5, 3, 256, 256) if torch.cuda.is_available(): inputs = inputs.cuda() targets = targets.cuda() restorer = restorer.cuda() # prepare data and optimizer data_batch = {'lq': inputs, 'gt': targets} optim_cfg = dict(type='Adam', lr=2e-4, betas=(0.9, 0.999)) optimizer = { 'generator': obj_from_dict(optim_cfg, torch.optim, dict(params=getattr(restorer, 'generator').parameters())) } # train_step (wihout updating spynet) outputs = restorer.train_step(data_batch, optimizer) assert isinstance(outputs, dict) assert isinstance(outputs['log_vars'], dict) assert isinstance(outputs['log_vars']['loss_pix'], float) assert outputs['num_samples'] == 1 assert torch.equal(outputs['results']['lq'], data_batch['lq'].cpu()) assert torch.equal(outputs['results']['gt'], data_batch['gt'].cpu()) assert torch.is_tensor(outputs['results']['output']) assert outputs['results']['output'].size() == (1, 5, 3, 256, 256) # train with spynet updated outputs = restorer.train_step(data_batch, optimizer) assert isinstance(outputs, dict) assert isinstance(outputs['log_vars'], dict) assert isinstance(outputs['log_vars']['loss_pix'], float) assert outputs['num_samples'] == 1 assert torch.equal(outputs['results']['lq'], data_batch['lq'].cpu()) assert torch.equal(outputs['results']['gt'], data_batch['gt'].cpu()) assert torch.is_tensor(outputs['results']['output']) assert outputs['results']['output'].size() == (1, 5, 3, 256, 256) # test forward_dummy with torch.no_grad(): output = restorer.forward_dummy(data_batch['lq']) assert torch.is_tensor(output) assert output.size() == (1, 5, 3, 256, 256) # forward_test with torch.no_grad(): outputs = restorer(**data_batch, test_mode=True) assert torch.equal(outputs['lq'], data_batch['lq'].cpu()) assert torch.equal(outputs['gt'], data_batch['gt'].cpu()) assert torch.is_tensor(outputs['output']) assert outputs['output'].size() == (1, 5, 3, 256, 256) with torch.no_grad(): outputs = restorer(inputs, test_mode=True) assert torch.equal(outputs['lq'], data_batch['lq'].cpu()) assert torch.is_tensor(outputs['output']) assert outputs['output'].size() == (1, 5, 3, 256, 256) # test with metric and save image train_cfg = mmcv.ConfigDict(fix_iter=1) test_cfg = dict(metrics=('PSNR', 'SSIM'), crop_border=0) test_cfg = mmcv.Config(test_cfg) data_batch = { 'lq': inputs, 'gt': targets, 'meta': [{ 'gt_path': 'fake_path/fake_name.png', 'key': '000' }] } restorer = build_model(model_cfg, train_cfg=train_cfg, test_cfg=test_cfg) if torch.cuda.is_available(): restorer = restorer.cuda() with pytest.raises(AssertionError): # evaluation with metrics must have gt images restorer(lq=inputs, test_mode=True) with tempfile.TemporaryDirectory() as tmpdir: outputs = restorer(**data_batch, test_mode=True, save_image=True, save_path=tmpdir, iteration=None) assert isinstance(outputs, dict) assert isinstance(outputs['eval_result'], dict) assert isinstance(outputs['eval_result']['PSNR'], float) assert isinstance(outputs['eval_result']['SSIM'], float) outputs = restorer(**data_batch, test_mode=True, save_image=True, save_path=tmpdir, iteration=100) assert isinstance(outputs, dict) assert isinstance(outputs['eval_result'], dict) assert isinstance(outputs['eval_result']['PSNR'], float) assert isinstance(outputs['eval_result']['SSIM'], float) with pytest.raises(ValueError): # iteration should be number or None restorer(**data_batch, test_mode=True, save_image=True, save_path=tmpdir, iteration='100')
def test_basic_restorer(): model_cfg = dict(type='BasicRestorer', generator=dict(type='MSRResNet', in_channels=3, out_channels=3, mid_channels=4, num_blocks=1, upscale_factor=4), pixel_loss=dict(type='L1Loss', loss_weight=1.0, reduction='mean')) train_cfg = None test_cfg = None # build restorer restorer = build_model(model_cfg, train_cfg=train_cfg, test_cfg=test_cfg) # test attributes assert restorer.__class__.__name__ == 'BasicRestorer' assert isinstance(restorer.generator, MSRResNet) assert isinstance(restorer.pixel_loss, L1Loss) # prepare data inputs = torch.rand(1, 3, 2, 2) targets = torch.rand(1, 3, 8, 8) data_batch = {'lq': inputs, 'gt': targets} # prepare optimizer optim_cfg = dict(type='Adam', lr=2e-4, betas=(0.9, 0.999)) optimizer = { 'generator': obj_from_dict(optim_cfg, torch.optim, dict(params=restorer.parameters())) } # test forward train outputs = restorer(**data_batch, test_mode=False) assert isinstance(outputs, dict) assert isinstance(outputs['losses'], dict) assert isinstance(outputs['losses']['loss_pix'], torch.FloatTensor) assert outputs['num_samples'] == 1 assert torch.equal(outputs['results']['lq'], data_batch['lq']) assert torch.equal(outputs['results']['gt'], data_batch['gt']) assert torch.is_tensor(outputs['results']['output']) assert outputs['results']['output'].size() == (1, 3, 8, 8) # test forward_test with torch.no_grad(): outputs = restorer(**data_batch, test_mode=True) assert torch.equal(outputs['lq'], data_batch['lq']) assert torch.is_tensor(outputs['output']) assert outputs['output'].size() == (1, 3, 8, 8) # test forward_dummy with torch.no_grad(): output = restorer.forward_dummy(data_batch['lq']) assert torch.is_tensor(output) assert output.size() == (1, 3, 8, 8) # test train_step outputs = restorer.train_step(data_batch, optimizer) assert isinstance(outputs, dict) assert isinstance(outputs['log_vars'], dict) assert isinstance(outputs['log_vars']['loss_pix'], float) assert outputs['num_samples'] == 1 assert torch.equal(outputs['results']['lq'], data_batch['lq']) assert torch.equal(outputs['results']['gt'], data_batch['gt']) assert torch.is_tensor(outputs['results']['output']) assert outputs['results']['output'].size() == (1, 3, 8, 8) # test train_step and forward_test (gpu) if torch.cuda.is_available(): restorer = restorer.cuda() optimizer['generator'] = obj_from_dict( optim_cfg, torch.optim, dict(params=restorer.parameters())) data_batch = {'lq': inputs.cuda(), 'gt': targets.cuda()} # test forward train outputs = restorer(**data_batch, test_mode=False) assert isinstance(outputs, dict) assert isinstance(outputs['losses'], dict) assert isinstance(outputs['losses']['loss_pix'], torch.cuda.FloatTensor) assert outputs['num_samples'] == 1 assert torch.equal(outputs['results']['lq'], data_batch['lq'].cpu()) assert torch.equal(outputs['results']['gt'], data_batch['gt'].cpu()) assert torch.is_tensor(outputs['results']['output']) assert outputs['results']['output'].size() == (1, 3, 8, 8) # forward_test with torch.no_grad(): outputs = restorer(**data_batch, test_mode=True) assert torch.equal(outputs['lq'], data_batch['lq'].cpu()) assert torch.is_tensor(outputs['output']) assert outputs['output'].size() == (1, 3, 8, 8) # train_step outputs = restorer.train_step(data_batch, optimizer) assert isinstance(outputs, dict) assert isinstance(outputs['log_vars'], dict) assert isinstance(outputs['log_vars']['loss_pix'], float) assert outputs['num_samples'] == 1 assert torch.equal(outputs['results']['lq'], data_batch['lq'].cpu()) assert torch.equal(outputs['results']['gt'], data_batch['gt'].cpu()) assert torch.is_tensor(outputs['results']['output']) assert outputs['results']['output'].size() == (1, 3, 8, 8) # test with metric and save image test_cfg = dict(metrics=('PSNR', 'SSIM'), crop_border=0) test_cfg = mmcv.Config(test_cfg) data_batch = { 'lq': inputs, 'gt': targets, 'meta': [{ 'lq_path': 'fake_path/fake_name.png' }] } restorer = build_model(model_cfg, train_cfg=train_cfg, test_cfg=test_cfg) with pytest.raises(AssertionError): # evaluation with metrics must have gt images restorer(lq=inputs, test_mode=True) with tempfile.TemporaryDirectory() as tmpdir: outputs = restorer(**data_batch, test_mode=True, save_image=True, save_path=tmpdir, iteration=None) assert isinstance(outputs, dict) assert isinstance(outputs['eval_result'], dict) assert isinstance(outputs['eval_result']['PSNR'], float) assert isinstance(outputs['eval_result']['SSIM'], float) outputs = restorer(**data_batch, test_mode=True, save_image=True, save_path=tmpdir, iteration=100) assert isinstance(outputs, dict) assert isinstance(outputs['eval_result'], dict) assert isinstance(outputs['eval_result']['PSNR'], float) assert isinstance(outputs['eval_result']['SSIM'], float) with pytest.raises(ValueError): # iteration should be number or None restorer(**data_batch, test_mode=True, save_image=True, save_path=tmpdir, iteration='100')
def test_yolact_head_loss(): """Tests yolact head losses when truth is empty and non-empty.""" s = 550 img_metas = [{ 'img_shape': (s, s, 3), 'scale_factor': 1, 'pad_shape': (s, s, 3) }] train_cfg = mmcv.Config( dict( assigner=dict( type='MaxIoUAssigner', pos_iou_thr=0.5, neg_iou_thr=0.4, min_pos_iou=0., ignore_iof_thr=-1, gt_max_assign_all=False), smoothl1_beta=1., allowed_border=-1, pos_weight=-1, neg_pos_ratio=3, debug=False, min_gt_box_wh=[4.0, 4.0])) bbox_head = YOLACTHead( num_classes=80, in_channels=256, feat_channels=256, anchor_generator=dict( type='AnchorGenerator', octave_base_scale=3, scales_per_octave=1, base_sizes=[8, 16, 32, 64, 128], ratios=[0.5, 1.0, 2.0], strides=[550.0 / x for x in [69, 35, 18, 9, 5]], centers=[(550 * 0.5 / x, 550 * 0.5 / x) for x in [69, 35, 18, 9, 5]]), bbox_coder=dict( type='DeltaXYWHBBoxCoder', target_means=[.0, .0, .0, .0], target_stds=[0.1, 0.1, 0.2, 0.2]), loss_cls=dict( type='CrossEntropyLoss', use_sigmoid=False, reduction='none', loss_weight=1.0), loss_bbox=dict(type='SmoothL1Loss', beta=1.0, loss_weight=1.5), num_head_convs=1, num_protos=32, use_ohem=True, train_cfg=train_cfg) segm_head = YOLACTSegmHead( in_channels=256, num_classes=80, loss_segm=dict( type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0)) mask_head = YOLACTProtonet( num_classes=80, in_channels=256, num_protos=32, max_masks_to_train=100, loss_mask_weight=6.125) feat = [ torch.rand(1, 256, feat_size, feat_size) for feat_size in [69, 35, 18, 9, 5] ] cls_score, bbox_pred, coeff_pred = bbox_head.forward(feat) # Test that empty ground truth encourages the network to predict background gt_bboxes = [torch.empty((0, 4))] gt_labels = [torch.LongTensor([])] gt_masks = [torch.empty((0, 550, 550))] gt_bboxes_ignore = None empty_gt_losses, sampling_results = bbox_head.loss( cls_score, bbox_pred, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore=gt_bboxes_ignore) # When there is no truth, the cls loss should be nonzero but there should # be no box loss. empty_cls_loss = sum(empty_gt_losses['loss_cls']) empty_box_loss = sum(empty_gt_losses['loss_bbox']) assert empty_cls_loss.item() > 0, 'cls loss should be non-zero' assert empty_box_loss.item() == 0, ( 'there should be no box loss when there are no true boxes') # Test segm head and mask head segm_head_outs = segm_head(feat[0]) empty_segm_loss = segm_head.loss(segm_head_outs, gt_masks, gt_labels) mask_pred = mask_head(feat[0], coeff_pred, gt_bboxes, img_metas, sampling_results) empty_mask_loss = mask_head.loss(mask_pred, gt_masks, gt_bboxes, img_metas, sampling_results) # When there is no truth, the segm and mask loss should be zero. empty_segm_loss = sum(empty_segm_loss['loss_segm']) empty_mask_loss = sum(empty_mask_loss['loss_mask']) assert empty_segm_loss.item() == 0, ( 'there should be no segm loss when there are no true boxes') assert empty_mask_loss == 0, ( 'there should be no mask loss when there are no true boxes') # When truth is non-empty then cls, box, mask, segm loss should be # nonzero for random inputs. gt_bboxes = [ torch.Tensor([[23.6667, 23.8757, 238.6326, 151.8874]]), ] gt_labels = [torch.LongTensor([2])] gt_masks = [(torch.rand((1, 550, 550)) > 0.5).float()] one_gt_losses, sampling_results = bbox_head.loss( cls_score, bbox_pred, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore=gt_bboxes_ignore) one_gt_cls_loss = sum(one_gt_losses['loss_cls']) one_gt_box_loss = sum(one_gt_losses['loss_bbox']) assert one_gt_cls_loss.item() > 0, 'cls loss should be non-zero' assert one_gt_box_loss.item() > 0, 'box loss should be non-zero' one_gt_segm_loss = segm_head.loss(segm_head_outs, gt_masks, gt_labels) mask_pred = mask_head(feat[0], coeff_pred, gt_bboxes, img_metas, sampling_results) one_gt_mask_loss = mask_head.loss(mask_pred, gt_masks, gt_bboxes, img_metas, sampling_results) one_gt_segm_loss = sum(one_gt_segm_loss['loss_segm']) one_gt_mask_loss = sum(one_gt_mask_loss['loss_mask']) assert one_gt_segm_loss.item() > 0, 'segm loss should be non-zero' assert one_gt_mask_loss.item() > 0, 'mask loss should be non-zero'
def test_atss_head_loss(): """Tests atss head loss when truth is empty and non-empty.""" s = 256 img_metas = [{ 'img_shape': (s, s, 3), 'scale_factor': 1, 'pad_shape': (s, s, 3) }] train_cfg = mmcv.Config( dict(assigner=dict(type='ATSSAssigner', topk=9), allowed_border=-1, pos_weight=-1, debug=False)) self = ATSSHead(num_classes=4, in_channels=1, train_cfg=train_cfg, anchor_generator=dict(type='AnchorGenerator', ratios=[1.0], octave_base_scale=8, scales_per_octave=1, strides=[8, 16, 32, 64, 128]), loss_cls=dict(type='FocalLoss', use_sigmoid=True, gamma=2.0, alpha=0.25, loss_weight=1.0), loss_bbox=dict(type='GIoULoss', loss_weight=2.0)) feat = [ torch.rand(1, 1, s // feat_size, s // feat_size) for feat_size in [4, 8, 16, 32, 64] ] cls_scores, bbox_preds, centernesses = self.forward(feat) # Test that empty ground truth encourages the network to predict background gt_bboxes = [torch.empty((0, 4))] gt_labels = [torch.LongTensor([])] gt_bboxes_ignore = None empty_gt_losses = self.loss(cls_scores, bbox_preds, centernesses, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore) # When there is no truth, the cls loss should be nonzero but there should # be no box loss. empty_cls_loss = sum(empty_gt_losses['loss_cls']) empty_box_loss = sum(empty_gt_losses['loss_bbox']) empty_centerness_loss = sum(empty_gt_losses['loss_centerness']) assert empty_cls_loss.item() > 0, 'cls loss should be non-zero' assert empty_box_loss.item() == 0, ( 'there should be no box loss when there are no true boxes') assert empty_centerness_loss.item() == 0, ( 'there should be no centerness loss when there are no true boxes') # When truth is non-empty then both cls and box loss should be nonzero for # random inputs gt_bboxes = [ torch.Tensor([[23.6667, 23.8757, 238.6326, 151.8874]]), ] gt_labels = [torch.LongTensor([2])] one_gt_losses = self.loss(cls_scores, bbox_preds, centernesses, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore) onegt_cls_loss = sum(one_gt_losses['loss_cls']) onegt_box_loss = sum(one_gt_losses['loss_bbox']) onegt_centerness_loss = sum(one_gt_losses['loss_centerness']) assert onegt_cls_loss.item() > 0, 'cls loss should be non-zero' assert onegt_box_loss.item() > 0, 'box loss should be non-zero' assert onegt_centerness_loss.item() > 0, ( 'centerness loss should be non-zero')
dataset = [] for img_path in img_paths: # Image name structure framegta_2862738_camid_2_pid_2733.png img_name = osp.basename(img_path) dataset.append(img_name) return dataset if __name__ == "__main__": feature_extractor_cfg = { "feature_extractor": { "reid_strong_baseline_config": "/home/philipp/Dokumente/masterarbeit/JTA-MTMCT-Mod/deep_sort_mc/feature_extractors/reid-strong-baseline/configs/softmax_triplet.yml", "checkpoint_file": "/media/philipp/philippkoehl_ssd/work_dirs/feature_extractor/strong_reid_baseline/resnet50_model_reid_GTA_softmax_triplet.pth", "device": "cuda:0", "visible_device": "0" } } feature_ext_cfg = mmcv.Config(feature_extractor_cfg) vrq = Visualize_reid_query( reid_dataset_folder= "/media/philipp/philippkoehl_ssd/reid_camid_GTA_22.07.2019", feature_extractor_cfg=feature_ext_cfg, work_dirs="/media/philipp/philippkoehl_ssd/work_dirs") vrq.draw_gallery_query()
def test_stark_head_loss(): """Tests stark head loss when truth is non-empty.""" head_cfg = dict( num_query=1, transformer=dict( type='StarkTransformer', encoder=dict(type='DetrTransformerEncoder', num_layers=6, transformerlayers=dict( type='BaseTransformerLayer', attn_cfgs=[ dict(type='MultiheadAttention', embed_dims=16, num_heads=8, attn_drop=0.1, dropout_layer=dict(type='Dropout', drop_prob=0.1)) ], ffn_cfgs=dict(feedforward_channels=16, embed_dims=16, ffn_drop=0.1), operation_order=('self_attn', 'norm', 'ffn', 'norm'))), decoder=dict(type='DetrTransformerDecoder', return_intermediate=False, num_layers=6, transformerlayers=dict( type='BaseTransformerLayer', attn_cfgs=dict(type='MultiheadAttention', embed_dims=16, num_heads=8, attn_drop=0.1, dropout_layer=dict(type='Dropout', drop_prob=0.1)), ffn_cfgs=dict(feedforward_channels=16, embed_dims=16, ffn_drop=0.1), operation_order=('self_attn', 'norm', 'cross_attn', 'norm', 'ffn', 'norm'))), ), positional_encoding=dict(type='SinePositionalEncoding', num_feats=8, normalize=True), bbox_head=dict(type='CornerPredictorHead', inplanes=16, channel=16, feat_size=20, stride=16), loss_bbox=dict(type='L1Loss', loss_weight=5.0), loss_iou=dict(type='GIoULoss', loss_weight=2.0), test_cfg=dict(search_factor=5.0, search_size=320, template_factor=2.0, template_size=128, update_intervals=[200])) cfg = mmcv.Config(head_cfg) self = StarkHead(**cfg) head_inputs = [ dict(feat=(torch.rand(1, 16, 8, 8), ), mask=torch.zeros(1, 128, 128, dtype=bool)), dict(feat=(torch.rand(1, 16, 8, 8), ), mask=torch.zeros(1, 128, 128, dtype=bool)), dict(feat=(torch.rand(1, 16, 20, 20), ), mask=torch.zeros(1, 320, 320, dtype=bool)) ] track_results = self.forward(head_inputs) gt_bboxes = [ torch.Tensor([[0., 23.6667, 23.8757, 238.6326, 151.8874]]), ] gt_labels = [ torch.Tensor([[0., 1]]), ] bboxes_losses = self.loss(track_results, gt_bboxes, gt_labels, (320, 320)) assert bboxes_losses['loss_iou'] >= 0, 'iou loss should be' 'non-zero or zero' assert bboxes_losses[ 'loss_bbox'] >= 0, 'bbox loss should be non-zero or zero' head_cfg.update( dict(cls_head=dict(type='ScoreHead', input_dim=16, hidden_dim=16, output_dim=1, num_layers=3, use_bn=False), frozen_module=['transformer', 'bbox_head'], loss_cls=dict(type='CrossEntropyLoss', use_sigmoid=True))) cfg = mmcv.Config(head_cfg) self = StarkHead(**cfg) track_results = self.forward(head_inputs) bboxes_losses = self.loss(track_results, gt_bboxes, gt_labels, (320, 320)) assert bboxes_losses['loss_cls'] >= 0, 'iou loss should be' 'non-zero or zero'
def test_anchor_head_loss(): """ Tests anchor head loss when truth is empty and non-empty """ self = AnchorHead(num_classes=4, in_channels=1) s = 256 img_metas = [{ "img_shape": (s, s, 3), "scale_factor": 1, "pad_shape": (s, s, 3) }] cfg = mmcv.Config({ "assigner": { "type": "MaxIoUAssigner", "pos_iou_thr": 0.7, "neg_iou_thr": 0.3, "min_pos_iou": 0.3, "ignore_iof_thr": -1, }, "sampler": { "type": "RandomSampler", "num": 256, "pos_fraction": 0.5, "neg_pos_ub": -1, "add_gt_as_proposals": False, }, "allowed_border": 0, "pos_weight": -1, "debug": False, }) # Anchor head expects a multiple levels of features per image feat = [ torch.rand(1, 1, s // (2**(i + 2)), s // (2**(i + 2))) for i in range(len(self.anchor_generators)) ] cls_scores, bbox_preds = self.forward(feat) # Test that empty ground truth encourages the network to predict background gt_bboxes = [torch.empty((0, 4))] gt_labels = [torch.LongTensor([])] gt_bboxes_ignore = None empty_gt_losses = self.loss(cls_scores, bbox_preds, gt_bboxes, gt_labels, img_metas, cfg, gt_bboxes_ignore) # When there is no truth, the cls loss should be nonzero but there should # be no box loss. empty_cls_loss = sum(empty_gt_losses["loss_cls"]) empty_box_loss = sum(empty_gt_losses["loss_bbox"]) assert empty_cls_loss.item() > 0, "cls loss should be non-zero" assert (empty_box_loss.item() == 0 ), "there should be no box loss when there are no true boxes" # When truth is non-empty then both cls and box loss should be nonzero for # random inputs gt_bboxes = [torch.Tensor([[23.6667, 23.8757, 238.6326, 151.8874]])] gt_labels = [torch.LongTensor([2])] one_gt_losses = self.loss(cls_scores, bbox_preds, gt_bboxes, gt_labels, img_metas, cfg, gt_bboxes_ignore) onegt_cls_loss = sum(one_gt_losses["loss_cls"]) onegt_box_loss = sum(one_gt_losses["loss_bbox"]) assert onegt_cls_loss.item() > 0, "cls loss should be non-zero" assert onegt_box_loss.item() > 0, "box loss should be non-zero"
def test_cain(): model_cfg = dict( type='CAIN', generator=dict(type='CAINNet'), pixel_loss=dict(type='L1Loss', loss_weight=1.0, reduction='mean')) train_cfg = None test_cfg = None # build restorer restorer = build_model(model_cfg, train_cfg=train_cfg, test_cfg=test_cfg) # test attributes assert restorer.__class__.__name__ == 'CAIN' assert isinstance(restorer.generator, CAINNet) assert isinstance(restorer.pixel_loss, L1Loss) # prepare data inputs = torch.rand(1, 2, 3, 128, 128) target = torch.rand(1, 3, 128, 128) data_batch = {'inputs': inputs, 'target': target, 'meta': [{'key': '001'}]} # prepare optimizer optim_cfg = dict(type='Adam', lr=2e-4, betas=(0.9, 0.999)) optimizer = { 'generator': obj_from_dict(optim_cfg, torch.optim, dict(params=restorer.parameters())) } # test forward_test with torch.no_grad(): outputs = restorer.forward_test(**data_batch) assert torch.equal(outputs['inputs'], data_batch['inputs']) assert torch.is_tensor(outputs['output']) assert outputs['output'].size() == (1, 3, 128, 128) # test train_step outputs = restorer.train_step(data_batch, optimizer) assert isinstance(outputs, dict) assert isinstance(outputs['log_vars'], dict) assert isinstance(outputs['log_vars']['loss_pix'], float) assert outputs['num_samples'] == 1 assert torch.equal(outputs['results']['inputs'], data_batch['inputs']) assert torch.equal(outputs['results']['target'], data_batch['target']) assert torch.is_tensor(outputs['results']['output']) assert outputs['results']['output'].size() == (1, 3, 128, 128) # test train_step and forward_test (gpu) if torch.cuda.is_available(): restorer = restorer.cuda() optimizer['generator'] = obj_from_dict( optim_cfg, torch.optim, dict(params=restorer.parameters())) data_batch = { 'inputs': inputs.cuda(), 'target': target.cuda(), 'meta': [{ 'key': '001' }] } # forward_test with torch.no_grad(): outputs = restorer.forward_test(**data_batch) assert torch.equal(outputs['inputs'], data_batch['inputs'].cpu()) assert torch.is_tensor(outputs['output']) assert outputs['output'].size() == (1, 3, 128, 128) # train_step outputs = restorer.train_step(data_batch, optimizer) assert isinstance(outputs, dict) assert isinstance(outputs['log_vars'], dict) assert isinstance(outputs['log_vars']['loss_pix'], float) assert outputs['num_samples'] == 1 assert torch.equal(outputs['results']['inputs'], data_batch['inputs'].cpu()) assert torch.equal(outputs['results']['target'], data_batch['target'].cpu()) assert torch.is_tensor(outputs['results']['output']) assert outputs['results']['output'].size() == (1, 3, 128, 128) # test with metric and save image test_cfg = dict(metrics=('PSNR', 'SSIM'), crop_border=0) test_cfg = mmcv.Config(test_cfg) data_batch = { 'inputs': inputs, 'target': target, 'meta': [{ 'key': 'fake_path/fake_name' }] } restorer = build_model(model_cfg, train_cfg=train_cfg, test_cfg=test_cfg) with pytest.raises(AssertionError): # evaluation with metrics must have target images restorer(inputs=inputs, test_mode=True) with tempfile.TemporaryDirectory() as tmpdir: outputs = restorer( **data_batch, test_mode=True, save_image=True, save_path=tmpdir, iteration=None) assert isinstance(outputs, dict) assert isinstance(outputs['eval_result'], dict) assert isinstance(outputs['eval_result']['PSNR'], float) assert isinstance(outputs['eval_result']['SSIM'], float) outputs = restorer( **data_batch, test_mode=True, save_image=True, save_path=tmpdir, iteration=100) assert isinstance(outputs, dict) assert isinstance(outputs['eval_result'], dict) assert isinstance(outputs['eval_result']['PSNR'], float) assert isinstance(outputs['eval_result']['SSIM'], float)
def test_tdan_model(): model_cfg = dict( type='TDAN', generator=dict(type='TDANNet', in_channels=3, mid_channels=64, out_channels=3, num_blocks_before_align=5, num_blocks_after_align=10), pixel_loss=dict(type='MSELoss', loss_weight=1.0, reduction='sum'), lq_pixel_loss=dict(type='MSELoss', loss_weight=1.0, reduction='sum'), ) train_cfg = None test_cfg = None # build restorer restorer = build_model(model_cfg, train_cfg=train_cfg, test_cfg=test_cfg) # test attributes assert restorer.__class__.__name__ == 'TDAN' assert isinstance(restorer.generator, TDANNet) assert isinstance(restorer.pixel_loss, MSELoss) # prepare data inputs = torch.rand(1, 5, 3, 8, 8) targets = torch.rand(1, 3, 32, 32) # test train_step and forward_test (gpu) if torch.cuda.is_available(): restorer = restorer.cuda() data_batch = {'lq': inputs.cuda(), 'gt': targets.cuda()} # prepare optimizer optim_cfg = dict(type='Adam', lr=2e-4, betas=(0.9, 0.999)) optimizer = { 'generator': obj_from_dict( optim_cfg, torch.optim, dict(params=getattr(restorer, 'generator').parameters())) } # train_step outputs = restorer.train_step(data_batch, optimizer) assert isinstance(outputs, dict) assert isinstance(outputs['log_vars'], dict) assert isinstance(outputs['log_vars']['loss_pix'], float) assert outputs['num_samples'] == 1 assert torch.equal(outputs['results']['lq'], data_batch['lq'].cpu()) assert torch.equal(outputs['results']['gt'], data_batch['gt'].cpu()) assert torch.is_tensor(outputs['results']['output']) assert outputs['results']['output'].size() == (1, 3, 32, 32) # test forward_dummy with torch.no_grad(): output = restorer.forward_dummy(data_batch['lq']) assert isinstance(output, tuple) assert torch.is_tensor(output[0]) assert output[0].size() == (1, 3, 32, 32) assert torch.is_tensor(output[1]) assert output[1].size() == (1, 5, 3, 8, 8) # forward_test with torch.no_grad(): outputs = restorer(**data_batch, test_mode=True) assert torch.equal(outputs['lq'], data_batch['lq'].cpu()) assert torch.equal(outputs['gt'], data_batch['gt'].cpu()) assert torch.is_tensor(outputs['output']) assert outputs['output'].size() == (1, 3, 32, 32) with torch.no_grad(): outputs = restorer(inputs.cuda(), test_mode=True) assert torch.equal(outputs['lq'], data_batch['lq'].cpu()) assert torch.is_tensor(outputs['output']) assert outputs['output'].size() == (1, 3, 32, 32) # test with metric and save image if torch.cuda.is_available(): train_cfg = mmcv.ConfigDict(tsa_iter=1) test_cfg = dict(metrics=('PSNR', 'SSIM'), crop_border=0) test_cfg = mmcv.Config(test_cfg) data_batch = { 'lq': inputs.cuda(), 'gt': targets.cuda(), 'meta': [{ 'gt_path': 'fake_path/fake_name.png', 'key': '000/00000000' }] } restorer = build_model(model_cfg, train_cfg=train_cfg, test_cfg=test_cfg).cuda() with pytest.raises(AssertionError): # evaluation with metrics must have gt images restorer(lq=inputs.cuda(), test_mode=True) with tempfile.TemporaryDirectory() as tmpdir: outputs = restorer(**data_batch, test_mode=True, save_image=True, save_path=tmpdir, iteration=None) assert isinstance(outputs, dict) assert isinstance(outputs['eval_result'], dict) assert isinstance(outputs['eval_result']['PSNR'], float) assert isinstance(outputs['eval_result']['SSIM'], float) outputs = restorer(**data_batch, test_mode=True, save_image=True, save_path=tmpdir, iteration=100) assert isinstance(outputs, dict) assert isinstance(outputs['eval_result'], dict) assert isinstance(outputs['eval_result']['PSNR'], float) assert isinstance(outputs['eval_result']['SSIM'], float) with pytest.raises(ValueError): # iteration should be number or None restorer(**data_batch, test_mode=True, save_image=True, save_path=tmpdir, iteration='100')
def test_fsaf_head_loss(): """Tests anchor head loss when truth is empty and non-empty.""" s = 256 img_metas = [{ 'img_shape': (s, s, 3), 'scale_factor': 1, 'pad_shape': (s, s, 3) }] cfg = dict(reg_decoded_bbox=True, anchor_generator=dict(type='AnchorGenerator', octave_base_scale=1, scales_per_octave=1, ratios=[1.0], strides=[8, 16, 32, 64, 128]), bbox_coder=dict(type='TBLRBBoxCoder', normalizer=4.0), loss_cls=dict(type='FocalLoss', use_sigmoid=True, gamma=2.0, alpha=0.25, loss_weight=1.0, reduction='none'), loss_bbox=dict(type='IoULoss', eps=1e-6, loss_weight=1.0, reduction='none')) train_cfg = mmcv.Config( dict(assigner=dict(type='CenterRegionAssigner', pos_scale=0.2, neg_scale=0.2, min_pos_iof=0.01), allowed_border=-1, pos_weight=-1, debug=False)) head = FSAFHead(num_classes=4, in_channels=1, train_cfg=train_cfg, **cfg) if torch.cuda.is_available(): head.cuda() # FSAF head expects a multiple levels of features per image feat = [ torch.rand(1, 1, s // (2**(i + 2)), s // (2**(i + 2))).cuda() for i in range(len(head.anchor_generator.strides)) ] cls_scores, bbox_preds = head.forward(feat) gt_bboxes_ignore = None # When truth is non-empty then both cls and box loss should be nonzero # for random inputs gt_bboxes = [ torch.Tensor([[23.6667, 23.8757, 238.6326, 151.8874]]).cuda(), ] gt_labels = [torch.LongTensor([2]).cuda()] one_gt_losses = head.loss(cls_scores, bbox_preds, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore) onegt_cls_loss = sum(one_gt_losses['loss_cls']) onegt_box_loss = sum(one_gt_losses['loss_bbox']) assert onegt_cls_loss.item() > 0, 'cls loss should be non-zero' assert onegt_box_loss.item() > 0, 'box loss should be non-zero' # Test that empty ground truth encourages the network to predict bkg gt_bboxes = [torch.empty((0, 4)).cuda()] gt_labels = [torch.LongTensor([]).cuda()] empty_gt_losses = head.loss(cls_scores, bbox_preds, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore) # When there is no truth, the cls loss should be nonzero but there # should be no box loss. empty_cls_loss = sum(empty_gt_losses['loss_cls']) empty_box_loss = sum(empty_gt_losses['loss_bbox']) assert empty_cls_loss.item() > 0, 'cls loss should be non-zero' assert empty_box_loss.item() == 0, ( 'there should be no box loss when there are no true boxes')
def test_recognizer_wrapper(): try: import onnxruntime as ort # noqa: F401 import tensorrt as trt from mmcv.tensorrt import (onnx2trt, save_trt_engine) except ImportError: pytest.skip('ONNXRuntime or TensorRT is not available.') cfg = dict( label_convertor=dict( type='CTCConvertor', dict_type='DICT36', with_unknown=False, lower=True), model=dict( type='CRNNNet', preprocessor=None, backbone=dict( type='VeryDeepVgg', leaky_relu=False, input_channels=1), encoder=None, decoder=dict(type='CRNNDecoder', in_channels=512, rnn_flag=True), loss=dict(type='CTCLoss'), label_convertor=dict( type='CTCConvertor', dict_type='DICT36', with_unknown=False, lower=True), pretrained=None), train_cfg=None, test_cfg=None) cfg = mmcv.Config(cfg) pytorch_model = build_detector(cfg.model, None, None) # prepare data inputs = torch.rand(1, 1, 32, 32) img_metas = [{ 'img_shape': [1, 1, 32, 32], 'ori_shape': [1, 1, 32, 32], 'pad_shape': [1, 1, 32, 32], 'filename': None, 'scale_factor': np.array([1, 1, 1, 1]) }] pytorch_model.forward = partial( pytorch_model.forward, img_metas=img_metas, return_loss=False, rescale=True) with tempfile.TemporaryDirectory() as tmpdirname: onnx_path = f'{tmpdirname}/tmp.onnx' with torch.no_grad(): torch.onnx.export( pytorch_model, inputs, onnx_path, input_names=['input'], output_names=['output'], export_params=True, keep_initializers_as_inputs=False, verbose=False, opset_version=11) # TensorRT part def get_GiB(x: int): """return x GiB.""" return x * (1 << 30) trt_path = onnx_path.replace('.onnx', '.trt') min_shape = [1, 1, 32, 32] max_shape = [1, 1, 32, 32] # create trt engine and wrapper opt_shape_dict = {'input': [min_shape, min_shape, max_shape]} max_workspace_size = get_GiB(1) trt_engine = onnx2trt( onnx_path, opt_shape_dict, log_level=trt.Logger.ERROR, fp16_mode=False, max_workspace_size=max_workspace_size) save_trt_engine(trt_engine, trt_path) print(f'Successfully created TensorRT engine: {trt_path}') wrap_onnx = ONNXRuntimeRecognizer(onnx_path, cfg, 0) wrap_trt = TensorRTRecognizer(trt_path, cfg, 0) assert isinstance(wrap_onnx, ONNXRuntimeRecognizer) assert isinstance(wrap_trt, TensorRTRecognizer) with torch.no_grad(): onnx_outputs = wrap_onnx.simple_test(inputs, img_metas, rescale=False) trt_outputs = wrap_onnx.simple_test(inputs, img_metas, rescale=False) assert isinstance(onnx_outputs[0], dict) assert isinstance(trt_outputs[0], dict) assert 'text' in onnx_outputs[0] assert 'text' in trt_outputs[0]
def test_pisa_roi_head_loss(): """Tests pisa roi head loss when truth is empty and non-empty.""" train_cfg = mmcv.Config( dict(assigner=dict(type='MaxIoUAssigner', pos_iou_thr=0.7, neg_iou_thr=0.3, min_pos_iou=0.3, match_low_quality=True, ignore_iof_thr=-1), sampler=dict(type='ScoreHLRSampler', num=4, pos_fraction=0.25, neg_pos_ub=-1, add_gt_as_proposals=True, k=0.5, bias=0.), isr=dict(k=2., bias=0.), carl=dict(k=1., bias=0.2), allowed_border=0, pos_weight=-1, debug=False)) bbox_roi_extractor = dict(type='SingleRoIExtractor', roi_layer=dict(type='RoIAlign', out_size=7, sample_num=0), out_channels=1, featmap_strides=[1]) bbox_head = dict(type='Shared2FCBBoxHead', in_channels=1, fc_out_channels=2, roi_feat_size=7, num_classes=4, bbox_coder=dict(type='DeltaXYWHBBoxCoder', target_means=[0., 0., 0., 0.], target_stds=[0.1, 0.1, 0.2, 0.2]), reg_class_agnostic=False, loss_cls=dict(type='CrossEntropyLoss', use_sigmoid=False, loss_weight=1.0), loss_bbox=dict(type='L1Loss', loss_weight=1.0)) self = PISARoIHead(bbox_roi_extractor, bbox_head, train_cfg=train_cfg) s = 256 img_metas = [{ 'img_shape': (s, s, 3), 'scale_factor': 1, 'pad_shape': (s, s, 3) }] # Anchor head expects a multiple levels of features per image feat = [ torch.rand(1, 1, s // (2**(i + 2)), s // (2**(i + 2))) for i in range(1) ] proposal_list = [ torch.Tensor([[22.6667, 22.8757, 238.6326, 151.8874], [0, 3, 5, 7]]) ] # Test that empty ground truth encourages the network to predict background gt_bboxes = [torch.empty((0, 4))] gt_labels = [torch.LongTensor([])] gt_bboxes_ignore = None empty_gt_losses = self.forward_train(feat, img_metas, proposal_list, gt_bboxes, gt_labels, gt_bboxes_ignore) # When there is no truth, the cls loss should be nonzero but there should # be no box loss. empty_cls_loss = empty_gt_losses['loss_cls'].sum() empty_box_loss = empty_gt_losses['loss_bbox'].sum() assert empty_cls_loss.item() > 0, 'cls loss should be non-zero' assert empty_box_loss.item() == 0, ( 'there should be no box loss when there are no true boxes') # When truth is non-empty then both cls and box loss should be nonzero for # random inputs gt_bboxes = [ torch.Tensor([[23.6667, 23.8757, 238.6326, 151.8874]]), ] gt_labels = [torch.LongTensor([2])] one_gt_losses = self.forward_train(feat, img_metas, proposal_list, gt_bboxes, gt_labels, gt_bboxes_ignore) onegt_cls_loss = one_gt_losses['loss_cls'].sum() onegt_box_loss = one_gt_losses['loss_bbox'].sum() assert onegt_cls_loss.item() > 0, 'cls loss should be non-zero' assert onegt_box_loss.item() > 0, 'box loss should be non-zero'
def test_detector_wrapper(): try: import onnxruntime as ort # noqa: F401 import tensorrt as trt from mmcv.tensorrt import (onnx2trt, save_trt_engine) except ImportError: pytest.skip('ONNXRuntime or TensorRT is not available.') cfg = dict( model=dict( type='DBNet', backbone=dict( type='ResNet', depth=18, num_stages=4, out_indices=(0, 1, 2, 3), frozen_stages=-1, norm_cfg=dict(type='BN', requires_grad=True), init_cfg=dict( type='Pretrained', checkpoint='torchvision://resnet18'), norm_eval=False, style='caffe'), neck=dict( type='FPNC', in_channels=[64, 128, 256, 512], lateral_channels=256), bbox_head=dict( type='DBHead', text_repr_type='quad', in_channels=256, loss=dict(type='DBLoss', alpha=5.0, beta=10.0, bbce_loss=True)), train_cfg=None, test_cfg=None)) cfg = mmcv.Config(cfg) pytorch_model = build_detector(cfg.model, None, None) # prepare data inputs = torch.rand(1, 3, 224, 224) img_metas = [{ 'img_shape': [1, 3, 224, 224], 'ori_shape': [1, 3, 224, 224], 'pad_shape': [1, 3, 224, 224], 'filename': None, 'scale_factor': np.array([1, 1, 1, 1]) }] pytorch_model.forward = pytorch_model.forward_dummy with tempfile.TemporaryDirectory() as tmpdirname: onnx_path = f'{tmpdirname}/tmp.onnx' with torch.no_grad(): torch.onnx.export( pytorch_model, inputs, onnx_path, input_names=['input'], output_names=['output'], export_params=True, keep_initializers_as_inputs=False, verbose=False, opset_version=11) # TensorRT part def get_GiB(x: int): """return x GiB.""" return x * (1 << 30) trt_path = onnx_path.replace('.onnx', '.trt') min_shape = [1, 3, 224, 224] max_shape = [1, 3, 224, 224] # create trt engine and wrapper opt_shape_dict = {'input': [min_shape, min_shape, max_shape]} max_workspace_size = get_GiB(1) trt_engine = onnx2trt( onnx_path, opt_shape_dict, log_level=trt.Logger.ERROR, fp16_mode=False, max_workspace_size=max_workspace_size) save_trt_engine(trt_engine, trt_path) print(f'Successfully created TensorRT engine: {trt_path}') wrap_onnx = ONNXRuntimeDetector(onnx_path, cfg, 0) wrap_trt = TensorRTDetector(trt_path, cfg, 0) assert isinstance(wrap_onnx, ONNXRuntimeDetector) assert isinstance(wrap_trt, TensorRTDetector) with torch.no_grad(): onnx_outputs = wrap_onnx.simple_test(inputs, img_metas, rescale=False) trt_outputs = wrap_onnx.simple_test(inputs, img_metas, rescale=False) assert isinstance(onnx_outputs[0], dict) assert isinstance(trt_outputs[0], dict) assert 'boundary_result' in onnx_outputs[0] assert 'boundary_result' in trt_outputs[0]
def test_pisa_ssd_head_loss(): """Tests pisa ssd head loss when truth is empty and non-empty.""" s = 256 img_metas = [{ 'img_shape': (s, s, 3), 'scale_factor': 1, 'pad_shape': (s, s, 3) }] cfg = mmcv.Config( dict(assigner=dict(type='MaxIoUAssigner', pos_iou_thr=0.5, neg_iou_thr=0.5, min_pos_iou=0., ignore_iof_thr=-1, gt_max_assign_all=False), isr=dict(k=2., bias=0.), carl=dict(k=1., bias=0.2), smoothl1_beta=1., allowed_border=-1, pos_weight=-1, neg_pos_ratio=3, debug=False)) ssd_anchor_generator = dict(type='SSDAnchorGenerator', scale_major=False, input_size=300, strides=[1], ratios=([2], ), basesize_ratio_range=(0.15, 0.9)) self = PISASSDHead(num_classes=4, in_channels=(1, ), train_cfg=cfg, anchor_generator=ssd_anchor_generator) # Anchor head expects a multiple levels of features per image feat = [ torch.rand(1, 1, s // (2**(i + 2)), s // (2**(i + 2))) for i in range(len(self.anchor_generator.strides)) ] cls_scores, bbox_preds = self.forward(feat) # Test that empty ground truth encourages the network to predict background gt_bboxes = [torch.empty((0, 4))] gt_labels = [torch.LongTensor([])] gt_bboxes_ignore = None empty_gt_losses = self.loss(cls_scores, bbox_preds, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore) # When there is no truth, the cls loss should be nonzero but there should # be no box loss. empty_cls_loss = sum(empty_gt_losses['loss_cls']) empty_box_loss = sum(empty_gt_losses['loss_bbox']) # SSD is special, #pos:#neg = 1: 3, so empth gt will also lead loss cls = 0 assert empty_cls_loss.item() == 0, 'cls loss should be non-zero' assert empty_box_loss.item() == 0, ( 'there should be no box loss when there are no true boxes') # When truth is non-empty then both cls and box loss should be nonzero for # random inputs gt_bboxes = [ torch.Tensor([[23.6667, 23.8757, 238.6326, 151.8874]]), ] gt_labels = [torch.LongTensor([2])] one_gt_losses = self.loss(cls_scores, bbox_preds, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore) onegt_cls_loss = sum(one_gt_losses['loss_cls']) onegt_box_loss = sum(one_gt_losses['loss_bbox']) assert onegt_cls_loss.item() > 0, 'cls loss should be non-zero' assert onegt_box_loss.item() > 0, 'box loss should be non-zero'
def test_paa_head_loss(): """Tests paa head loss when truth is empty and non-empty.""" class mock_skm(object): def GaussianMixture(self, *args, **kwargs): return self def fit(self, loss): pass def predict(self, loss): components = np.zeros_like(loss, dtype=np.long) return components.reshape(-1) def score_samples(self, loss): scores = np.random.random(len(loss)) return scores paa_head.skm = mock_skm() s = 256 img_metas = [{ 'img_shape': (s, s, 3), 'scale_factor': 1, 'pad_shape': (s, s, 3) }] train_cfg = mmcv.Config( dict(assigner=dict(type='MaxIoUAssigner', pos_iou_thr=0.1, neg_iou_thr=0.1, min_pos_iou=0, ignore_iof_thr=-1), allowed_border=-1, pos_weight=-1, debug=False)) # since Focal Loss is not supported on CPU self = PAAHead(num_classes=4, in_channels=1, train_cfg=train_cfg, loss_cls=dict(type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0), loss_bbox=dict(type='GIoULoss', loss_weight=1.3), loss_centerness=dict(type='CrossEntropyLoss', use_sigmoid=True, loss_weight=0.5)) feat = [ torch.rand(1, 1, s // feat_size, s // feat_size) for feat_size in [4, 8, 16, 32, 64] ] self.init_weights() cls_scores, bbox_preds, iou_preds = self(feat) # Test that empty ground truth encourages the network to predict background gt_bboxes = [torch.empty((0, 4))] gt_labels = [torch.LongTensor([])] gt_bboxes_ignore = None empty_gt_losses = self.loss(cls_scores, bbox_preds, iou_preds, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore) # When there is no truth, the cls loss should be nonzero but there should # be no box loss. empty_cls_loss = empty_gt_losses['loss_cls'] empty_box_loss = empty_gt_losses['loss_bbox'] empty_iou_loss = empty_gt_losses['loss_iou'] assert empty_cls_loss.item() > 0, 'cls loss should be non-zero' assert empty_box_loss.item() == 0, ( 'there should be no box loss when there are no true boxes') assert empty_iou_loss.item() == 0, ( 'there should be no box loss when there are no true boxes') # When truth is non-empty then both cls and box loss should be nonzero for # random inputs gt_bboxes = [ torch.Tensor([[23.6667, 23.8757, 238.6326, 151.8874]]), ] gt_labels = [torch.LongTensor([2])] one_gt_losses = self.loss(cls_scores, bbox_preds, iou_preds, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore) onegt_cls_loss = one_gt_losses['loss_cls'] onegt_box_loss = one_gt_losses['loss_bbox'] onegt_iou_loss = one_gt_losses['loss_iou'] assert onegt_cls_loss.item() > 0, 'cls loss should be non-zero' assert onegt_box_loss.item() > 0, 'box loss should be non-zero' assert onegt_iou_loss.item() > 0, 'box loss should be non-zero' n, c, h, w = 10, 4, 20, 20 mlvl_tensor = [torch.ones(n, c, h, w) for i in range(5)] results = levels_to_images(mlvl_tensor) assert len(results) == n assert results[0].size() == (h * w * 5, c) assert self.with_score_voting cls_scores = [torch.ones(4, 5, 5)] bbox_preds = [torch.ones(4, 5, 5)] iou_preds = [torch.ones(1, 5, 5)] mlvl_anchors = [torch.ones(5 * 5, 4)] img_shape = None scale_factor = [0.5, 0.5] cfg = mmcv.Config( dict(nms_pre=1000, min_bbox_size=0, score_thr=0.05, nms=dict(type='nms', iou_threshold=0.6), max_per_img=100)) rescale = False self._get_bboxes_single(cls_scores, bbox_preds, iou_preds, mlvl_anchors, img_shape, scale_factor, cfg, rescale=rescale)
def test_mattor_wrapper(): try: import onnxruntime as ort from mmedit.core.export.wrappers import (ONNXRuntimeEditing, ONNXRuntimeMattor) except ImportError: pytest.skip('ONNXRuntime is not available.') onnx_path = 'tmp.onnx' train_cfg = None test_cfg = dict(refine=False, metrics=['SAD', 'MSE', 'GRAD', 'CONN']) cfg = dict( model=dict( type='DIM', backbone=dict( type='SimpleEncoderDecoder', encoder=dict(type='VGG16', in_channels=4), decoder=dict(type='PlainDecoder')), pretrained='open-mmlab://mmedit/vgg16', loss_alpha=dict(type='CharbonnierLoss', loss_weight=0.5), loss_comp=dict(type='CharbonnierCompLoss', loss_weight=0.5)), train_cfg=train_cfg, test_cfg=test_cfg) cfg = mmcv.Config(cfg) pytorch_model = build_model( cfg.model, train_cfg=cfg.train_cfg, test_cfg=cfg.test_cfg) img_shape = (32, 32) merged = torch.rand(1, 3, img_shape[1], img_shape[0]) trimap = torch.rand(1, 1, img_shape[1], img_shape[0]) data_batch = {'merged': merged, 'trimap': trimap} inputs = torch.cat([merged, trimap], dim=1) pytorch_model.forward = pytorch_model.forward_dummy with torch.no_grad(): torch.onnx.export( pytorch_model, inputs, onnx_path, input_names=['input'], output_names=['output'], export_params=True, keep_initializers_as_inputs=False, verbose=False, opset_version=11) wrap_model = ONNXRuntimeEditing(onnx_path, cfg, 0) os.remove(onnx_path) assert isinstance(wrap_model.wrapper, ONNXRuntimeMattor) if ort.get_device() == 'GPU': merged = merged.cuda() trimap = trimap.cuda() data_batch = {'merged': merged, 'trimap': trimap} ori_alpha = np.random.random(img_shape).astype(np.float32) ori_trimap = np.random.randint(256, size=img_shape).astype(np.float32) data_batch['meta'] = [ dict( ori_alpha=ori_alpha, ori_trimap=ori_trimap, merged_ori_shape=img_shape) ] with torch.no_grad(): outputs = wrap_model(**data_batch, test_mode=True) assert isinstance(outputs, dict) assert 'pred_alpha' in outputs pred_alpha = outputs['pred_alpha'] assert isinstance(pred_alpha, np.ndarray) assert pred_alpha.shape == img_shape
def test_sabl_retina_head_loss(): """Tests anchor head loss when truth is empty and non-empty.""" s = 256 img_metas = [{ 'img_shape': (s, s, 3), 'scale_factor': 1, 'pad_shape': (s, s, 3) }] cfg = mmcv.Config( dict(assigner=dict(type='ApproxMaxIoUAssigner', pos_iou_thr=0.5, neg_iou_thr=0.4, min_pos_iou=0.0, ignore_iof_thr=-1), allowed_border=-1, pos_weight=-1, debug=False)) head = SABLRetinaHead(num_classes=4, in_channels=3, feat_channels=10, loss_cls=dict(type='CrossEntropyLoss', use_sigmoid=True, loss_weight=1.0), train_cfg=cfg) if torch.cuda.is_available(): head.cuda() # Anchor head expects a multiple levels of features per image feat = [ torch.rand(1, 3, s // (2**(i + 2)), s // (2**(i + 2))).cuda() for i in range(len(head.approx_anchor_generator.base_anchors)) ] cls_scores, bbox_preds = head.forward(feat) # Test that empty ground truth encourages the network # to predict background gt_bboxes = [torch.empty((0, 4)).cuda()] gt_labels = [torch.LongTensor([]).cuda()] gt_bboxes_ignore = None empty_gt_losses = head.loss(cls_scores, bbox_preds, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore) # When there is no truth, the cls loss should be nonzero but there # should be no box loss. empty_cls_loss = sum(empty_gt_losses['loss_cls']) empty_box_cls_loss = sum(empty_gt_losses['loss_bbox_cls']) empty_box_reg_loss = sum(empty_gt_losses['loss_bbox_reg']) assert empty_cls_loss.item() > 0, 'cls loss should be non-zero' assert empty_box_cls_loss.item() == 0, ( 'there should be no box cls loss when there are no true boxes') assert empty_box_reg_loss.item() == 0, ( 'there should be no box reg loss when there are no true boxes') # When truth is non-empty then both cls and box loss should # be nonzero for random inputs gt_bboxes = [ torch.Tensor([[23.6667, 23.8757, 238.6326, 151.8874]]).cuda(), ] gt_labels = [torch.LongTensor([2]).cuda()] one_gt_losses = head.loss(cls_scores, bbox_preds, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore) onegt_cls_loss = sum(one_gt_losses['loss_cls']) onegt_box_cls_loss = sum(one_gt_losses['loss_bbox_cls']) onegt_box_reg_loss = sum(one_gt_losses['loss_bbox_reg']) assert onegt_cls_loss.item() > 0, 'cls loss should be non-zero' assert onegt_box_cls_loss.item() > 0, 'box loss cls should be non-zero' assert onegt_box_reg_loss.item() > 0, 'box loss reg should be non-zero'
def to_config(self): return mmcv.Config( dict(type='VideoDecordBackend', params=dict(video_path=self.video_path)))
def test_mask_head_loss(): """Test mask head loss when mask target is empty.""" self = FCNMaskHead(num_convs=1, roi_feat_size=6, in_channels=8, conv_out_channels=8, num_classes=8) # Dummy proposals proposal_list = [ torch.Tensor([[23.6667, 23.8757, 228.6326, 153.8874]]), ] gt_bboxes = [ torch.Tensor([[23.6667, 23.8757, 238.6326, 151.8874]]), ] gt_labels = [torch.LongTensor([2])] sampling_results = _dummy_bbox_sampling(proposal_list, gt_bboxes, gt_labels) # create dummy mask import numpy as np from mmdet.core import BitmapMasks dummy_mask = np.random.randint(0, 2, (1, 160, 240), dtype=np.uint8) gt_masks = [BitmapMasks(dummy_mask, 160, 240)] # create dummy train_cfg train_cfg = mmcv.Config(dict(mask_size=12, mask_thr_binary=0.5)) # Create dummy features "extracted" for each sampled bbox num_sampled = sum(len(res.bboxes) for res in sampling_results) dummy_feats = torch.rand(num_sampled, 8, 6, 6) mask_pred = self.forward(dummy_feats) mask_targets = self.get_targets(sampling_results, gt_masks, train_cfg) pos_labels = torch.cat([res.pos_gt_labels for res in sampling_results]) loss_mask = self.loss(mask_pred, mask_targets, pos_labels) onegt_mask_loss = sum(loss_mask['loss_mask']) assert onegt_mask_loss.item() > 0, 'mask loss should be non-zero' # test mask_iou_head mask_iou_head = MaskIoUHead(num_convs=1, num_fcs=1, roi_feat_size=6, in_channels=8, conv_out_channels=8, fc_out_channels=8, num_classes=8) pos_mask_pred = mask_pred[range(mask_pred.size(0)), pos_labels] mask_iou_pred = mask_iou_head(dummy_feats, pos_mask_pred) pos_mask_iou_pred = mask_iou_pred[range(mask_iou_pred.size(0)), pos_labels] mask_iou_targets = mask_iou_head.get_targets(sampling_results, gt_masks, pos_mask_pred, mask_targets, train_cfg) loss_mask_iou = mask_iou_head.loss(pos_mask_iou_pred, mask_iou_targets) onegt_mask_iou_loss = loss_mask_iou['loss_mask_iou'].sum() assert onegt_mask_iou_loss.item() >= 0 # test dynamic_mask_head dummy_proposal_feats = torch.rand(num_sampled, 8) dynamic_mask_head = DynamicMaskHead(dynamic_conv_cfg=dict( type='DynamicConv', in_channels=8, feat_channels=8, out_channels=8, input_feat_shape=6, with_proj=False, act_cfg=dict(type='ReLU', inplace=True), norm_cfg=dict(type='LN')), num_convs=1, num_classes=8, in_channels=8, roi_feat_size=6) mask_pred = dynamic_mask_head(dummy_feats, dummy_proposal_feats) mask_target = dynamic_mask_head.get_targets(sampling_results, gt_masks, train_cfg) loss_mask = dynamic_mask_head.loss(mask_pred, mask_target, pos_labels) loss_mask = loss_mask['loss_mask'].sum() assert loss_mask.item() >= 0
def test_yolof_head_loss(): """Tests yolof head loss when truth is empty and non-empty.""" s = 256 img_metas = [{ 'img_shape': (s, s, 3), 'scale_factor': 1, 'pad_shape': (s, s, 3) }] train_cfg = mmcv.Config( dict(assigner=dict(type='UniformAssigner', pos_ignore_thr=0.15, neg_ignore_thr=0.7), allowed_border=-1, pos_weight=-1, debug=False)) self = YOLOFHead(num_classes=4, in_channels=1, reg_decoded_bbox=True, train_cfg=train_cfg, anchor_generator=dict(type='AnchorGenerator', ratios=[1.0], scales=[1, 2, 4, 8, 16], strides=[32]), bbox_coder=dict(type='DeltaXYWHBBoxCoder', target_means=[.0, .0, .0, .0], target_stds=[1., 1., 1., 1.], add_ctr_clamp=True, ctr_clamp=32), loss_cls=dict(type='FocalLoss', use_sigmoid=True, gamma=2.0, alpha=0.25, loss_weight=1.0), loss_bbox=dict(type='GIoULoss', loss_weight=1.0)) feat = [torch.rand(1, 1, s // 32, s // 32)] cls_scores, bbox_preds = self.forward(feat) # Test that empty ground truth encourages the network to predict background gt_bboxes = [torch.empty((0, 4))] gt_labels = [torch.LongTensor([])] gt_bboxes_ignore = None empty_gt_losses = self.loss(cls_scores, bbox_preds, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore) # When there is no truth, the cls loss should be nonzero but there should # be no box loss. empty_cls_loss = empty_gt_losses['loss_cls'] empty_box_loss = empty_gt_losses['loss_bbox'] assert empty_cls_loss.item() > 0, 'cls loss should be non-zero' assert empty_box_loss.item() == 0, ( 'there should be no box loss when there are no true boxes') # When truth is non-empty then both cls and box loss should be nonzero for # random inputs gt_bboxes = [ torch.Tensor([[23.6667, 23.8757, 238.6326, 151.8874]]), ] gt_labels = [torch.LongTensor([2])] one_gt_losses = self.loss(cls_scores, bbox_preds, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore) onegt_cls_loss = one_gt_losses['loss_cls'] onegt_box_loss = one_gt_losses['loss_bbox'] assert onegt_cls_loss.item() > 0, 'cls loss should be non-zero' assert onegt_box_loss.item() > 0, 'box loss should be non-zero'
def test_sabl_bbox_head_loss(): """Tests bbox head loss when truth is empty and non-empty.""" self = SABLHead(num_classes=4, cls_in_channels=3, reg_in_channels=3, cls_out_channels=3, reg_offset_out_channels=3, reg_cls_out_channels=3, roi_feat_size=7) # Dummy proposals proposal_list = [ torch.Tensor([[23.6667, 23.8757, 228.6326, 153.8874]]), ] target_cfg = mmcv.Config(dict(pos_weight=1)) # Test bbox loss when truth is empty gt_bboxes = [torch.empty((0, 4))] gt_labels = [torch.LongTensor([])] sampling_results = _dummy_bbox_sampling(proposal_list, gt_bboxes, gt_labels) bbox_targets = self.get_targets(sampling_results, gt_bboxes, gt_labels, target_cfg) labels, label_weights, bbox_targets, bbox_weights = bbox_targets # Create dummy features "extracted" for each sampled bbox num_sampled = sum(len(res.bboxes) for res in sampling_results) rois = bbox2roi([res.bboxes for res in sampling_results]) dummy_feats = torch.rand(num_sampled, 3, 7, 7) cls_scores, bbox_preds = self.forward(dummy_feats) losses = self.loss(cls_scores, bbox_preds, rois, labels, label_weights, bbox_targets, bbox_weights) assert losses.get('loss_cls', 0) > 0, 'cls-loss should be non-zero' assert losses.get('loss_bbox_cls', 0) == 0, 'empty gt bbox-cls-loss should be zero' assert losses.get('loss_bbox_reg', 0) == 0, 'empty gt bbox-reg-loss should be zero' # Test bbox loss when truth is non-empty gt_bboxes = [ torch.Tensor([[23.6667, 23.8757, 238.6326, 151.8874]]), ] gt_labels = [torch.LongTensor([2])] sampling_results = _dummy_bbox_sampling(proposal_list, gt_bboxes, gt_labels) rois = bbox2roi([res.bboxes for res in sampling_results]) bbox_targets = self.get_targets(sampling_results, gt_bboxes, gt_labels, target_cfg) labels, label_weights, bbox_targets, bbox_weights = bbox_targets # Create dummy features "extracted" for each sampled bbox num_sampled = sum(len(res.bboxes) for res in sampling_results) dummy_feats = torch.rand(num_sampled, 3, 7, 7) cls_scores, bbox_preds = self.forward(dummy_feats) losses = self.loss(cls_scores, bbox_preds, rois, labels, label_weights, bbox_targets, bbox_weights) assert losses.get('loss_bbox_cls', 0) > 0, 'empty gt bbox-cls-loss should be zero' assert losses.get('loss_bbox_reg', 0) > 0, 'empty gt bbox-reg-loss should be zero'
def test_yolox_head_loss(): """Tests yolox head loss when truth is empty and non-empty.""" s = 256 img_metas = [{ 'img_shape': (s, s, 3), 'scale_factor': 1, 'pad_shape': (s, s, 3) }] train_cfg = mmcv.Config( dict(assigner=dict(type='SimOTAAssigner', center_radius=2.5, candidate_topk=10, iou_weight=3.0, cls_weight=1.0))) self = YOLOXHead(num_classes=4, in_channels=1, use_depthwise=False, train_cfg=train_cfg) assert not self.use_l1 assert isinstance(self.multi_level_cls_convs[0][0], ConvModule) feat = [ torch.rand(1, 1, s // feat_size, s // feat_size) for feat_size in [4, 8, 16] ] cls_scores, bbox_preds, objectnesses = self.forward(feat) # Test that empty ground truth encourages the network to predict background gt_bboxes = [torch.empty((0, 4))] gt_labels = [torch.LongTensor([])] empty_gt_losses = self.loss(cls_scores, bbox_preds, objectnesses, gt_bboxes, gt_labels, img_metas) # When there is no truth, the cls loss should be nonzero but there should # be no box loss. empty_cls_loss = empty_gt_losses['loss_cls'].sum() empty_box_loss = empty_gt_losses['loss_bbox'].sum() empty_obj_loss = empty_gt_losses['loss_obj'].sum() assert empty_cls_loss.item() == 0, ( 'there should be no cls loss when there are no true boxes') assert empty_box_loss.item() == 0, ( 'there should be no box loss when there are no true boxes') assert empty_obj_loss.item() > 0, 'objectness loss should be non-zero' # When truth is non-empty then both cls and box loss should be nonzero for # random inputs self = YOLOXHead(num_classes=4, in_channels=1, use_depthwise=True, train_cfg=train_cfg) assert isinstance(self.multi_level_cls_convs[0][0], DepthwiseSeparableConvModule) self.use_l1 = True gt_bboxes = [ torch.Tensor([[23.6667, 23.8757, 238.6326, 151.8874]]), ] gt_labels = [torch.LongTensor([2])] one_gt_losses = self.loss(cls_scores, bbox_preds, objectnesses, gt_bboxes, gt_labels, img_metas) onegt_cls_loss = one_gt_losses['loss_cls'].sum() onegt_box_loss = one_gt_losses['loss_bbox'].sum() onegt_obj_loss = one_gt_losses['loss_obj'].sum() onegt_l1_loss = one_gt_losses['loss_l1'].sum() assert onegt_cls_loss.item() > 0, 'cls loss should be non-zero' assert onegt_box_loss.item() > 0, 'box loss should be non-zero' assert onegt_obj_loss.item() > 0, 'obj loss should be non-zero' assert onegt_l1_loss.item() > 0, 'l1 loss should be non-zero'
def test_paa_head_loss(): """Tests paa head loss when truth is empty and non-empty.""" s = 256 img_metas = [{ 'img_shape': (s, s, 3), 'scale_factor': 1, 'pad_shape': (s, s, 3) }] train_cfg = mmcv.Config( dict(initial_epoch=4, initial_assigner=dict(type='ATSSAssigner', topk=9), assigner=dict(type='TaskAlignedAssigner', topk=13), alpha=1, beta=6, allowed_border=-1, pos_weight=-1, debug=False)) test_cfg = mmcv.Config( dict(nms_pre=1000, min_bbox_size=0, score_thr=0.05, nms=dict(type='nms', iou_threshold=0.6), max_per_img=100)) # since Focal Loss is not supported on CPU self = TOODHead( num_classes=80, in_channels=1, stacked_convs=6, feat_channels=256, anchor_type='anchor_free', anchor_generator=dict(type='AnchorGenerator', ratios=[1.0], octave_base_scale=8, scales_per_octave=1, strides=[8, 16, 32, 64, 128]), bbox_coder=dict(type='DeltaXYWHBBoxCoder', target_means=[.0, .0, .0, .0], target_stds=[0.1, 0.1, 0.2, 0.2]), initial_loss_cls=dict( type='FocalLoss', use_sigmoid=True, activated=True, # use probability instead of logit as input gamma=2.0, alpha=0.25, loss_weight=1.0), loss_cls=dict( type='QualityFocalLoss', use_sigmoid=True, activated=True, # use probability instead of logit as input beta=2.0, loss_weight=1.0), loss_bbox=dict(type='GIoULoss', loss_weight=2.0), train_cfg=train_cfg, test_cfg=test_cfg) self.init_weights() feat = [ torch.rand(1, 1, s // feat_size, s // feat_size) for feat_size in [8, 16, 32, 64, 128] ] cls_scores, bbox_preds = self(feat) # test initial assigner and losses self.epoch = 0 # Test that empty ground truth encourages the network to predict background gt_bboxes = [torch.empty((0, 4))] gt_labels = [torch.LongTensor([])] gt_bboxes_ignore = None empty_gt_losses = self.loss(cls_scores, bbox_preds, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore) # When there is no truth, the cls loss should be nonzero but there should # be no box loss. empty_cls_loss = empty_gt_losses['loss_cls'] empty_box_loss = empty_gt_losses['loss_bbox'] assert sum(empty_cls_loss).item() > 0, 'cls loss should be non-zero' assert sum(empty_box_loss).item() == 0, ( 'there should be no box loss when there are no true boxes') # When truth is non-empty then both cls and box loss should be nonzero for # random inputs gt_bboxes = [ torch.Tensor([[23.6667, 23.8757, 238.6326, 151.8874]]), ] gt_labels = [torch.LongTensor([2])] one_gt_losses = self.loss(cls_scores, bbox_preds, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore) onegt_cls_loss = one_gt_losses['loss_cls'] onegt_box_loss = one_gt_losses['loss_bbox'] assert sum(onegt_cls_loss).item() > 0, 'cls loss should be non-zero' assert sum(onegt_box_loss).item() > 0, 'box loss should be non-zero' # test task alignment assigner and losses self.epoch = 10 # Test that empty ground truth encourages the network to predict background gt_bboxes = [torch.empty((0, 4))] gt_labels = [torch.LongTensor([])] gt_bboxes_ignore = None empty_gt_losses = self.loss(cls_scores, bbox_preds, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore) # When there is no truth, the cls loss should be nonzero but there should # be no box loss. empty_cls_loss = empty_gt_losses['loss_cls'] empty_box_loss = empty_gt_losses['loss_bbox'] assert sum(empty_cls_loss).item() > 0, 'cls loss should be non-zero' assert sum(empty_box_loss).item() == 0, ( 'there should be no box loss when there are no true boxes') # When truth is non-empty then both cls and box loss should be nonzero for # random inputs gt_bboxes = [ torch.Tensor([[23.6667, 23.8757, 238.6326, 151.8874]]), ] gt_labels = [torch.LongTensor([2])] one_gt_losses = self.loss(cls_scores, bbox_preds, gt_bboxes, gt_labels, img_metas, gt_bboxes_ignore) onegt_cls_loss = one_gt_losses['loss_cls'] onegt_box_loss = one_gt_losses['loss_bbox'] assert sum(onegt_cls_loss).item() > 0, 'cls loss should be non-zero' assert sum(onegt_box_loss).item() > 0, 'box loss should be non-zero'