open-mmlab/mmdetection · warning

Y2 < Y1 value in box. Swap them.

Error message

Y2 < Y1 value in box. Swap them.

What it means

Emitted by prefilter_boxes in WBF when a box has y2 < y1 — the vertical corners are reversed. The code swaps y1 and y2 so the box becomes valid and fusion continues. Like its X counterpart it is a data-hygiene warning, not a failure.

Source

Thrown at mmdet/models/utils/wbf.py:168

            exit()

        for j in range(len(boxes[t])):
            score = scores[t][j]
            if score < thr:
                continue
            label = int(labels[t][j])
            box_part = boxes[t][j]
            x1 = float(box_part[0])
            y1 = float(box_part[1])
            x2 = float(box_part[2])
            y2 = float(box_part[3])

            # Box data checks
            if x2 < x1:
                warnings.warn('X2 < X1 value in box. Swap them.')
                x1, x2 = x2, x1
            if y2 < y1:
                warnings.warn('Y2 < Y1 value in box. Swap them.')
                y1, y2 = y2, y1
            if (x2 - x1) * (y2 - y1) == 0.0:
                warnings.warn('Zero area box skipped: {}.'.format(box_part))
                continue

            # [label, score, weight, model index, x1, y1, x2, y2]
            b = [
                int(label),
                float(score) * weights[t], weights[t], t, x1, y1, x2, y2
            ]

            if label not in new_boxes:
                new_boxes[label] = []
            new_boxes[label].append(b)

    # Sort each list in dict by score and transform it to numpy array
    for k in new_boxes:
        current_boxes = np.array(new_boxes[k])

View on GitHub (pinned to cfd5d3a985)

Solutions

  1. Fix the cx,cy,w,h → x1,y1,x2,y2 conversion: y1 = cy - h/2, y2 = cy + h/2 (signs, not both minus).
  2. Clamp/swap coordinates defensively before fusion: y1, y2 = min(y1, y2), max(y1, y2).
  3. Verify flip/TTA post-processing restores the original coordinate frame before feeding WBF.
  4. Silence expected noise with warnings.filterwarnings('ignore', message='Y2 < Y1 value in box.*').

Example fix

# before
y1, y2 = cy - h / 2, cy - h / 2  # typo: both minus
# after
y1, y2 = cy - h / 2, cy + h / 2
Defensive patterns

Strategy: validation

Validate before calling

def sanitize_y(boxes):
    boxes = np.asarray(boxes, dtype=np.float64).copy()
    y1, y2 = boxes[:, 1], boxes[:, 3]
    boxes[:, 1], boxes[:, 3] = np.minimum(y1, y2), np.maximum(y1, y2)
    return boxes

Type guard

def has_valid_y_order(boxes):
    boxes = np.asarray(boxes)
    return bool((boxes[:, 3] >= boxes[:, 1]).all())

Prevention

When it happens

Trigger: Calling weighted_boxes_fusion() with a boxes entry where box[3] < box[1]. Happens when image-space y axis is flipped (e.g. top-left vs bottom-left origin conventions), when height is subtracted instead of added (y2 = cy - h/2 instead of cy + h/2), or with flipped images in TTA where coordinates are not un-flipped.

Common situations: Mixing coordinate systems from different detection backends (COCO vs Albumentations vs pixel coordinates); h-flip TTA augmentations where the inverse transform was not applied to y; hand-written cxcywh→xyxy converters with a typo'd sign.

Related errors


AI-assisted analysis of open-mmlab/mmdetection@cfd5d3a985 (2026-08-27). Data as JSON: /api/errors/fc1108d31b6f1ce5. Report an issue: GitHub.