class_docstr: Head of CornerNet: Detecting Objects as Paired Keypoints.
  
  Code is modified from the `official github repo
  <https://github.com/princeton-vl/CornerNet/blob/master/models/py_utils/
  kp.py#L73>`_ .
  
  More details can be found in the `paper
  <https://arxiv.org/abs/1808.01244>`_ .
  
  Args:
      num_classes (int): Number of categories excluding the background
          category.
      in_channels (int): Number of channels in the input feature map.
      num_feat_levels (int): Levels of feature from the previous module.
          2 for HourglassNet-104 and 1 for HourglassNet-52. Because
          HourglassNet-104 outputs the final feature and intermediate
          supervision feature and HourglassNet-52 only outputs the final
          feature. Defaults to 2.
      corner_emb_channels (int): Channel of embedding vector. Defaults to 1.
      train_cfg (:obj:`ConfigDict` or dict, optional): Training config.
          Useless in CornerHead, but we keep this variable for
          SingleStageDetector.
      test_cfg (:obj:`ConfigDict` or dict, optional): Testing config of
          CornerHead.
      loss_heatmap (:obj:`ConfigDict` or dict): Config of corner heatmap
          loss. Defaults to GaussianFocalLoss.
      loss_embedding (:obj:`ConfigDict` or dict): Config of corner embedding
          loss. Defaults to AssociativeEmbeddingLoss.
      loss_offset (:obj:`ConfigDict` or dict): Config of corner offset loss.
          Defaults to SmoothL1Loss.
      init_cfg (:obj:`ConfigDict` or dict, optional): the config to control
          the initialization.
class_docstr_tok: ["Head","of","CornerNet",":","Detecting","Objects","as","Paired","Keypoints",".","Code","is","modified","from","the","`","official","github","repo","<","https",":","\/\/github.com\/princeton-vl\/CornerNet\/blob\/master\/models\/py_utils\/","kp.py","#","L73",">","`","_",".","More","details","can","be","found","in","the","`","paper","<","https",":","\/\/arxiv.org\/abs\/1808.01244",">","`","_",".","Args",":","num_classes","(","int",")",":","Number","of","categories","excluding","the","background","category",".","in_channels","(","int",")",":","Number","of","channels","in","the","input","feature","map",".","num_feat_levels","(","int",")",":","Levels","of","feature","from","the","previous","module",".","2","for","HourglassNet-104","and","1","for","HourglassNet-52",".","Because","HourglassNet-104","outputs","the","final","feature","and","intermediate","supervision","feature","and","HourglassNet-52","only","outputs","the","final","feature",".","Defaults","to","2.","corner_emb_channels","(","int",")",":","Channel","of","embedding","vector",".","Defaults","to","1.","train_cfg","(",":","obj",":","`","ConfigDict","`","or","dict",",","optional",")",":","Training","config",".","Useless","in","CornerHead",",","but","we","keep","this","variable","for","SingleStageDetector",".","test_cfg","(",":","obj",":","`","ConfigDict","`","or","dict",",","optional",")",":","Testing","config","of","CornerHead",".","loss_heatmap","(",":","obj",":","`","ConfigDict","`","or","dict",")",":","Config","of","corner","heatmap","loss",".","Defaults","to","GaussianFocalLoss",".","loss_embedding","(",":","obj",":","`","ConfigDict","`","or","dict",")",":","Config","of","corner","embedding","loss",".","Defaults","to","AssociativeEmbeddingLoss",".","loss_offset","(",":","obj",":","`","ConfigDict","`","or","dict",")",":","Config","of","corner","offset","loss",".","Defaults","to","SmoothL1Loss",".","init_cfg","(",":","obj",":","`","ConfigDict","`","or","dict",",","optional",")",":","the","config","to","control","the","initialization","."]
docstr: Transform outputs into detections raw bbox prediction.
  
  Args:
      tl_heat (Tensor): Top-left corner heatmap for current level with
          shape (N, num_classes, H, W).
      br_heat (Tensor): Bottom-right corner heatmap for current level
          with shape (N, num_classes, H, W).
      tl_off (Tensor): Top-left corner offset for current level with
          shape (N, corner_offset_channels, H, W).
      br_off (Tensor): Bottom-right corner offset for current level with
          shape (N, corner_offset_channels, H, W).
      tl_emb (Tensor, Optional): Top-left corner embedding for current
          level with shape (N, corner_emb_channels, H, W).
      br_emb (Tensor, Optional): Bottom-right corner embedding for
          current level with shape (N, corner_emb_channels, H, W).
      tl_centripetal_shift (Tensor, Optional): Top-left centripetal shift
          for current level with shape (N, 2, H, W).
      br_centripetal_shift (Tensor, Optional): Bottom-right centripetal
          shift for current level with shape (N, 2, H, W).
      img_meta (dict): Meta information of current image, e.g.,
          image size, scaling factor, etc.
      k (int): Get top k corner keypoints from heatmap.
      kernel (int): Max pooling kernel for extract local maximum pixels.
      distance_threshold (float): Distance threshold. Top-left and
          bottom-right corner keypoints with feature distance less than
          the threshold will be regarded as keypoints from same object.
      num_dets (int): Num of raw boxes before doing nms.
  
  Returns:
      tuple[torch.Tensor]: Decoded output of CornerHead, containing the
      following Tensors:
  
      - bboxes (Tensor): Coords of each box.
      - scores (Tensor): Scores of each box.
      - clses (Tensor): Categories of each box.
