Skip to content

fix(dataset): preserve LabelMe instance grouping - #2640

Merged
Borda merged 6 commits into
roboflow:developfrom
INo-xious:fix/labelme-instance-grouping
Sep 30, 2026
Merged

Borda merged 6 commits into
roboflow:developfrom
INo-xious:fix/labelme-instance-grouping

Conversation

@INo-xious

Copy link
Copy Markdown
Contributor

Description

LabelMe export writes each disconnected region of a detection mask as a polygon, but previously left every group_id null. Import also ignored explicit groups, so one instance became multiple detections. This change exports shared IDs for disconnected components and imports shapes with the same (label, group_id) as one detection with a union mask and enclosing box.

Minimal reproduction on develop:

import numpy as np
import supervision as sv
from supervision.dataset.formats.labelme import (
    detections_to_labelme_shapes,
    labelme_shapes_to_detections,
)

mask = np.zeros((1, 48, 64), dtype=bool)
mask[0, 5:15, 5:15] = True
mask[0, 30:40, 30:40] = True
detections = sv.Detections(
    xyxy=np.array([[5, 5, 39, 39]], dtype=np.float32),
    class_id=np.array([0]),
    mask=mask,
)
shapes = detections_to_labelme_shapes(detections, ["dog"])
result = labelme_shapes_to_detections(shapes, {"dog": 0}, (64, 48), True)
len(result)  # Before: 2; after: 1

Motivation and Context

Instance membership must survive LabelMe conversion. LabelMe's own instance-segmentation converter groups by (label, group_id), unions masks, and treats only missing/null group IDs as ungrouped.

#2299 introduced LabelMe support; its multicomponent test checked polygon output without checking preserved instance count. Open #2637 concerns image copying into the source folder and addresses a separate failure.

Changes Made

  • Import explicit groups, including group_id=0, using mask unions and enclosing component boxes. Missing/null IDs, different groups, and different labels remain independent.
  • Export a shared numeric group ID for each mask with multiple polygon components. Existing single-polygon, rectangle, and empty-mask fallback behavior remains intact.
  • Add focused grouping and round-trip regression coverage, update the affected public docstrings, and add an Unreleased changelog entry.

Testing

All commands ran in this branch's own worktree using Python 3.11 and the default NumPy fallback backend:

  • Clean develop baseline, uv run pytest -q: 4316 passed, 24 skipped.

  • New/updated tests against unmodified production code, uv run pytest tests/dataset/formats/test_labelme.py -q: 15 failed, 44 passed. Failures show explicit groups remaining split, missing export group IDs, and round trips producing two/four detections instead of one/two.

  • With the fix, the same focused command: 59 passed.

  • uv run pytest --cov=supervision: 4335 passed, 24 skipped, 91% total coverage.

  • uv run pytest --doctest-modules src/supervision/dataset/formats/labelme.py src/supervision/dataset/core.py: 3 passed.

  • uv run pre-commit run --all-files: all hooks passed, including mypy.

  • git diff --check: passed.

  • Added/updated tests, and the full suite passes locally

  • Updated docs (docstrings / mkdocs entry) for new or changed public API

  • Added a changelog entry in docs/changelog.md under Unreleased (skip for lint/type/format-only or pure doc changes)

Additional Notes

The base is 8c7df2388ce46f16139edc498c2bc3874493b4bc. Polygon rasterization fidelity is unchanged; numeric group IDs are regenerated on export because Detections stores instance membership, not LabelMe IDs. The 24 skips also occur on the clean baseline. Native OpenCV was not installed for these runs.

@INo-xious
INo-xious requested a review from SkalskiP as a code owner September 29, 2026 05:15
@CLAassistant

CLAassistant commented Sep 29, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@Borda
Borda requested a balanced review from Copilot September 29, 2026 05:52
@Borda Borda added the bug Something isn't working label Sep 29, 2026
@Borda

Borda commented Sep 29, 2026

Copy link
Copy Markdown
Member

Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.

@INo-xious ^^ 🙏

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

The focused implementation matches LabelMe semantics and includes comprehensive regression coverage.

Review effort: Balanced
Findings: None

What changed in this PR

Preserves LabelMe instance grouping across import and export.

Changes:

  • Groups shapes by (label, group_id) and unions masks/boxes.
  • Assigns shared IDs to disconnected mask components.
  • Adds regression tests, documentation, and changelog entry.

Assessment: Code quality 5/5 · Testing 5/5 · Documentation 5/5

File Description
src/​supervision/​dataset/​formats/​labelme.py Implements grouping and shared export IDs.
src/​supervision/​dataset/​core.py Documents grouping behavior.
tests/​dataset/​formats/​test_labelme.py Covers grouping and round trips.
docs/​changelog.md Records the fix.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@Borda Borda changed the title fix(dataset): preserve LabelMe instance grouping fix(dataset): preserve LabelMe instance grouping Sep 29, 2026
@Borda
Borda marked this pull request as ready for review September 29, 2026 06:12
@codecov

codecov Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92%. Comparing base (a2e80c9) to head (d2e05b7).
⚠️ Report is 1 commits behind head on develop.

Additional details and impacted files
@@           Coverage Diff           @@
##           develop   #2640   +/-   ##
=======================================
  Coverage       92%     92%           
=======================================
  Files           78      78           
  Lines        11733   11748   +15     
=======================================
+ Hits         10759   10774   +15     
  Misses         974     974           
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Changes:
- Add an A/B/A grouped-shape regression case in the LabelMe importer tests, asserting first-seen detection order, combined group bounds, and union masks.
- Keep the fix scoped to test coverage; no library behavior or public API changes are included.

Impact:
- Protects against grouping implementations that split or reorder repeated shapes when another group appears between them.
- Makes both detection ordering and per-group geometry/mask combination part of the importer contract.

Verification:
- Focused LabelMe tests: 60 passed.
- Recorded gates: lint, format, types, full tests, and review passed; `git diff --cached --check` passed.

Residual limits:
- Current-head Codecov evidence is still pending; local coverage does not refresh the remote status.
- The remediation result artifact remains unvalidated because the frozen work-bucket plan conflicts with the selected skill validator contract.

---

Co-authored-by: Codex <[email protected]>
@Borda
Borda merged commit 93faa58 into roboflow:develop Sep 30, 2026
36 checks passed
Borda added a commit that referenced this pull request Oct 4, 2026
* fix(dataset): preserve LabelMe instance grouping
* docs: link LabelMe instance grouping pull request
* test(tests): cover interleaved LabelMe groups

---------

Co-authored-by: jirka <[email protected]>
Co-authored-by: Codex <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants