class_docstr: Assign pixels at the center region of a bbox as positive.
  
  Each proposals will be assigned with `-1`, `0`, or a positive integer
  indicating the ground truth index.
  - -1: negative samples
  - semi-positive numbers: positive sample, index (0-based) of assigned gt
  
  Args:
      pos_scale (float): Threshold within which pixels are
          labelled as positive.
      neg_scale (float): Threshold above which pixels are
          labelled as positive.
      min_pos_iof (float): Minimum iof of a pixel with a gt to be
          labelled as positive. Default: 1e-2
      ignore_gt_scale (float): Threshold within which the pixels
          are ignored when the gt is labelled as shadowed. Default: 0.5
      foreground_dominate (bool): If True, the bbox will be assigned as
          positive when a gt's kernel region overlaps with another's shadowed
          (ignored) region, otherwise it is set as ignored. Default to False.
      iou_calculator (:obj:`ConfigDict` or dict): Config of overlaps
          Calculator.
class_docstr_tok: ["Assign","pixels","at","the","center","region","of","a","bbox","as","positive",".","Each","proposals","will","be","assigned","with","`","-1","`",",","`","0","`",",","or","a","positive","integer","indicating","the","ground","truth","index",".","-","-1",":","negative","samples","-","semi-positive","numbers",":","positive","sample",",","index","(","0-based",")","of","assigned","gt","Args",":","pos_scale","(","float",")",":","Threshold","within","which","pixels","are","labelled","as","positive",".","neg_scale","(","float",")",":","Threshold","above","which","pixels","are","labelled","as","positive",".","min_pos_iof","(","float",")",":","Minimum","iof","of","a","pixel","with","a","gt","to","be","labelled","as","positive",".","Default",":","1e-2","ignore_gt_scale","(","float",")",":","Threshold","within","which","the","pixels","are","ignored","when","the","gt","is","labelled","as","shadowed",".","Default",":","0.5","foreground_dominate","(","bool",")",":","If","True",",","the","bbox","will","be","assigned","as","positive","when","a","gt","'s","kernel","region","overlaps","with","another","'s","shadowed","(","ignored",")","region",",","otherwise","it","is","set","as","ignored",".","Default","to","False",".","iou_calculator","(",":","obj",":","`","ConfigDict","`","or","dict",")",":","Config","of","overlaps","Calculator","."]
docstr: Assign gt to bboxes.
  
  This method assigns gts to every prior (proposal/anchor), each prior
  will be assigned with -1, or a semi-positive number. -1 means
  negative sample, semi-positive number is the index (0-based) of
  assigned gt.
  
  Args:
      pred_instances (:obj:`InstanceData`): Instances of model
          predictions. It includes ``priors``, and the priors can
          be anchors or points, or the bboxes predicted by the
          previous stage, has shape (n, 4). The bboxes predicted by
          the current model or stage will be named ``bboxes``,
          ``labels``, and ``scores``, the same as the ``InstanceData``
          in other places.
      gt_instances (:obj:`InstanceData`): Ground truth of instance
          annotations. It usually includes ``bboxes``, with shape (k, 4),
          and ``labels``, with shape (k, ).
      gt_instances_ignore (:obj:`InstanceData`, optional): Instances
          to be ignored during training. It includes ``bboxes``
          attribute data that is ignored during training and testing.
          Defaults to None.
  
  Returns:
      :obj:`AssignResult`: The assigned result. Note that shadowed_labels
      of shape (N, 2) is also added as an `assign_result` attribute.
      `shadowed_labels` is a tensor composed of N pairs of anchor_ind,
      class_label], where N is the number of anchors that lie in the
      outer region of a gt, anchor_ind is the shadowed anchor index
      and class_label is the shadowed class label.
  
  Example:
      >>> from mmengine.structures import InstanceData
      >>> self = CenterRegionAssigner(0.2, 0.2)
      >>> pred_instances.priors = torch.Tensor([[0, 0, 10, 10],
      ...                                      [10, 10, 20, 20]])
      >>> gt_instances = InstanceData()
      >>> gt_instances.bboxes = torch.Tensor([[0, 0, 10, 10]])
      >>> gt_instances.labels = torch.Tensor([0])
      >>> assign_result = self.assign(pred_instances, gt_instances)
      >>> expected_gt_inds = torch.LongTensor([1, 0])
      >>> assert torch.all(assign_result.gt_inds == expected_gt_inds)