docstr_tok: ["Transform","outputs","into","detections","raw","bbox","prediction",".","Args",":","tl_heat","(","Tensor",")",":","Top-left","corner","heatmap","for","current","level","with","shape","(","N",",","num_classes",",","H",",","W",")",".","br_heat","(","Tensor",")",":","Bottom-right","corner","heatmap","for","current","level","with","shape","(","N",",","num_classes",",","H",",","W",")",".","tl_off","(","Tensor",")",":","Top-left","corner","offset","for","current","level","with","shape","(","N",",","corner_offset_channels",",","H",",","W",")",".","br_off","(","Tensor",")",":","Bottom-right","corner","offset","for","current","level","with","shape","(","N",",","corner_offset_channels",",","H",",","W",")",".","tl_emb","(","Tensor",",","Optional",")",":","Top-left","corner","embedding","for","current","level","with","shape","(","N",",","corner_emb_channels",",","H",",","W",")",".","br_emb","(","Tensor",",","Optional",")",":","Bottom-right","corner","embedding","for","current","level","with","shape","(","N",",","corner_emb_channels",",","H",",","W",")",".","tl_centripetal_shift","(","Tensor",",","Optional",")",":","Top-left","centripetal","shift","for","current","level","with","shape","(","N",",","2",",","H",",","W",")",".","br_centripetal_shift","(","Tensor",",","Optional",")",":","Bottom-right","centripetal","shift","for","current","level","with","shape","(","N",",","2",",","H",",","W",")",".","img_meta","(","dict",")",":","Meta","information","of","current","image",",","e.g.",",","image","size",",","scaling","factor",",","etc",".","k","(","int",")",":","Get","top","k","corner","keypoints","from","heatmap",".","kernel","(","int",")",":","Max","pooling","kernel","for","extract","local","maximum","pixels",".","distance_threshold","(","float",")",":","Distance","threshold",".","Top-left","and","bottom-right","corner","keypoints","with","feature","distance","less","than","the","threshold","will","be","regarded","as","keypoints","from","same","object",".","num_dets","(","int",")",":","Num","of","raw","boxes","before","doing","nms",".","Returns",":","tuple","[","torch.Tensor","]",":","Decoded","output","of","CornerHead",",","containing","the","following","Tensors",":","-","bboxes","(","Tensor",")",":","Coords","of","each","box",".","-","scores","(","Tensor",")",":","Scores","of","each","box",".","-","clses","(","Tensor",")",":","Categories","of","each","box","."]
code: def _decode_heatmap(
      self,
      tl_heat: Tensor,
      br_heat: Tensor,
      tl_off: Tensor,
      br_off: Tensor,
      tl_emb: Optional[Tensor] = None,
      br_emb: Optional[Tensor] = None,
      tl_centripetal_shift: Optional[Tensor] = None,
      br_centripetal_shift: Optional[Tensor] = None,
      img_meta: Optional[dict] = None,
      k: int = 100,
      kernel: int = 3,
      distance_threshold: float = 0.5,
      num_dets: int = 1000,
  ) -> Tuple[Tensor, Tensor, Tensor]:
      """Transform outputs into detections raw bbox prediction.
  
      Args:
          tl_heat (Tensor): Top-left corner heatmap for current level with
              shape (N, num_classes, H, W).
          br_heat (Tensor): Bottom-right corner heatmap for current level
              with shape (N, num_classes, H, W).
          tl_off (Tensor): Top-left corner offset for current level with
              shape (N, corner_offset_channels, H, W).
          br_off (Tensor): Bottom-right corner offset for current level with
              shape (N, corner_offset_channels, H, W).
          tl_emb (Tensor, Optional): Top-left corner embedding for current
              level with shape (N, corner_emb_channels, H, W).
          br_emb (Tensor, Optional): Bottom-right corner embedding for
              current level with shape (N, corner_emb_channels, H, W).
          tl_centripetal_shift (Tensor, Optional): Top-left centripetal shift
              for current level with shape (N, 2, H, W).
          br_centripetal_shift (Tensor, Optional): Bottom-right centripetal
              shift for current level with shape (N, 2, H, W).
          img_meta (dict): Meta information of current image, e.g.,
              image size, scaling factor, etc.
          k (int): Get top k corner keypoints from heatmap.
          kernel (int): Max pooling kernel for extract local maximum pixels.
          distance_threshold (float): Distance threshold. Top-left and
              bottom-right corner keypoints with feature distance less than
              the threshold will be regarded as keypoints from same object.
          num_dets (int): Num of raw boxes before doing nms.
  
      Returns:
          tuple[torch.Tensor]: Decoded output of CornerHead, containing the
          following Tensors:
  
          - bboxes (Tensor): Coords of each box.
          - scores (Tensor): Scores of each box.
          - clses (Tensor): Categories of each box.
      """
      with_embedding = tl_emb is not None and br_emb is not None
      with_centripetal_shift = (
          tl_centripetal_shift is not None
          and br_centripetal_shift is not None
      )
      assert with_embedding + with_centripetal_shift == 1
      batch, _, height, width = tl_heat.size()
      if torch.onnx.is_in_onnx_export():
          inp_h, inp_w = img_meta["pad_shape_for_onnx"][:2]
      else:
          inp_h, inp_w = img_meta["batch_input_shape"][:2]
  
      # perform nms on heatmaps
      tl_heat = get_local_maximum(tl_heat, kernel=kernel)
      br_heat = get_local_maximum(br_heat, kernel=kernel)
  
      (
          tl_scores,
          tl_inds,
          tl_clses,
          tl_ys,
          tl_xs,
      ) = get_topk_from_heatmap(tl_heat, k=k)
      (
          br_scores,
          br_inds,
          br_clses,
          br_ys,
          br_xs,
      ) = get_topk_from_heatmap(br_heat, k=k)
  
      # We use repeat instead of expand here because expand is a
      # shallow-copy function. Thus it could cause unexpected testing result
      # sometimes. Using expand will decrease about 10% mAP during testing
      # compared to repeat.
      tl_ys = tl_ys.view(batch, k, 1).repeat(1, 1, k)
      tl_xs = tl_xs.view(batch, k, 1).repeat(1, 1, k)
      br_ys = br_ys.view(batch, 1, k).repeat(1, k, 1)
      br_xs = br_xs.view(batch, 1, k).repeat(1, k, 1)
  
      tl_off = transpose_and_gather_feat(tl_off, tl_inds)
      tl_off = tl_off.view(batch, k, 1, 2)
      br_off = transpose_and_gather_feat(br_off, br_inds)
      br_off = br_off.view(batch, 1, k, 2)
  
      tl_xs = tl_xs + tl_off[..., 0]
      tl_ys = tl_ys + tl_off[..., 1]
      br_xs = br_xs + br_off[..., 0]
      br_ys = br_ys + br_off[..., 1]
  
      if with_centripetal_shift:
          tl_centripetal_shift = (
              transpose_and_gather_feat(tl_centripetal_shift, tl_inds)
              .view(batch, k, 1, 2)
              .exp()
          )
          br_centripetal_shift = (
              transpose_and_gather_feat(br_centripetal_shift, br_inds)
              .view(batch, 1, k, 2)
              .exp()
          )
  
          tl_ctxs = tl_xs + tl_centripetal_shift[..., 0]
          tl_ctys = tl_ys + tl_centripetal_shift[..., 1]
          br_ctxs = br_xs - br_centripetal_shift[..., 0]
          br_ctys = br_ys - br_centripetal_shift[..., 1]
  
      # all possible boxes based on top k corners (ignoring class)
      tl_xs *= inp_w / width
      tl_ys *= inp_h / height
      br_xs *= inp_w / width
      br_ys *= inp_h / height
  
      if with_centripetal_shift:
          tl_ctxs *= inp_w / width
          tl_ctys *= inp_h / height
          br_ctxs *= inp_w / width
          br_ctys *= inp_h / height
  
      x_off, y_off = 0, 0  # no crop
      if not torch.onnx.is_in_onnx_export():
          # since `RandomCenterCropPad` is done on CPU with numpy and it's
          # not dynamic traceable when exporting to ONNX, thus 'border'
          # does not appears as key in 'img_meta'. As a tmp solution,
          # we move this 'border' handle part to the postprocess after
          # finished exporting to ONNX, which is handle in
          # `mmdet/core/export/model_wrappers.py`. Though difference between
          # pytorch and exported onnx model, it might be ignored since
          # comparable performance is achieved between them (e.g. 40.4 vs
          # 40.6 on COCO val2017, for CornerNet without test-time flip)
          if "border" in img_meta:
              x_off = img_meta["border"][2]
              y_off = img_meta["border"][0]
  
      tl_xs -= x_off
      tl_ys -= y_off
      br_xs -= x_off
      br_ys -= y_off
  
      zeros = tl_xs.new_zeros(*tl_xs.size())
      tl_xs = torch.where(tl_xs > 0.0, tl_xs, zeros)
      tl_ys = torch.where(tl_ys > 0.0, tl_ys, zeros)
      br_xs = torch.where(br_xs > 0.0, br_xs, zeros)
      br_ys = torch.where(br_ys > 0.0, br_ys, zeros)
  
      bboxes = torch.stack((tl_xs, tl_ys, br_xs, br_ys), dim=3)
      area_bboxes = ((br_xs - tl_xs) * (br_ys - tl_ys)).abs()
  
      if with_centripetal_shift:
          tl_ctxs -= x_off
          tl_ctys -= y_off
          br_ctxs -= x_off
          br_ctys -= y_off
  
          tl_ctxs *= tl_ctxs.gt(0.0).type_as(tl_ctxs)
          tl_ctys *= tl_ctys.gt(0.0).type_as(tl_ctys)
          br_ctxs *= br_ctxs.gt(0.0).type_as(br_ctxs)
          br_ctys *= br_ctys.gt(0.0).type_as(br_ctys)
  
          ct_bboxes = torch.stack(
              (tl_ctxs, tl_ctys, br_ctxs, br_ctys), dim=3
          )
          area_ct_bboxes = (
              (br_ctxs - tl_ctxs) * (br_ctys - tl_ctys)
          ).abs()
  
          rcentral = torch.zeros_like(ct_bboxes)
          # magic nums from paper section 4.1
          mu = torch.ones_like(area_bboxes) / 2.4
          mu[area_bboxes > 3500] = 1 / 2.1  # large bbox have smaller mu
  
          bboxes_center_x = (bboxes[..., 0] + bboxes[..., 2]) / 2
          bboxes_center_y = (bboxes[..., 1] + bboxes[..., 3]) / 2
          rcentral[..., 0] = (
              bboxes_center_x
              - mu * (bboxes[..., 2] - bboxes[..., 0]) / 2
          )
          rcentral[..., 1] = (
              bboxes_center_y
              - mu * (bboxes[..., 3] - bboxes[..., 1]) / 2
          )
          rcentral[..., 2] = (
              bboxes_center_x
              + mu * (bboxes[..., 2] - bboxes[..., 0]) / 2
          )
          rcentral[..., 3] = (
              bboxes_center_y
              + mu * (bboxes[..., 3] - bboxes[..., 1]) / 2
          )
          area_rcentral = (
              (rcentral[..., 2] - rcentral[..., 0])
              * (rcentral[..., 3] - rcentral[..., 1])
          ).abs()
          dists = area_ct_bboxes / area_rcentral
  
          tl_ctx_inds = (ct_bboxes[..., 0] <= rcentral[..., 0]) | (
              ct_bboxes[..., 0] >= rcentral[..., 2]
          )
          tl_cty_inds = (ct_bboxes[..., 1] <= rcentral[..., 1]) | (
              ct_bboxes[..., 1] >= rcentral[..., 3]
          )
          br_ctx_inds = (ct_bboxes[..., 2] <= rcentral[..., 0]) | (
              ct_bboxes[..., 2] >= rcentral[..., 2]
          )
          br_cty_inds = (ct_bboxes[..., 3] <= rcentral[..., 1]) | (
              ct_bboxes[..., 3] >= rcentral[..., 3]
          )
  
      if with_embedding:
          tl_emb = transpose_and_gather_feat(tl_emb, tl_inds)
          tl_emb = tl_emb.view(batch, k, 1)
          br_emb = transpose_and_gather_feat(br_emb, br_inds)
          br_emb = br_emb.view(batch, 1, k)
          dists = torch.abs(tl_emb - br_emb)
  
      tl_scores = tl_scores.view(batch, k, 1).repeat(1, 1, k)
      br_scores = br_scores.view(batch, 1, k).repeat(1, k, 1)
  
      scores = (
          tl_scores + br_scores
      ) / 2  # scores for all possible boxes
  
      # tl and br should have same class
      tl_clses = tl_clses.view(batch, k, 1).repeat(1, 1, k)
      br_clses = br_clses.view(batch, 1, k).repeat(1, k, 1)
      cls_inds = tl_clses != br_clses
  
      # reject boxes based on distances
      dist_inds = dists > distance_threshold
  
      # reject boxes based on widths and heights
      width_inds = br_xs <= tl_xs
      height_inds = br_ys <= tl_ys
  
      # No use `scores[cls_inds]`, instead we use `torch.where` here.
      # Since only 1-D indices with type 'tensor(bool)' are supported
      # when exporting to ONNX, any other bool indices with more dimensions
      # (e.g. 2-D bool tensor) as input parameter in node is invalid
      negative_scores = -1 * torch.ones_like(scores)
      scores = torch.where(cls_inds, negative_scores, scores)
      scores = torch.where(width_inds, negative_scores, scores)
      scores = torch.where(height_inds, negative_scores, scores)
      scores = torch.where(dist_inds, negative_scores, scores)
  
      if with_centripetal_shift:
          scores[tl_ctx_inds] = -1
          scores[tl_cty_inds] = -1
          scores[br_ctx_inds] = -1
          scores[br_cty_inds] = -1
  
      scores = scores.view(batch, -1)
      scores, inds = torch.topk(scores, num_dets)
      scores = scores.unsqueeze(2)
  
      bboxes = bboxes.view(batch, -1, 4)
      bboxes = gather_feat(bboxes, inds)
  
      clses = tl_clses.contiguous().view(batch, -1, 1)
      clses = gather_feat(clses, inds)
  
      return bboxes, scores, clses
  
imports: from logging import warning
  from math import ceil, log
  from typing import List, Optional, Sequence, Tuple
  import torch
  import torch.nn
  from mmcv.cnn import ConvModule
  from mmcv.ops import CornerPool, batched_nms
  from mmengine.config import ConfigDict
  from mmengine.model import BaseModule, bias_init_with_prob
  from mmengine.structures import InstanceData
  from torch import Tensor
  from mmdet.registry import MODELS
  from mmdet.utils import ConfigType, InstanceList, OptConfigType, OptInstanceList, OptMultiConfig
  from ..utils import gather_feat, gaussian_radius, gen_gaussian_target, get_local_maximum, get_topk_from_heatmap, multi_apply, transpose_and_gather_feat
  from .base_dense_head import BaseDenseHead
label_desc: Use image node_id 15 for calling the CornerHead obj's underlying member method code with example usage: obj._decode_heatmap(tl_heat, br_heat, tl_off, br_off, tl_emb, br_emb, tl_centripetal_shift, br_centripetal_shift, img_meta, k, kernel, distance_threshold, num_dets) and returns: bboxes,  scores,  clses