# Difference Between `box_iou`, `box_iou_batch`, and `mask_iou_batch` in Roboflow Supervision

> Understand the differences between box_iou, box_iou_batch, and mask_iou_batch in Roboflow Supervision. Learn how each function handles single boxes, batches, and masks efficiently for your computer vision projects.

- Repository: [Roboflow/supervision](https://github.com/roboflow/supervision)
- Tags: deep-dive
- Published: 2026-04-06

---

**`box_iou` computes IoU for a single pair of bounding boxes and returns a scalar, `box_iou_batch` calculates pairwise IoU for batches of boxes returning an (N, M) matrix, and `mask_iou_batch` handles segmentation masks with automatic memory management for large datasets.**

All three functions reside in [`src/supervision/detection/utils/iou_and_nms.py`](https://github.com/roboflow/supervision/blob/main/src/supervision/detection/utils/iou_and_nms.py) within the [roboflow/supervision](https://github.com/roboflow/supervision) repository. They share a common purpose—measuring spatial overlap—but differ in input dimensionality, vectorization strategy, and memory handling. Each supports the `OverlapMetric` enum to toggle between standard **IoU** (Intersection over Union) and **IOS** (Intersection over Smaller area) calculations.

## Function Comparison Overview

The primary distinction lies in what each function considers an "object" and how many comparisons it performs:

| Function | Input Shape | Output Shape | Computation Scope |
|----------|-------------|--------------|-------------------|
| `box_iou` | Two boxes: `(4,)` and `(4,)` | Scalar `float` | Single pair comparison |
| `box_iou_batch` | Two batches: `(N, 4)` and `(M, 4)` | Matrix `(N, M)` | All pairwise box combinations |
| `mask_iou_batch` | Two mask sets: `(N, H, W)` and `(M, H, W)` | Matrix `(N, M)` | All pairwise mask combinations with memory chunking |

## box_iou – Single Pair Comparison

Use `box_iou` when you need to compare **exactly two axis-aligned bounding boxes**. Located at lines 87-112 in [`iou_and_nms.py`](https://github.com/roboflow/supervision/blob/main/iou_and_nms.py), this function extracts `x_min`, `y_min`, `x_max`, and `y_max` coordinates to compute the intersection rectangle, then divides by either the union (IoU) or the smaller box area (IOS) depending on the `overlap_metric` parameter.

The implementation is lightweight and scalar-focused, making it ideal for debugging loops or simple threshold checks where vectorization overhead is unnecessary.

## box_iou_batch – Vectorized Box Overlaps

When evaluating detection pipelines or implementing Non-Maximum Suppression (NMS), use `box_iou_batch`. This function accepts two NumPy arrays of shape `(N, 4)` and `(M, 4)`, then leverages broadcasting (`[:, None]` and `[None, :]`) to generate the full `(N, M)` intersection matrix without Python loops.

According to the source code at lines 158-187, the function transposes input arrays to create 1-D coordinate views, computes intersection widths and heights via broadcasting, and returns a `float32` matrix. It handles empty inputs gracefully by returning an empty `(0, 0)` array. This vectorized approach powers the library's `box_non_max_suppression` and `box_non_max_merge` utilities.

## mask_iou_batch – Segmentation Mask Overlaps

For instance segmentation tasks, `mask_iou_batch` operates on **binary masks** rather than bounding boxes. It accepts tensors of shape `(N, H, W)` and `(M, H, W)`, where H and W represent image height and width.

The implementation (lines 54-84 for the public wrapper, lines 401-452 for core logic) addresses a critical memory constraint: computing IoU for all mask pairs simultaneously can exhaust RAM. The function estimates required memory and, if it exceeds the default `memory_limit` of 5 GB, automatically falls back to `_mask_iou_batch_split`. This chunked approach processes slices of the true mask set iteratively, returning a `float64` matrix. This routine underpins `mask_non_max_suppression` and mask merging operations.

## Practical Code Examples

```python
import numpy as np
import supervision as sv

# 1️⃣ box_iou – single pair comparison

box_a = [100, 100, 200, 200]  # x_min, y_min, x_max, y_max

box_b = [150, 150, 250, 250]
iou = sv.box_iou(box_a, box_b)
print(f"Single IoU: {iou:.3f}")  # Output: 0.143

# 2️⃣ box_iou_batch – matrix of overlaps

true_boxes = np.array([[100, 100, 200, 200], [300, 300, 400, 400]])
det_boxes = np.array([[150, 150, 250, 250], [320, 320, 420, 420]])
iou_matrix = sv.box_iou_batch(true_boxes, det_boxes)
print("Box IoU Matrix:\n", iou_matrix)

# Output: [[0.142857, 0.        ],

#          [0.        , 0.470588]]

# 3️⃣ mask_iou_batch – segmentation masks

mask_true = np.stack([np.eye(5, dtype=np.uint8), np.zeros((5, 5), dtype=np.uint8)])
mask_det = np.stack([np.eye(5, dtype=np.uint8), np.ones((5, 5), dtype=np.uint8)])
mask_matrix = sv.mask_iou_batch(mask_true, mask_det)
print("Mask IoU Matrix:\n", mask_matrix)

# Output: [[1. , 0. ],

#          [0. , 0.2]]

```

## Summary

- **`box_iou`** handles scalar comparisons of individual bounding boxes at lines 87-112, returning a single float value.
- **`box_iou_batch`** provides fully vectorized pairwise IoU calculations for box batches using broadcasting (lines 158-187), returning an `(N, M)` float32 matrix.
- **`mask_iou_batch`** processes binary segmentation masks with automatic memory management via chunking (lines 54-84), returning an `(N, M)` float64 matrix.
- All three functions support the `overlap_metric` parameter to switch between IoU and IOS calculation modes.
- Use scalar `box_iou` for debugging, `box_iou_batch` for detection metrics and NMS, and `mask_iou_batch` for instance segmentation evaluation.

## Frequently Asked Questions

### What is the difference between IoU and IOS in these functions?

**IoU** (Intersection over Union) divides the intersection area by the union of both boxes or masks, penalizing large non-overlapping regions. **IOS** (Intersection over Smaller) divides by the area of the smaller object, which is useful when you want to measure containment rather than symmetric overlap. Both metrics are controlled via the `overlap_metric` parameter, which accepts `OverlapMetric.IOU` or `OverlapMetric.IOS` as defined in [`src/supervision/detection/utils/iou_and_nms.py`](https://github.com/roboflow/supervision/blob/main/src/supervision/detection/utils/iou_and_nms.py).

### How does `mask_iou_batch` handle large datasets without running out of memory?

The function estimates the memory required for the full `(N, M, H, W)` computation. If this exceeds the `memory_limit` parameter (default 5 GB), it automatically triggers `_mask_iou_batch_split` to process the true masks in smaller chunks, accumulation results incrementally. This allows processing of arbitrarily large mask batches on memory-constrained hardware.

### When should I use `box_iou` instead of `box_iou_batch`?

Use `box_iou` when you need to compare exactly two boxes and require a scalar return value, such as inside a Python loop with conditional breakpoints or simple threshold checks. For any operation requiring multiple comparisons—such as computing assignment costs for the Hungarian algorithm or performing Non-Maximum Suppression—use `box_iou_batch` to leverage vectorized NumPy operations and avoid slow Python loops.

### Can these functions handle rotated or oriented bounding boxes?

No, these specific functions only support **axis-aligned** bounding boxes defined by `[x_min, y_min, x_max, y_max]`. For oriented bounding boxes, the supervision library provides separate utilities in [`src/supervision/detection/utils/converters.py`](https://github.com/roboflow/supervision/blob/main/src/supervision/detection/utils/converters.py) (such as `polygon_to_mask`) that convert polygons to masks, which can then be processed with `mask_iou_batch` if pixel-level overlap is required.