roboflow/supervision · error · TypeError

box coordinates must be real-valued

Error message

box coordinates must be real-valued

What it means

Raised by sv.box_iou when either bounding box contains complex-valued coordinates (np.iscomplexobj true). IoU is defined over real geometry, so complex inputs indicate an upstream data error and are rejected explicitly instead of producing nonsense values or a subtle NumPy cast.

Source

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

        ValueError: If `overlap_metric` is not IOU or IOS.

    Examples:
        ```pycon
        >>> import supervision as sv
        >>> box_true = [100, 100, 200, 200]
        >>> box_detection = [150, 150, 250, 250]
        >>> sv.box_iou(box_true, box_detection, overlap_metric=sv.OverlapMetric.IOU)
        0.142857...
        >>> sv.box_iou(box_true, box_detection, overlap_metric=sv.OverlapMetric.IOS)
        0.25

        ```
    """
    overlap_metric = OverlapMetric.from_value(overlap_metric)
    box_true_array = np.asarray(box_true)
    box_detection_array = np.asarray(box_detection)
    if np.iscomplexobj(box_true_array) or np.iscomplexobj(box_detection_array):
        raise TypeError("box coordinates must be real-valued")

    x_min_true, y_min_true, x_max_true, y_max_true = box_true_array
    x_min_det, y_min_det, x_max_det, y_max_det = box_detection_array

    x_min_inter = max(x_min_true, x_min_det)
    y_min_inter = max(y_min_true, y_min_det)
    x_max_inter = min(x_max_true, x_max_det)
    y_max_inter = min(y_max_true, y_max_det)

    inter_w = max(0.0, _coordinate_difference(x_max_inter, x_min_inter))
    inter_h = max(0.0, _coordinate_difference(y_max_inter, y_min_inter))

    area_inter = inter_w * inter_h

    area_true = _coordinate_difference(x_max_true, x_min_true) * _coordinate_difference(
        y_max_true, y_min_true
    )
    area_det = _coordinate_difference(x_max_det, x_min_det) * _coordinate_difference(

View on GitHub (pinned to 7f254d9784)

Solutions

  1. Take the real part before calling: boxes = np.real(np.asarray(boxes))
  2. Fix the upstream step that produced complex coordinates if complex values are unexpected
  3. If complex tensors come from PyTorch, convert with .real before turning into numpy

Example fix

# before
iou = sv.box_iou(np.array([0,0,10,10], dtype=complex), [5,5,15,15])
# after
iou = sv.box_iou(np.real(np.array([0,0,10,10])), [5,5,15,15])
Defensive patterns

Strategy: type-guard

Validate before calling

import numpy as np

def as_real_boxes(boxes):
    arr = np.asarray(boxes)
    if np.iscomplexobj(arr):
        arr = np.real(arr)
    return arr

Type guard

def is_real_valued_boxes(boxes) -> bool:
    import numpy as np
    return not np.iscomplexobj(np.asarray(boxes))

Prevention

When it happens

Trigger: sv.box_iou(box_true, box_detection) where either argument is a complex dtype array, e.g. boxes produced by an FFT-based pipeline, complex-valued model outputs, or accidental dtype propagation (np.zeros(4, dtype=complex) defaults).

Common situations: Signal-processing or frequency-domain preprocessing leaking complex dtype into downstream box code; loading boxes from a complex-typed tensor (torch.complex) without conversion; a bug that mixes complex intermediates into coordinate arrays.

Related errors


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