Difference Between `box_iou`, `box_iou_batch`, and `mask_iou_batch` in Roboflow Supervision
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 within the 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, 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
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_iouhandles scalar comparisons of individual bounding boxes at lines 87-112, returning a single float value.box_iou_batchprovides fully vectorized pairwise IoU calculations for box batches using broadcasting (lines 158-187), returning an(N, M)float32 matrix.mask_iou_batchprocesses binary segmentation masks with automatic memory management via chunking (lines 54-84), returning an(N, M)float64 matrix.- All three functions support the
overlap_metricparameter to switch between IoU and IOS calculation modes. - Use scalar
box_ioufor debugging,box_iou_batchfor detection metrics and NMS, andmask_iou_batchfor 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.
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 (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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →