code: def multiclass_nms(
      multi_bboxes: Tensor,
      multi_scores: Tensor,
      score_thr: float,
      nms_cfg: ConfigType,
      max_num: int = -1,
      score_factors: Optional[Tensor] = None,
      return_inds: bool = False,
      box_dim: int = 4,
  ) -> Union[Tuple[Tensor, Tensor, Tensor], Tuple[Tensor, Tensor]]:
      """NMS for multi-class bboxes.
  
      Args:
          multi_bboxes (Tensor): shape (n, #class*4) or (n, 4)
          multi_scores (Tensor): shape (n, #class), where the last column
              contains scores of the background class, but this will be ignored.
          score_thr (float): bbox threshold, bboxes with scores lower than it
              will not be considered.
          nms_cfg (Union[:obj:`ConfigDict`, dict]): a dict that contains
              the arguments of nms operations.
          max_num (int, optional): if there are more than max_num bboxes after
              NMS, only top max_num will be kept. Default to -1.
          score_factors (Tensor, optional): The factors multiplied to scores
              before applying NMS. Default to None.
          return_inds (bool, optional): Whether return the indices of kept
              bboxes. Default to False.
          box_dim (int): The dimension of boxes. Defaults to 4.
  
      Returns:
          Union[Tuple[Tensor, Tensor, Tensor], Tuple[Tensor, Tensor]]:
              (dets, labels, indices (optional)), tensors of shape (k, 5),
              (k), and (k). Dets are boxes with scores. Labels are 0-based.
      """
      num_classes = multi_scores.size(1) - 1
      # exclude background category
      if multi_bboxes.shape[1] > box_dim:
          bboxes = multi_bboxes.view(multi_scores.size(0), -1, box_dim)
      else:
          bboxes = multi_bboxes[:, None].expand(
              multi_scores.size(0), num_classes, box_dim
          )
  
      scores = multi_scores[:, :-1]
  
      labels = torch.arange(
          num_classes, dtype=torch.long, device=scores.device
      )
      labels = labels.view(1, -1).expand_as(scores)
  
      bboxes = bboxes.reshape(-1, box_dim)
      scores = scores.reshape(-1)
      labels = labels.reshape(-1)
  
      if not torch.onnx.is_in_onnx_export():
          # NonZero not supported  in TensorRT
          # remove low scoring boxes
          valid_mask = scores > score_thr
      # multiply score_factor after threshold to preserve more bboxes, improve
      # mAP by 1% for YOLOv3
      if score_factors is not None:
          # expand the shape to match original shape of score
          score_factors = score_factors.view(-1, 1).expand(
              multi_scores.size(0), num_classes
          )
          score_factors = score_factors.reshape(-1)
          scores = scores * score_factors
  
      if not torch.onnx.is_in_onnx_export():
          # NonZero not supported  in TensorRT
          inds = valid_mask.nonzero(as_tuple=False).squeeze(1)
          bboxes, scores, labels = (
              bboxes[inds],
              scores[inds],
              labels[inds],
          )
      else:
          # TensorRT NMS plugin has invalid output filled with -1
          # add dummy data to make detection output correct.
          bboxes = torch.cat(
              [bboxes, bboxes.new_zeros(1, box_dim)], dim=0
          )
          scores = torch.cat([scores, scores.new_zeros(1)], dim=0)
          labels = torch.cat([labels, labels.new_zeros(1)], dim=0)
  
      if bboxes.numel() == 0:
          if torch.onnx.is_in_onnx_export():
              raise RuntimeError(
                  "[ONNX Error] Can not record NMS "
                  "as it has not been executed this time"
              )
          dets = torch.cat([bboxes, scores[:, None]], -1)
          if return_inds:
              return dets, labels, inds
          else:
              return dets, labels
  
      dets, keep = batched_nms(bboxes, scores, labels, nms_cfg)
  
      if max_num > 0:
          dets = dets[:max_num]
          keep = keep[:max_num]
  
      if return_inds:
          return dets, labels[keep], inds[keep]
      else:
          return dets, labels[keep]
  
file_path: mmdetection/mmdet/models/layers/bbox_nms.py
imports: from typing import Optional, Tuple, Union
  import torch
  from mmcv.ops.nms import batched_nms
  from torch import Tensor
  from mmdet.structures.bbox import bbox_overlaps
  from mmdet.utils import ConfigType
label_desc: Use image node_id 1 for calling a global function with example usage: multiclass_nms(multi_bboxes, multi_scores, score_thr, nms_cfg, max_num, score_factors, return_inds, box_dim) and returns: dets,  labels,  inds, dets,  labels, dets,  labels,  inds, dets,  labels