code: def per_class_nms(params, boxes, scores, classes, image_scales=None):
      """Per-class nms, a utility for postprocess_per_class.
  
      Args:
        params: a dict of parameters.
        boxes: A tensor with shape [N, K, 4], where N is batch_size, K is num_boxes.
          Box format is [y_min, x_min, y_max, x_max].
        scores: A tensor with shape [N, K].
        classes: A tensor with shape [N, K].
        image_scales: scaling factor or the final image and bounding boxes.
  
      Returns:
        A tuple of batch level (boxes, scores, classess, valid_len) after nms.
      """
  
      def single_batch_fn(element):
          """A mapping function for a single batch."""
          boxes_i, scores_i, classes_i = (
              element[0],
              element[1],
              element[2],
          )
          nms_boxes_cls, nms_scores_cls, nms_classes_cls = [], [], []
          nms_valid_len_cls = []
          for cid in range(params["num_classes"]):
              indices = tf.where(tf.equal(classes_i, cid))
              if indices.shape[0] == 0:
                  continue
              classes_cls = tf.gather_nd(classes_i, indices)
              boxes_cls = tf.gather_nd(boxes_i, indices)
              scores_cls = tf.gather_nd(scores_i, indices)
  
              nms_boxes, nms_scores, nms_classes, nms_valid_len = nms(
                  params, boxes_cls, scores_cls, classes_cls, False
              )
              nms_boxes_cls.append(nms_boxes)
              nms_scores_cls.append(nms_scores)
              nms_classes_cls.append(nms_classes)
              nms_valid_len_cls.append(nms_valid_len)
  
          # Pad zeros and select topk.
          max_output_size = params["nms_configs"].get(
              "max_output_size", 100
          )
          nms_boxes_cls = tf.pad(
              tf.concat(nms_boxes_cls, 0),
              [[0, max_output_size], [0, 0]],
          )
          nms_scores_cls = tf.pad(
              tf.concat(nms_scores_cls, 0), [[0, max_output_size]]
          )
          nms_classes_cls = tf.pad(
              tf.concat(nms_classes_cls, 0), [[0, max_output_size]]
          )
          nms_valid_len_cls = tf.stack(nms_valid_len_cls)
  
          _, indices = tf.math.top_k(
              nms_scores_cls, k=max_output_size, sorted=True
          )
  
          return tuple(
              (
                  tf.gather(nms_boxes_cls, indices),
                  tf.gather(nms_scores_cls, indices),
                  tf.gather(nms_classes_cls, indices),
                  tf.minimum(
                      max_output_size, tf.reduce_sum(nms_valid_len_cls)
                  ),
              )
          )
          # end of single_batch_fn
  
      nms_boxes, nms_scores, nms_classes, nms_valid_len = batch_map_fn(
          single_batch_fn, [boxes, scores, classes]
      )
      if image_scales is not None:
          scales = tf.expand_dims(tf.expand_dims(image_scales, -1), -1)
          nms_boxes = nms_boxes * tf.cast(scales, nms_boxes.dtype)
      return nms_boxes, nms_scores, nms_classes, nms_valid_len
  
file_path: DALI/docs/examples/use_cases/tensorflow/efficientdet/model/utils/postprocess.py
imports: from typing import List, Tuple
  from absl import logging
  import tensorflow
  from pipeline import anchors
label_desc: Use image node_id 7 for calling a global function with example usage: per_class_nms(params, boxes, scores, classes, image_scales) and returns: nms_boxes,  nms_scores,  nms_classes,  nms_valid_len, tuple