roboflow/supervision · error · ValueError

masks_true and masks_detection must share the same (H, W); g

Error message

masks_true and masks_detection must share the same (H, W); got {masks_true.shape[1:]} and {masks_detection.shape[1:]}.

What it means

Raised by sv.mask_iou_batch when the two mask batches have matching ndim=3 but different spatial dimensions — masks_true.shape[1:] != masks_detection.shape[1:]. Pairwise overlap is only defined for masks on the same pixel grid, so differing (H, W) is rejected.

Source

Thrown at src/supervision/detection/utils/iou_and_nms.py:853

        ```
    """

    if isinstance(masks_true, CompactMask) and isinstance(masks_detection, CompactMask):
        return compact_mask_iou_batch(masks_true, masks_detection, overlap_metric)

    # Materialise any CompactMask that was passed alongside a dense array.
    if isinstance(masks_true, CompactMask):
        masks_true = np.asarray(masks_true)
    if isinstance(masks_detection, CompactMask):
        masks_detection = np.asarray(masks_detection)

    if masks_true.ndim != 3 or masks_detection.ndim != 3:
        raise ValueError(
            "masks_true and masks_detection must be 3D (N, H, W); got "
            f"ndim={masks_true.ndim} and ndim={masks_detection.ndim}."
        )
    if masks_true.shape[1:] != masks_detection.shape[1:]:
        raise ValueError(
            "masks_true and masks_detection must share the same (H, W); got "
            f"{masks_true.shape[1:]} and {masks_detection.shape[1:]}."
        )
    # A single pass already handles empty inputs and avoids np.vstack([]) below.
    if masks_true.shape[0] == 0 or masks_detection.shape[0] == 0:
        return _mask_iou_batch_split(masks_true, masks_detection, overlap_metric)

    # Peak memory of a single matmul pass: the flattened detection masks (shared
    # across chunks) plus, per true-mask row, its flattened pixels and the three
    # (N, M) matrices it touches (intersection, denominator and output). The
    # previous (N, M, H, W) estimate overcounted by a factor of M and forced
    # needless chunking now that the intersection is a matmul.
    pixels = masks_true.shape[1] * masks_true.shape[2]
    itemsize = 4 if pixels <= 2**24 else 8
    limit_bytes = memory_limit * 1024 * 1024
    detection_bytes = masks_detection.shape[0] * pixels * itemsize
    per_true_row = pixels * itemsize + 3 * masks_detection.shape[0] * 8
    if detection_bytes > limit_bytes > 0:

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Resize one side to the other's (H, W) before calling: e.g. cv2.resize per mask or model postprocess that maps masks back to original image size
  2. Ensure the model's mask postprocess returns masks at input-image resolution
  3. Verify shape[1:] equality with an assert before evaluation loops to catch regressions early

Example fix

# before
ious = sv.mask_iou_batch(gt_masks, det_masks)  # (N,720,1280) vs (M,1080,1920)
# after
import cv2
det_masks = np.stack([cv2.resize(m, (gt_masks.shape[2], gt_masks.shape[1]), interpolation=cv2.INTER_NEAREST) for m in det_masks])
ious = sv.mask_iou_batch(gt_masks, det_masks)
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np

def assert_same_hw(masks_true, masks_detection):
    assert masks_true.ndim == 3 and masks_detection.ndim == 3
    assert masks_true.shape[1:] == masks_detection.shape[1:], (
        f"spatial mismatch: {masks_true.shape[1:]} vs {masks_detection.shape[1:]}"
    )

Prevention

When it happens

Trigger: sv.mask_iou_batch(masks_true, masks_detection) where ground truths are e.g. (N, 720, 1280) and detections (M, 1080, 1920), or any resize applied to one side only.

Common situations: Comparing model outputs against ground truth when the model resizes inputs internally and returns masks at a different resolution; mixing masks from two different cameras/resolutions; a preprocessing resize added to one branch of an evaluation script during refactoring.

Related errors


AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15). Data as JSON: /api/errors/9b43a315cec1ec56. Report an issue: GitHub.