docstr_tok: ["Assign","gt","to","bboxes",".","This","method","assigns","gts","to","every","prior","(","proposal\/anchor",")",",","each","prior","will","be","assigned","with","-1",",","or","a","semi-positive","number",".","-1","means","negative","sample",",","semi-positive","number","is","the","index","(","0-based",")","of","assigned","gt",".","Args",":","pred_instances","(",":","obj",":","`","InstanceData","`",")",":","Instances","of","model","predictions",".","It","includes","``","priors","``",",","and","the","priors","can","be","anchors","or","points",",","or","the","bboxes","predicted","by","the","previous","stage",",","has","shape","(","n",",","4",")",".","The","bboxes","predicted","by","the","current","model","or","stage","will","be","named","``","bboxes","``",",","``","labels","``",",","and","``","scores","``",",","the","same","as","the","``","InstanceData","``","in","other","places",".","gt_instances","(",":","obj",":","`","InstanceData","`",")",":","Ground","truth","of","instance","annotations",".","It","usually","includes","``","bboxes","``",",","with","shape","(","k",",","4",")",",","and","``","labels","``",",","with","shape","(","k",",",")",".","gt_instances_ignore","(",":","obj",":","`","InstanceData","`",",","optional",")",":","Instances","to","be","ignored","during","training",".","It","includes","``","bboxes","``","attribute","data","that","is","ignored","during","training","and","testing",".","Defaults","to","None",".","Returns",":",":","obj",":","`","AssignResult","`",":","The","assigned","result",".","Note","that","shadowed_labels","of","shape","(","N",",","2",")","is","also","added","as","an","`","assign_result","`","attribute",".","`","shadowed_labels","`","is","a","tensor","composed","of","N","pairs","of","anchor_ind",",","class_label","]",",","where","N","is","the","number","of","anchors","that","lie","in","the","outer","region","of","a","gt",",","anchor_ind","is","the","shadowed","anchor","index","and","class_label","is","the","shadowed","class","label",".","Example",":",">",">",">","from","mmengine.structures","import","InstanceData",">",">",">","self","=","CenterRegionAssigner","(","0.2",",","0.2",")",">",">",">","pred_instances.priors","=","torch.Tensor","(","[","[","0",",","0",",","10",",","10","]",",","...","[","10",",","10",",","20",",","20","]","]",")",">",">",">","gt_instances","=","InstanceData","(",")",">",">",">","gt_instances.bboxes","=","torch.Tensor","(","[","[","0",",","0",",","10",",","10","]","]",")",">",">",">","gt_instances.labels","=","torch.Tensor","(","[","0","]",")",">",">",">","assign_result","=","self.assign","(","pred_instances",",","gt_instances",")",">",">",">","expected_gt_inds","=","torch.LongTensor","(","[","1",",","0","]",")",">",">",">","assert","torch.all","(","assign_result.gt_inds","==","expected_gt_inds",")"]
code: def assign(
      self,
      pred_instances: InstanceData,
      gt_instances: InstanceData,
      gt_instances_ignore: Optional[InstanceData] = None,
      **kwargs,
  ) -> AssignResult:
      """Assign gt to bboxes.
  
      This method assigns gts to every prior (proposal/anchor), each prior
      will be assigned with -1, or a semi-positive number. -1 means
      negative sample, semi-positive number is the index (0-based) of
      assigned gt.
  
      Args:
          pred_instances (:obj:`InstanceData`): Instances of model
              predictions. It includes ``priors``, and the priors can
              be anchors or points, or the bboxes predicted by the
              previous stage, has shape (n, 4). The bboxes predicted by
              the current model or stage will be named ``bboxes``,
              ``labels``, and ``scores``, the same as the ``InstanceData``
              in other places.
          gt_instances (:obj:`InstanceData`): Ground truth of instance
              annotations. It usually includes ``bboxes``, with shape (k, 4),
              and ``labels``, with shape (k, ).
          gt_instances_ignore (:obj:`InstanceData`, optional): Instances
              to be ignored during training. It includes ``bboxes``
              attribute data that is ignored during training and testing.
              Defaults to None.
  
      Returns:
          :obj:`AssignResult`: The assigned result. Note that shadowed_labels
          of shape (N, 2) is also added as an `assign_result` attribute.
          `shadowed_labels` is a tensor composed of N pairs of anchor_ind,
          class_label], where N is the number of anchors that lie in the
          outer region of a gt, anchor_ind is the shadowed anchor index
          and class_label is the shadowed class label.
  
      Example:
          >>> from mmengine.structures import InstanceData
          >>> self = CenterRegionAssigner(0.2, 0.2)
          >>> pred_instances.priors = torch.Tensor([[0, 0, 10, 10],
          ...                                      [10, 10, 20, 20]])
          >>> gt_instances = InstanceData()
          >>> gt_instances.bboxes = torch.Tensor([[0, 0, 10, 10]])
          >>> gt_instances.labels = torch.Tensor([0])
          >>> assign_result = self.assign(pred_instances, gt_instances)
          >>> expected_gt_inds = torch.LongTensor([1, 0])
          >>> assert torch.all(assign_result.gt_inds == expected_gt_inds)
      """
      # There are in total 5 steps in the pixel assignment
      # 1. Find core (the center region, say inner 0.2)
      #     and shadow (the relatively ourter part, say inner 0.2-0.5)
      #     regions of every gt.
      # 2. Find all prior bboxes that lie in gt_core and gt_shadow regions
      # 3. Assign prior bboxes in gt_core with a one-hot id of the gt in
      #      the image.
      #    3.1. For overlapping objects, the prior bboxes in gt_core is
      #           assigned with the object with smallest area
      # 4. Assign prior bboxes with class label according to its gt id.
      #    4.1. Assign -1 to prior bboxes lying in shadowed gts
      #    4.2. Assign positive prior boxes with the corresponding label
      # 5. Find pixels lying in the shadow of an object and assign them with
      #      background label, but set the loss weight of its corresponding
      #      gt to zero.
  
      # TODO not extract bboxes in assign.
      gt_bboxes = gt_instances.bboxes
      priors = pred_instances.priors
      gt_labels = gt_instances.labels
  
      assert priors.size(1) == 4, "priors must have size of 4"
      # 1. Find core positive and shadow region of every gt
      gt_core = scale_boxes(gt_bboxes, self.pos_scale)
      gt_shadow = scale_boxes(gt_bboxes, self.neg_scale)
  
      # 2. Find prior bboxes that lie in gt_core and gt_shadow regions
      prior_centers = (priors[:, 2:4] + priors[:, 0:2]) / 2
      # The center points lie within the gt boxes
      is_prior_in_gt = is_located_in(prior_centers, gt_bboxes)
      # Only calculate prior and gt_core IoF. This enables small prior bboxes
      #   to match large gts
      prior_and_gt_core_overlaps = self.iou_calculator(
          priors, gt_core, mode="iof"
      )
      # The center point of effective priors should be within the gt box
      is_prior_in_gt_core = is_prior_in_gt & (
          prior_and_gt_core_overlaps > self.min_pos_iof
      )  # shape (n, k)
  
      is_prior_in_gt_shadow = (
          self.iou_calculator(priors, gt_shadow, mode="iof")
          > self.min_pos_iof
      )
      # Rule out center effective positive pixels
      is_prior_in_gt_shadow &= ~is_prior_in_gt_core
  
      num_gts, num_priors = gt_bboxes.size(0), priors.size(0)
      if num_gts == 0 or num_priors == 0:
          # If no gts exist, assign all pixels to negative
          assigned_gt_ids = is_prior_in_gt_core.new_zeros(
              (num_priors,), dtype=torch.long
          )
          pixels_in_gt_shadow = assigned_gt_ids.new_empty((0, 2))
      else:
          # Step 3: assign a one-hot gt id to each pixel, and smaller objects
          #    have high priority to assign the pixel.
          sort_idx = self.get_gt_priorities(gt_bboxes)
          (
              assigned_gt_ids,
              pixels_in_gt_shadow,
          ) = self.assign_one_hot_gt_indices(
              is_prior_in_gt_core,
              is_prior_in_gt_shadow,
              gt_priority=sort_idx,
          )
  
      if (
          gt_instances_ignore is not None
          and gt_instances_ignore.bboxes.numel() > 0
      ):
          # No ground truth or boxes, return empty assignment
          gt_bboxes_ignore = gt_instances_ignore.bboxes
          gt_bboxes_ignore = scale_boxes(
              gt_bboxes_ignore, scale=self.ignore_gt_scale
          )
          is_prior_in_ignored_gts = is_located_in(
              prior_centers, gt_bboxes_ignore
          )
          is_prior_in_ignored_gts = is_prior_in_ignored_gts.any(dim=1)
          assigned_gt_ids[is_prior_in_ignored_gts] = -1
  
      # 4. Assign prior bboxes with class label according to its gt id.
      # Default assigned label is the background (-1)
      assigned_labels = assigned_gt_ids.new_full((num_priors,), -1)
      pos_inds = torch.nonzero(
          assigned_gt_ids > 0, as_tuple=False
      ).squeeze()
      if pos_inds.numel() > 0:
          assigned_labels[pos_inds] = gt_labels[
              assigned_gt_ids[pos_inds] - 1
          ]
      # 5. Find pixels lying in the shadow of an object
      shadowed_pixel_labels = pixels_in_gt_shadow.clone()
      if pixels_in_gt_shadow.numel() > 0:
          pixel_idx, gt_idx = (
              pixels_in_gt_shadow[:, 0],
              pixels_in_gt_shadow[:, 1],
          )
          assert (
              assigned_gt_ids[pixel_idx] != gt_idx
          ).all(), "Some pixels are dually assigned to ignore and gt!"
          shadowed_pixel_labels[:, 1] = gt_labels[gt_idx - 1]
          override = (
              assigned_labels[pixel_idx] == shadowed_pixel_labels[:, 1]
          )
          if self.foreground_dominate:
              # When a pixel is both positive and shadowed, set it as pos
              shadowed_pixel_labels = shadowed_pixel_labels[~override]
          else:
              # When a pixel is both pos and shadowed, set it as shadowed
              assigned_labels[pixel_idx[override]] = -1
              assigned_gt_ids[pixel_idx[override]] = 0
  
      assign_result = AssignResult(
          num_gts, assigned_gt_ids, None, labels=assigned_labels
      )
      # Add shadowed_labels as assign_result property. Shape: (num_shadow, 2)
      assign_result.set_extra_property(
          "shadowed_labels", shadowed_pixel_labels
      )
      return assign_result
  
file_path: mmdetection/mmdet/models/task_modules/assigners/center_region_assigner.py
imports: from typing import Optional, Tuple
  import torch
  from mmengine.structures import InstanceData
  from torch import Tensor
  from mmdet.registry import TASK_UTILS
  from mmdet.utils import ConfigType
  from .assign_result import AssignResult
  from .base_assigner import BaseAssigner
label_desc: Use image node_id 3 for calling the CenterRegionAssigner obj's underlying member method code with example usage: obj.assign(pred_instances, gt_instances, gt_instances_ignore) and returns: assign_result