open-mmlab/mmdetection · warning
Zero area box skipped: {}.
Error message
Zero area box skipped: {}. What it means
prefilter_boxes in WBF drops (continue) any box whose area (x2-x1)*(y2-y1) equals 0.0 and warns with the offending box_part. A zero-area box (a line or point, or a degenerate box where x1==x2 or y1==y2) cannot participate in IoU-based fusion, so it is excluded from the result. This is the only one of the three box checks that actually removes data.
Source
Thrown at mmdet/models/utils/wbf.py:171
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])
new_boxes[k] = current_boxes[current_boxes[:, 1].argsort()[::-1]]
return new_boxesView on GitHub (pinned to cfd5d3a985)
Solutions
- Filter degenerate boxes before fusion: keep = (b[:, 2] > b[:, 0]) & (b[:, 3] > b[:, 1]) then pass b[keep].
- Clamp cxcywh sizes away from zero (w = max(w, eps), h = max(h, eps)) in your conversion code if zero-size boxes are spurious.
- Inspect the emitting model if zero-area boxes appear frequently — it usually signals a broken bbox head, bad regression targets, or a data annotation problem.
- If occasional drops are acceptable, ignore the warning: warnings.filterwarnings('ignore', message='Zero area box skipped.*').
Example fix
# before labels, scores, boxes = weighted_boxes_fusion(boxes_list, labels_list, scores_list) # after boxes_list = [[b for b in bl if (b[2] - b[0]) > 0 and (b[3] - b[1]) > 0] for bl in boxes_list] labels, scores, boxes = weighted_boxes_fusion(boxes_list, labels_list, scores_list)
Defensive patterns
Strategy: validation
Validate before calling
def drop_degenerate(boxes, labels=None, scores=None):
boxes = np.asarray(boxes)
keep = (boxes[:, 2] - boxes[:, 0]) > 0
if labels is None:
return boxes[keep]
return boxes[keep], [l for l, k in zip(labels, keep) if k], [s for s, k in zip(scores, keep) if k] Type guard
def all_positive_area(boxes):
boxes = np.asarray(boxes)
return bool(((boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1]) > 0).all()) Prevention
- Filter (x2-x1)>0 and (y2-y1)>0 before calling weighted_boxes_fusion.
- Clamp w,h in cxcywh space to a small epsilon during conversion.
- Investigate the source model if degenerate boxes recur — usually upstream regression issues.
When it happens
Trigger: Passing weighted_boxes_fusion() a boxes entry where x2 == x1 or y2 == y2-y1 == 0 — e.g. a clamped box at an image edge, a cxcywh box with w=0 or h=0, or float rounding that collapses a dimension to exactly 0.0. Note the exact == 0.0 comparison: only exactly-zero areas are skipped, not tiny ones.
Common situations: Models that regress zero width/height for very small or failed detections; boxes clipped to image bounds where the object is entirely outside so x1==x2 at the border; ensembling overconfidence-prone single-stage detectors that emit degenerate proposals.
Related errors
- X2 < X1 value in box. Swap them.
- Y2 < Y1 value in box. Swap them.
- LoadImageFromFile is not found in the test pipeline
- Visualization needs the "visualizer" termdefined in the conf
- Unsupported input type: {type(single_input)}
AI-assisted analysis of open-mmlab/mmdetection@cfd5d3a985 (2026-08-27).
Data as JSON: /api/errors/1af6a6bbdeef8e59.
Report an issue: GitHub.