code: def box_iou(
      boxes1: Array,
      boxes2: Array,
      np_backbone: PyModule = jnp,
      all_pairs: bool = True,
      eps: float = 1e-6,
  ) -> Array:
      """Computes IoU between two sets of boxes.
  
      Boxes are in [x, y, x', y'] format [x, y] is top-left, [x', y'] is bottom
      right.
  
      Args:
        boxes1: Predicted bounding-boxes in shape [bs, n, 4].
        boxes2: Target bounding-boxes in shape [bs, m, 4]. Can have a different
          number of boxes if all_pairs is True.
        np_backbone: numpy module: Either the regular numpy package or jax.numpy.
        all_pairs: Whether to compute IoU between all pairs of boxes or not.
        eps: Epsilon for numerical stability.
  
      Returns:
        If all_pairs == True, returns the pairwise IoU cost matrix of shape
        [bs, n, m]. If all_pairs == False, returns the IoU between corresponding
        boxes. The shape of the return value is then [bs, n].
      """
  
      # First, compute box areas. These will be used later for computing the union.
      wh1 = boxes1[..., 2:] - boxes1[..., :2]
      area1 = wh1[..., 0] * wh1[..., 1]  # [bs, n]
  
      wh2 = boxes2[..., 2:] - boxes2[..., :2]
      area2 = wh2[..., 0] * wh2[..., 1]  # [bs, m]
  
      if all_pairs:
          # Compute pairwise top-left and bottom-right corners of the intersection
          # of the boxes.
          lt = np_backbone.maximum(
              boxes1[..., :, None, :2], boxes2[..., None, :, :2]
          )  # [bs, n, m, 2].
          rb = np_backbone.minimum(
              boxes1[..., :, None, 2:], boxes2[..., None, :, 2:]
          )  # [bs, n, m, 2].
  
          # intersection = area of the box defined by [lt, rb]
          wh = (rb - lt).clip(0.0)  # [bs, n, m, 2]
          intersection = wh[..., 0] * wh[..., 1]  # [bs, n, m]
  
          # union = sum of areas - intersection
          union = (
              area1[..., :, None] + area2[..., None, :] - intersection
          )
  
          iou = intersection / (union + eps)
  
      else:
          # Compute top-left and bottom-right corners of the intersection between
          # corresponding boxes.
          assert (
              boxes1.shape[1] == boxes2.shape[1]
          ), "Different number of boxes when all_pairs is False"
          lt = np_backbone.maximum(
              boxes1[..., :, :2], boxes2[..., :, :2]
          )  # [bs, n, 2]
          rb = np_backbone.minimum(
              boxes1[..., :, 2:], boxes2[..., :, 2:]
          )  # [bs, n, 2]
  
          # intersection = area of the box defined by [lt, rb]
          wh = (rb - lt).clip(0.0)  # [bs, n, 2]
          intersection = wh[..., :, 0] * wh[..., :, 1]  # [bs, n]
  
          # union = sum of areas - intersection.
          union = area1 + area2 - intersection
  
          # Somehow the PyTorch implementation does not use eps to avoid 1/0 cases.
          iou = intersection / (union + eps)
  
      return iou, union
  
file_path: scenic/scenic/model_lib/base_models/box_utils.py
imports: from typing import Any, Union
  import jax.numpy
  import numpy
label_desc: Use image node_id 5 for calling a global function with example usage: box_iou(boxes1, boxes2, np_backbone, all_pairs, eps) and returns: iou,  union