class_docstr: SOLO mask head used in `SOLO: Segmenting Objects by Locations.
  
  <https://arxiv.org/abs/1912.04488>`_
  
  Args:
      num_classes (int): Number of categories excluding the background
          category.
      in_channels (int): Number of channels in the input feature map.
      feat_channels (int): Number of hidden channels. Used in child classes.
          Defaults to 256.
      stacked_convs (int): Number of stacking convs of the head.
          Defaults to 4.
      strides (tuple): Downsample factor of each feature map.
      scale_ranges (tuple[tuple[int, int]]): Area range of multiple
          level masks, in the format [(min1, max1), (min2, max2), ...].
          A range of (16, 64) means the area range between (16, 64).
      pos_scale (float): Constant scale factor to control the center region.
      num_grids (list[int]): Divided image into a uniform grids, each
          feature map has a different grid value. The number of output
          channels is grid ** 2. Defaults to [40, 36, 24, 16, 12].
      cls_down_index (int): The index of downsample operation in
          classification branch. Defaults to 0.
      loss_mask (dict): Config of mask loss.
      loss_cls (dict): Config of classification loss.
      norm_cfg (dict): Dictionary to construct and config norm layer.
          Defaults to norm_cfg=dict(type='GN', num_groups=32,
          requires_grad=True).
      train_cfg (dict): Training config of head.
      test_cfg (dict): Testing config of head.
      init_cfg (dict or list[dict], optional): Initialization config dict.
docstr: Compute targets for predictions of single image.
  
  Args:
      gt_instances (:obj:`InstanceData`): Ground truth of instance
          annotations. It should includes ``bboxes``, ``labels``,
          and ``masks`` attributes.
      featmap_sizes (list[:obj:`torch.size`]): Size of each
          feature map from feature pyramid, each element
          means (feat_h, feat_w). Defaults to None.
  
  Returns:
      Tuple: Usually returns a tuple containing targets for predictions.
  
          - mlvl_pos_mask_targets (list[Tensor]): Each element represent
            the binary mask targets for positive points in this
            level, has shape (num_pos, out_h, out_w).
          - mlvl_labels (list[Tensor]): Each element is
            classification labels for all
            points in this level, has shape
            (num_grid, num_grid).
          - mlvl_pos_masks (list[Tensor]): Each element is
            a `BoolTensor` to represent whether the
            corresponding point in single level
            is positive, has shape (num_grid **2).
