Skip to course content
Free computer vision course

Computer Vision and Multimodal AI

Unit 08.01: IoU, and why 0.5 is a choice

IoU turns two boxes into one number, and the threshold that calls it a hit is a choice.

0.5 is a convention

Four predictions against one ground-truth box.

The code computes IoU for each and applies a 0.5 threshold.

def iou(a, b):
    ax1, ay1, ax2, ay2 = a
    bx1, by1, bx2, by2 = b
    ix1, iy1 = max(ax1, bx1), max(ay1, by1)
    ix2, iy2 = min(ax2, bx2), min(ay2, by2)
    inter = max(0, ix2 - ix1) * max(0, iy2 - iy1)
    union = ((ax2 - ax1) * (ay2 - ay1) + (bx2 - bx1) * (by2 - by1) - inter)
    return inter / union


truth = (10, 10, 50, 50)
for name, pred in [("exact", (10, 10, 50, 50)),
                   ("off by 5px", (15, 15, 55, 55)),
                   ("half overlap", (30, 10, 70, 50)),
                   ("twice the size", (0, 0, 60, 60))]:
    score = iou(truth, pred)
    print(f"{name:16} IoU {score:.2f}  counts as a hit at 0.5: {score >= 0.5}")

print("\n0.5 is a convention. At 0.75 the 'off by 5px' box becomes a miss")

# The IoU threshold decides what "detected" means, and moving it changes every
# reported number without changing the model. Report the threshold with the
# metric, always.

The box off by five pixels scores 0.68 - a hit at 0.5 and a miss at 0.75. Moving the threshold changes every reported number without changing the model at all.

Which threshold is right depends on what the box is for. Cropping a region for a downstream classifier tolerates loose boxes; measuring an object's dimensions does not.

The mistake this prevents

The mistake is reporting detection metrics without the IoU threshold. mAP at 0.5 and at 0.5:0.95 are different numbers for the same model, and comparing across papers or across teams without it is meaningless.

Takeaway

Report the IoU threshold with every detection metric. It is a choice that moves every number, and it should follow from what the box is used for.