docstr: Tests condinst maskhead loss when truth is empty and non-empty.
docstr_tok: ["Tests","condinst","maskhead","loss","when","truth","is","empty","and","non-empty","."]
code: def test_condinst_maskhead_loss(self):
      """Tests condinst maskhead loss when truth is empty and non-empty."""
      s = 256
      img_metas = [
          {
              "img_shape": (s, s, 3),
              "pad_shape": (s, s, 3),
              "scale_factor": 1,
          }
      ]
      condinst_bboxhead = CondInstBboxHead(
          num_classes=4,
          in_channels=1,
          feat_channels=1,
          stacked_convs=1,
          norm_cfg=None,
      )
  
      mask_feature_head = _fake_mask_feature_head()
      condinst_maskhead = CondInstMaskHead(
          mask_feature_head=mask_feature_head,
          loss_mask=dict(
              type="DiceLoss",
              use_sigmoid=True,
              activate=True,
              eps=5e-6,
              loss_weight=1.0,
          ),
      )
  
      # Fcos head expects a multiple levels of features per image
      feats = []
      for i in range(len(condinst_bboxhead.strides)):
          feats.append(
              torch.rand(1, 1, s // (2 ** (i + 3)), s // (2 ** (i + 3)))
          )
      feats = tuple(feats)
      (
          cls_scores,
          bbox_preds,
          centernesses,
          param_preds,
      ) = condinst_bboxhead.forward(feats)
  
      # Test that empty ground truth encourages the network to
      # predict background
      gt_instances = InstanceData()
      gt_instances.bboxes = torch.empty((0, 4))
      gt_instances.labels = torch.LongTensor([])
      gt_instances.masks = _rand_masks(
          0, gt_instances.bboxes.numpy(), s, s
      )
  
      _ = condinst_bboxhead.loss_by_feat(
          cls_scores,
          bbox_preds,
          centernesses,
          param_preds,
          [gt_instances],
          img_metas,
      )
      # When truth is empty then all mask loss
      # should be zero for random inputs
      positive_infos = condinst_bboxhead.get_positive_infos()
      mask_outs = condinst_maskhead.forward(feats, positive_infos)
      empty_gt_mask_losses = condinst_maskhead.loss_by_feat(
          *mask_outs, [gt_instances], img_metas, positive_infos
      )
      loss_mask = empty_gt_mask_losses["loss_mask"]
      self.assertEqual(loss_mask, 0, "mask loss should be zero")
  
      # When truth is non-empty then all cls, box loss and centerness loss
      # should be nonzero for random inputs
      gt_instances = InstanceData()
      gt_instances.bboxes = torch.Tensor(
          [[23.6667, 23.8757, 238.6326, 151.8874]]
      )
      gt_instances.labels = torch.LongTensor([2])
      gt_instances.masks = _rand_masks(
          1, gt_instances.bboxes.numpy(), s, s
      )
  
      _ = condinst_bboxhead.loss_by_feat(
          cls_scores,
          bbox_preds,
          centernesses,
          param_preds,
          [gt_instances],
          img_metas,
      )
      positive_infos = condinst_bboxhead.get_positive_infos()
      mask_outs = condinst_maskhead.forward(feats, positive_infos)
      one_gt_mask_losses = condinst_maskhead.loss_by_feat(
          *mask_outs, [gt_instances], img_metas, positive_infos
      )
      loss_mask = one_gt_mask_losses["loss_mask"]
      self.assertGreater(loss_mask, 0, "mask loss should be nonzero")
  
file_path: mmdetection/tests/test_models/test_dense_heads/test_condinst_head.py
imports: from unittest import TestCase
  import numpy
  import torch
  from mmengine.config import ConfigDict
  from mmengine.structures import InstanceData
  from mmdet.models.dense_heads import CondInstBboxHead, CondInstMaskHead
  from mmdet.structures.mask import BitmapMasks
label_desc: Use image node_id 2 for calling the TestCondInstHead obj's underlying member method code with example usage: obj.test_condinst_maskhead_loss() without return types