code: def _get_targets_single(
      self,
      gt_instances: InstanceData,
      featmap_sizes: Optional[list] = None,
  ) -> tuple:
      """Compute targets for predictions of single image.
  
      Args:
          gt_instances (:obj:`InstanceData`): Ground truth of instance
              annotations. It should includes ``bboxes``, ``labels``,
              and ``masks`` attributes.
          featmap_sizes (list[:obj:`torch.size`]): Size of each
              feature map from feature pyramid, each element
              means (feat_h, feat_w). Defaults to None.
  
      Returns:
          Tuple: Usually returns a tuple containing targets for predictions.
  
              - mlvl_pos_mask_targets (list[Tensor]): Each element represent
                the binary mask targets for positive points in this
                level, has shape (num_pos, out_h, out_w).
              - mlvl_labels (list[Tensor]): Each element is
                classification labels for all
                points in this level, has shape
                (num_grid, num_grid).
              - mlvl_pos_masks (list[Tensor]): Each element is
                a `BoolTensor` to represent whether the
                corresponding point in single level
                is positive, has shape (num_grid **2).
      """
      gt_labels = gt_instances.labels
      device = gt_labels.device
  
      gt_bboxes = gt_instances.bboxes
      gt_areas = torch.sqrt(
          (gt_bboxes[:, 2] - gt_bboxes[:, 0])
          * (gt_bboxes[:, 3] - gt_bboxes[:, 1])
      )
  
      gt_masks = gt_instances.masks.to_tensor(
          dtype=torch.bool, device=device
      )
  
      mlvl_pos_mask_targets = []
      mlvl_labels = []
      mlvl_pos_masks = []
      for (
          (lower_bound, upper_bound),
          stride,
          featmap_size,
          num_grid,
      ) in zip(
          self.scale_ranges, self.strides, featmap_sizes, self.num_grids
      ):
          mask_target = torch.zeros(
              [num_grid**2, featmap_size[0], featmap_size[1]],
              dtype=torch.uint8,
              device=device,
          )
          # FG cat_id: [0, num_classes -1], BG cat_id: num_classes
          labels = (
              torch.zeros(
                  [num_grid, num_grid], dtype=torch.int64, device=device
              )
              + self.num_classes
          )
          pos_mask = torch.zeros(
              [num_grid**2], dtype=torch.bool, device=device
          )
  
          gt_inds = (
              ((gt_areas >= lower_bound) & (gt_areas <= upper_bound))
              .nonzero()
              .flatten()
          )
          if len(gt_inds) == 0:
              mlvl_pos_mask_targets.append(
                  mask_target.new_zeros(
                      0, featmap_size[0], featmap_size[1]
                  )
              )
              mlvl_labels.append(labels)
              mlvl_pos_masks.append(pos_mask)
              continue
          hit_gt_bboxes = gt_bboxes[gt_inds]
          hit_gt_labels = gt_labels[gt_inds]
          hit_gt_masks = gt_masks[gt_inds, ...]
  
          pos_w_ranges = (
              0.5
              * (hit_gt_bboxes[:, 2] - hit_gt_bboxes[:, 0])
              * self.pos_scale
          )
          pos_h_ranges = (
              0.5
              * (hit_gt_bboxes[:, 3] - hit_gt_bboxes[:, 1])
              * self.pos_scale
          )
  
          # Make sure hit_gt_masks has a value
          valid_mask_flags = hit_gt_masks.sum(dim=-1).sum(dim=-1) > 0
          output_stride = stride / 2
  
          for (
              gt_mask,
              gt_label,
              pos_h_range,
              pos_w_range,
              valid_mask_flag,
          ) in zip(
              hit_gt_masks,
              hit_gt_labels,
              pos_h_ranges,
              pos_w_ranges,
              valid_mask_flags,
          ):
              if not valid_mask_flag:
                  continue
              upsampled_size = (
                  featmap_sizes[0][0] * 4,
                  featmap_sizes[0][1] * 4,
              )
              center_h, center_w = center_of_mass(gt_mask)
  
              coord_w = int(
                  floordiv(
                      (center_w / upsampled_size[1]),
                      (1.0 / num_grid),
                      rounding_mode="trunc",
                  )
              )
              coord_h = int(
                  floordiv(
                      (center_h / upsampled_size[0]),
                      (1.0 / num_grid),
                      rounding_mode="trunc",
                  )
              )
  
              # left, top, right, down
              top_box = max(
                  0,
                  int(
                      floordiv(
                          (center_h - pos_h_range) / upsampled_size[0],
                          (1.0 / num_grid),
                          rounding_mode="trunc",
                      )
                  ),
              )
              down_box = min(
                  num_grid - 1,
                  int(
                      floordiv(
                          (center_h + pos_h_range) / upsampled_size[0],
                          (1.0 / num_grid),
                          rounding_mode="trunc",
                      )
                  ),
              )
              left_box = max(
                  0,
                  int(
                      floordiv(
                          (center_w - pos_w_range) / upsampled_size[1],
                          (1.0 / num_grid),
                          rounding_mode="trunc",
                      )
                  ),
              )
              right_box = min(
                  num_grid - 1,
                  int(
                      floordiv(
                          (center_w + pos_w_range) / upsampled_size[1],
                          (1.0 / num_grid),
                          rounding_mode="trunc",
                      )
                  ),
              )
  
              top = max(top_box, coord_h - 1)
              down = min(down_box, coord_h + 1)
              left = max(coord_w - 1, left_box)
              right = min(right_box, coord_w + 1)
  
              labels[top : (down + 1), left : (right + 1)] = gt_label
              # ins
              gt_mask = np.uint8(gt_mask.cpu().numpy())
              # Follow the original implementation, F.interpolate is
              # different from cv2 and opencv
              gt_mask = mmcv.imrescale(
                  gt_mask, scale=1.0 / output_stride
              )
              gt_mask = torch.from_numpy(gt_mask).to(device=device)
  
              for i in range(top, down + 1):
                  for j in range(left, right + 1):
                      index = int(i * num_grid + j)
                      mask_target[
                          index, : gt_mask.shape[0], : gt_mask.shape[1]
                      ] = gt_mask
                      pos_mask[index] = True
          mlvl_pos_mask_targets.append(mask_target[pos_mask])
          mlvl_labels.append(labels)
          mlvl_pos_masks.append(pos_mask)
      return mlvl_pos_mask_targets, mlvl_labels, mlvl_pos_masks
  
imports: from typing import List, Optional, Tuple
  import mmcv
  import numpy
  import torch
  import torch.nn
  import torch.nn.functional
  from mmcv.cnn import ConvModule
  from mmengine.structures import InstanceData
  from torch import Tensor
  from mmdet.models.utils.misc import floordiv
  from mmdet.registry import MODELS
  from mmdet.utils import ConfigType, InstanceList, MultiConfig, OptConfigType
  from ..layers import mask_matrix_nms
  from ..utils import center_of_mass, generate_coordinate, multi_apply
  from .base_mask_head import BaseMaskHead
label_desc: Use image node_id 6 for calling the SOLOHead obj's underlying member method code with example usage: obj._get_targets_single(gt_instances, featmap_sizes) and returns: mlvl_pos_mask_targets,  mlvl_labels,  mlvl_pos_masks