Skip to content
AI360Xpert
Beta

Intersection over Union Scores Box Overlap

Intersection over Union divides the overlap of two boxes by their combined area, giving one number between 0 and 1 for how well boxes agree.

Intersection over Union scores box agreement as overlap divided by combined area, with upgrades that still guide boxes that miss entirely
Intersection over Union scores box agreement as overlap divided by combined area, with upgrades that still guide boxes that miss entirely

Why Does This Exist?

Detectors output coordinates, but coordinate distance means nothing: is 5 pixels off good or terrible? It depends on box size. IoU normalizes agreement into one scale-free number used in four jobs: matching anchors to ground truth, labeling positives during training, suppressing duplicates in non-maximum suppression, and deciding true positives in evaluation. One metric, four jobs, which is why every detection page leans on it.

The general detection setup lives in object detection, and the boxes IoU matches start life as anchor boxes. Mask versions of the same ratio live on the IoU and Dice page.

Think of It Like This

Two picnic blankets on the grass

Two groups spread blankets that partly overlap. Overlap alone says little: 2 shared square meters matters differently for handkerchiefs versus circus tents. Divide the shared area by the total grass covered by either blanket and agreement becomes independent of blanket size.

That ratio is IoU: identical blankets score 1, blankets touching at a corner score 0, and a strong partial overlap lands near 0.74. Where it stops: blankets that do not touch all score 0 no matter how far apart they lie, so the ratio alone cannot guide a lost blanket home.

How It Actually Works

For boxes AA and BB, IoU=Area(A∩B)/Area(A∪B)\text{IoU} = \text{Area}(A \cap B) / \text{Area}(A \cup B). The convention is fixed: IoU at or above 0.50.5 usually counts as a true positive, and matching plus evaluation keep plain IoU even when training uses its upgrades. Plain IoU gives zero gradient when boxes do not touch, which stalls box regression at initialization.

The upgrades fix the stall. GIoU subtracts the empty space inside the smallest enclosing box, staying informative below zero. DIoU adds a center-distance penalty for faster convergence, and CIoU adds aspect-ratio consistency for tighter final boxes. Use CIoU or DIoU as the regression loss and keep plain IoU for matching and scoring.

Worked example

Take box A [50,50,150,150][50, 50, 150, 150] and box B [58,58,158,158][58, 58, 158, 158]. Each covers 100×100=10,000100 \times 100 = 10{,}000 pixels. The overlap runs xx from 5858 to 150150 and yy from 5858 to 150150, so 92×92=8,46492 \times 92 = 8{,}464 pixels. The union is 10,000+10,000−8,464=11,53610{,}000 + 10{,}000 - 8{,}464 = 11{,}536. IoU is 8,464/11,536≈0.73378{,}464 / 11{,}536 \approx 0.7337, about 0.730.73: comfortably above the 0.50.5 true-positive line, so these count as the same object.

GIoU on the same pair: the enclosing box [50,50,158,158][50, 50, 158, 158] covers 108×108=11,664108 \times 108 = 11{,}664. GIoU is 0.7337−(11,664−11,536)/11,664=0.7337−0.0110≈0.72270.7337 - (11{,}664 - 11{,}536) / 11{,}664 = 0.7337 - 0.0110 \approx 0.7227. Nearly identical here because the boxes nearly coincide; on a clean miss the penalty term is what keeps training alive.

Code

The point of this snippet is the ratio itself: pure standard-library code recomputes the worked example exactly.

def compute_iou(box1: list, box2: list) -> float:    x1, y1 = max(box1[0], box2[0]), max(box1[1], box2[1])    x2, y2 = min(box1[2], box2[2]), min(box1[3], box2[3])    inter = max(0, x2 - x1) * max(0, y2 - y1)    a1 = (box1[2] - box1[0]) * (box1[3] - box1[1])    a2 = (box2[2] - box2[0]) * (box2[3] - box2[1])    return round(inter / (a1 + a2 - inter), 4)
print(compute_iou([50, 50, 150, 150], [58, 58, 158, 158]))# -> 0.7337

Boxes offset by 88 pixels on a 100100-pixel side score 0.73370.7337. Below the 0.50.5 line they would count as different objects.

Watch Out For

One threshold for all object sizes

IoU 0.50.5 on a 20-pixel object tolerates far sloppier absolute errors than on a 400-pixel one, yet teams judge both by the same line. The symptom is small-object scores that look fine and mean little. Report across thresholds, as COCO-style AP does, instead of a single number.

IoU loss on non-overlapping starts

Plain IoU as a regression loss gives exactly zero gradient when prediction and target are disjoint, freezing early training. The symptom is boxes that never move from initialization. Use GIoU, DIoU, or CIoU for the loss while keeping IoU for decisions.

The Quick Version

  • IoU is overlap area divided by union area: 0 for disjoint boxes, 1 for identical ones.
  • The fixture scores 8,464/11,536≈0.738{,}464 / 11{,}536 \approx 0.73, above the 0.50.5 true-positive line.
  • GIoU on the pair gives about 0.72270.7227; on clean misses its penalty keeps gradients alive.
  • Use plain IoU for matching and scoring, DIoU or CIoU for regression losses.