Skip to content
Back to skills

Multi Annotator Bbox Consensus

ASecurity

Merges overlapping same-class bounding boxes from multiple annotators into a consensus box using IoU-based matching and intersection.

  • 61 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 12, 2026
documentationpython

Security analysis

A100/100

Scanned September 12, 2026

npx -y skills add wenmin-wu/ds-skills --skill multi-annotator-bbox-consensus --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Multi Annotator Bbox Consensus?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Multi Annotator Bbox Consensus
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/wenmin-wu-multi-annotator-bbox-consensus/badge)](https://www.skillsdirectory.com/skills/wenmin-wu-multi-annotator-bbox-consensus)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: cv-multi-annotator-bbox-consensus
description: >
  Merges overlapping same-class bounding boxes from multiple annotators into a consensus box using IoU-based matching and intersection.
---
# Multi-Annotator Bbox Consensus

## Overview

Datasets annotated by multiple experts (radiologists, pathologists) contain duplicate and conflicting bounding boxes for the same object. Using all raw annotations introduces noise; using only one annotator discards information. This technique groups overlapping same-class boxes by IoU, then computes a consensus box — either the intersection (inner box, conservative) or union (outer box, inclusive). Reduces annotation noise and improves detector training, especially when annotators have varying skill levels.

## Quick Start

```python
import numpy as np

def compute_iou(box1, box2):
    x1 = max(box1[0], box2[0])
    y1 = max(box1[1], box2[1])
    x2 = min(box1[2], box2[2])
    y2 = min(box1[3], box2[3])
    if x2 < x1 or y2 < y1:
        return 0.0
    inter = (x2 - x1) * (y2 - y1)
    area1 = (box1[2]-box1[0]) * (box1[3]-box1[1])
    area2 = (box2[2]-box2[0]) * (box2[3]-box2[1])
    return inter / (area1 + area2 - inter)

def consensus_box(boxes, mode='inner'):
    """Compute consensus from overlapping boxes."""
    boxes = np.array(boxes)
    if mode == 'inner':  # intersection
        return [boxes[:,0].max(), boxes[:,1].max(),
                boxes[:,2].min(), boxes[:,3].min()]
    else:  # union
        return [boxes[:,0].min(), boxes[:,1].min(),
                boxes[:,2].max(), boxes[:,3].max()]

def merge_annotations(annots, iou_thresh=0.0, mode='inner'):
    """Merge same-class overlapping boxes from multiple annotators."""
    merged = []
    used = set()
    for i, (cls_i, box_i) in enumerate(annots):
        if i in used:
            continue
        group = [box_i]
        for j, (cls_j, box_j) in enumerate(annots):
            if j <= i or j in used or cls_i != cls_j:
                continue
            if compute_iou(box_i, box_j) > iou_thresh:
                group.append(box_j)
                used.add(j)
        merged.append((cls_i, consensus_box(group, mode)))
    return merged
```

## Workflow

1. Group annotations by image_id
2. For each same-class pair, compute IoU
3. Cluster overlapping boxes (IoU > threshold)
4. Compute consensus box per cluster (inner or outer)
5. Use consensus annotations for training

## Key Decisions

- **Inner vs outer**: Inner (intersection) is conservative, reduces box size; outer (union) is inclusive
- **IoU threshold**: 0.0 merges any overlapping boxes; 0.3–0.5 requires significant overlap
- **Minimum annotators**: Optionally require 2+ annotators to agree before keeping a box
- **Weighted average**: Use annotator-weighted mean of coordinates instead of hard intersection

## References

- [Visual In-Depth EDA – VinBigData](https://www.kaggle.com/code/dschettler8845/visual-in-depth-eda-vinbigdata-competition-data)

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…