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.
docstr: Assign gt to bboxes.
  
  This method assigns gts to every bbox (proposal/anchor), each bbox         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:
      bboxes (Tensor): Bounding boxes to be assigned, shape(n, 4).
      gt_bboxes (Tensor): Groundtruth boxes, shape (k, 4).
      gt_bboxes_ignore (tensor, optional): Ground truth bboxes that are
        labelled as `ignored`, e.g., crowd boxes in COCO.
      gt_labels (tensor, optional): Label of gt_bboxes, shape (num_gts,).
  
  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:
      >>> self = CenterRegionAssigner(0.2, 0.2)
      >>> bboxes = torch.Tensor([[0, 0, 10, 10], [10, 10, 20, 20]])
      >>> gt_bboxes = torch.Tensor([[0, 0, 10, 10]])
      >>> assign_result = self.assign(bboxes, gt_bboxes)
      >>> 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","bbox","(","proposal\/anchor",")",",","each","bbox","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",":","bboxes","(","Tensor",")",":","Bounding","boxes","to","be","assigned",",","shape","(","n",",","4",")",".","gt_bboxes","(","Tensor",")",":","Groundtruth","boxes",",","shape","(","k",",","4",")",".","gt_bboxes_ignore","(","tensor",",","optional",")",":","Ground","truth","bboxes","that","are","labelled","as","`","ignored","`",",","e.g.",",","crowd","boxes","in","COCO",".","gt_labels","(","tensor",",","optional",")",":","Label","of","gt_bboxes",",","shape","(","num_gts",",",")",".","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",":",">",">",">","self","=","CenterRegionAssigner","(","0.2",",","0.2",")",">",">",">","bboxes","=","torch.Tensor","(","[","[","0",",","0",",","10",",","10","]",",","[","10",",","10",",","20",",","20","]","]",")",">",">",">","gt_bboxes","=","torch.Tensor","(","[","[","0",",","0",",","10",",","10","]","]",")",">",">",">","assign_result","=","self.assign","(","bboxes",",","gt_bboxes",")",">",">",">","expected_gt_inds","=","torch.LongTensor","(","[","1",",","0","]",")",">",">",">","assert","torch.all","(","assign_result.gt_inds","==","expected_gt_inds",")"]
code: def assign(
      self, bboxes, gt_bboxes, gt_bboxes_ignore=None, gt_labels=None
  ):
      """Assign gt to bboxes.
  
          This method assigns gts to every bbox (proposal/anchor), each bbox \
          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:
              bboxes (Tensor): Bounding boxes to be assigned, shape(n, 4).
              gt_bboxes (Tensor): Groundtruth boxes, shape (k, 4).
              gt_bboxes_ignore (tensor, optional): Ground truth bboxes that are
                labelled as `ignored`, e.g., crowd boxes in COCO.
              gt_labels (tensor, optional): Label of gt_bboxes, shape (num_gts,).
  
          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:
              >>> self = CenterRegionAssigner(0.2, 0.2)
              >>> bboxes = torch.Tensor([[0, 0, 10, 10], [10, 10, 20, 20]])
              >>> gt_bboxes = torch.Tensor([[0, 0, 10, 10]])
              >>> assign_result = self.assign(bboxes, gt_bboxes)
              >>> 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.
      assert bboxes.size(1) == 4, "bboxes 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
      bbox_centers = (bboxes[:, 2:4] + bboxes[:, 0:2]) / 2
      # The center points lie within the gt boxes
      is_bbox_in_gt = is_located_in(bbox_centers, gt_bboxes)
      # Only calculate bbox and gt_core IoF. This enables small prior bboxes
      #   to match large gts
      bbox_and_gt_core_overlaps = self.iou_calculator(
          bboxes, gt_core, mode="iof"
      )
      # The center point of effective priors should be within the gt box
      is_bbox_in_gt_core = is_bbox_in_gt & (
          bbox_and_gt_core_overlaps > self.min_pos_iof
      )  # shape (n, k)
  
      is_bbox_in_gt_shadow = (
          self.iou_calculator(bboxes, gt_shadow, mode="iof")
          > self.min_pos_iof
      )
      # Rule out center effective positive pixels
      is_bbox_in_gt_shadow &= ~is_bbox_in_gt_core
  
      num_gts, num_bboxes = gt_bboxes.size(0), bboxes.size(0)
      if num_gts == 0 or num_bboxes == 0:
          # If no gts exist, assign all pixels to negative
          assigned_gt_ids = is_bbox_in_gt_core.new_zeros(
              (num_bboxes,), 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_bbox_in_gt_core,
              is_bbox_in_gt_shadow,
              gt_priority=sort_idx,
          )
  
      if gt_bboxes_ignore is not None and gt_bboxes_ignore.numel() > 0:
          # No ground truth or boxes, return empty assignment
          gt_bboxes_ignore = scale_boxes(
              gt_bboxes_ignore, scale=self.ignore_gt_scale
          )
          is_bbox_in_ignored_gts = is_located_in(
              bbox_centers, gt_bboxes_ignore
          )
          is_bbox_in_ignored_gts = is_bbox_in_ignored_gts.any(dim=1)
          assigned_gt_ids[is_bbox_in_ignored_gts] = -1
  
      # 4. Assign prior bboxes with class label according to its gt id.
      assigned_labels = None
      shadowed_pixel_labels = None
      if gt_labels is not None:
          # Default assigned label is the background (-1)
          assigned_labels = assigned_gt_ids.new_full((num_bboxes,), -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: insightface/detection/scrfd/mmdet/core/bbox/assigners/center_region_assigner.py
imports: import torch
  from ..builder import BBOX_ASSIGNERS
  from ..iou_calculators import build_iou_calculator
  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(bboxes, gt_bboxes, gt_bboxes_ignore, gt_labels) and returns: assign_result