ML Grind

IoU (Intersection over Union) - CNNs & Computer Vision

Implement IoU (Intersection over Union) in Python with NumPy. easy exercise with examples, hints, and instant feedback. No setup or signup required.

IoU (Intersection over Union)

What you'll build

The Intersection over Union of two axis-aligned bounding boxes.

Background

IoU is the basic overlap measure of object detection. It decides whether a prediction counts as a true positive (IoU >= 0.5 for PASCAL VOC, 0.5 to 0.95 for COCO mAP), which anchors are matched to ground truth during training, and which boxes NMS suppresses. It is scale invariant: two boxes overlapping by the same fraction score the same whatever their size.

Box format: xyxy

Each box is [x1, y1, x2, y2]: (x1, y1) is the top-left corner and (x2, y2) the bottom-right corner, with x2 >= x1 and y2 >= y1 (image coordinates, y grows downward). Coordinates are continuous, so a box's area is (x2 - x1) * (y2 - y1). Other formats exist: COCO stores xywh = [x, y, width, height] and YOLO stores cxcywh = [center_x, center_y, width, height]. Convert them to xyxy first.

Formula

ix1 = max(a_x1, b_x1)     iy1 = max(a_y1, b_y1)      # intersection top-left
ix2 = min(a_x2, b_x2)     iy2 = min(a_y2, b_y2)      # intersection bottom-right
intersection = max(0, ix2 - ix1) * max(0, iy2 - iy1)
union        = area_a + area_b - intersection
IoU          = intersection / union                   # in [0, 1]

Inputs

  • box_a, box_b: length-4 arrays or lists [x1, y1, x2, y2] of ints or floats.

Expected return format

A Python float rounded to 4 decimal places.

Edge cases and conventions

  • Disjoint boxes, or boxes that only touch along an edge, have IoU 0.0. Clamp the intersection width and height at 0 separately; a negative width times a negative height would otherwise look like a positive overlap.
  • If the union is 0 (two zero-area boxes), return 0.0.
  • No +1 pixel convention: areas use x2 - x1, not x2 - x1 + 1.

Constraints

Plain Python or NumPy.

Follow-up

  • Vectorise it: compute an (N, M) IoU matrix between two sets of boxes with broadcasting.
  • What do GIoU, DIoU and CIoU add, and why are they better regression losses than 1 - IoU?

Examples

Input: box_a = [0, 0, 2, 2], box_b = [1, 1, 3, 3]
Output: 0.1429

Intersection is the 1x1 square [1, 1, 2, 2]; union = 4 + 4 - 1 = 7; IoU = 1/7.

Input: box_a = [0, 0, 4, 4], box_b = [2, 0, 6, 4]
Output: 0.3333

Intersection is 2 x 4 = 8; union = 16 + 16 - 8 = 24.

Input: box_a = [0, 0, 1, 1], box_b = [2, 2, 3, 3]
Output: 0.0

No overlap: the clamped intersection width and height are 0.

Practice in Python

import numpy as np

def iou(box_a, box_b):
    """
    Intersection over Union of two boxes in xyxy format.

    Args:
        box_a: [x1, y1, x2, y2], top-left (x1, y1) and bottom-right (x2, y2)
        box_b: [x1, y1, x2, y2]

    Returns:
        IoU as a Python float in [0, 1], rounded to 4 decimal places
        (0.0 when the union is 0)
    """
    # Your code here
    pass

The interactive editor loads with Python and NumPy. Run your implementation against 7 tests, or use the progressive hints.

More exercises in this section →