Skip to content

Fix lossy COCO round-trip: preserve area and iscrowd in as_coco#2185

Merged
Borda merged 11 commits into
developfrom
copilot/fix-as-coco-annotation-saving
Mar 30, 2026
Merged

Fix lossy COCO round-trip: preserve area and iscrowd in as_coco#2185
Borda merged 11 commits into
developfrom
copilot/fix-as-coco-annotation-saving

Conversation

Copilot AI commented Mar 30, 2026

Copy link
Copy Markdown
Contributor

DetectionDataset.from_cocoas_cocofrom_coco was not idempotent. The == comparison after a save/reload cycle returned False because detections_to_coco_annotations discarded annotation metadata from detections.data.

Root causes in detections_to_coco_annotations

  • area always overwritten with bbox areabox_width * box_height was used unconditionally, ignoring detections.data["area"] which holds the original COCO annotation area (typically polygon area, not bbox area).
  • iscrowd stored as Python boolcontains_holes(...) or contains_multiple_segments(...) returns a bool; COCO expects int (0/1). Serialized as true/false in JSON.
  • iscrowd reset to 0 when no mask — crowd annotations (iscrowd=1) loaded from COCO were silently demoted to 0 on save if no mask was present.

Fix

# Before
iscrowd = 0
if mask is not None:
    iscrowd = contains_holes(mask=mask) or contains_multiple_segments(mask=mask)
...
"area": box_width * box_height,
"iscrowd": iscrowd,  # Python bool or 0

# After
if mask is not None:
    iscrowd = int(contains_holes(mask=mask) or contains_multiple_segments(mask=mask))
    ...
else:
    iscrowd = int(data.get("iscrowd", 0))  # preserves crowd annotations

area: float = float(data.get("area", box_width * box_height))  # preserves original area

When detections.data has no area/iscrowd (e.g., detections not loaded from COCO), behavior is unchanged — falls back to bbox area and 0 respectively.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI linked an issue Mar 30, 2026 that may be closed by this pull request
2 tasks
Copilot AI changed the title [WIP] Fix as_coco function not saving the annotations as expected Fix lossy COCO round-trip: preserve area and iscrowd in as_coco Mar 30, 2026
Copilot AI requested a review from Borda March 30, 2026 08:11
@codecov

codecov Bot commented Mar 30, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.33333% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 77%. Comparing base (d337154) to head (1ba1023).
⚠️ Report is 1 commits behind head on develop.

Additional details and impacted files
@@           Coverage Diff           @@
##           develop   #2185   +/-   ##
=======================================
- Coverage       77%     77%   -0%     
=======================================
  Files           62      62           
  Lines         7592    7595    +3     
=======================================
+ Hits          5810    5812    +2     
- Misses        1782    1783    +1     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Borda and others added 4 commits March 30, 2026 19:37
- Replace bare int()/float() calls on data.get() with np.asarray(...).item()
  so mypy accepts all possible data dict value types (NDArray | list[Any] | int)

---
Co-authored-by: Claude Code <noreply@anthropic.com>
---
Co-authored-by: Claude Code <noreply@anthropic.com>
---
Co-authored-by: Claude Code <noreply@anthropic.com>
@Borda Borda marked this pull request as ready for review March 30, 2026 17:49
@Borda Borda requested a review from SkalskiP as a code owner March 30, 2026 17:49
Copilot AI review requested due to automatic review settings March 30, 2026 17:49

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.

Pull request overview

This PR fixes COCO export round-tripping for DetectionDataset.from_coco() -> as_coco() -> from_coco() by preserving COCO annotation metadata (area, iscrowd) stored in Detections.data instead of recomputing/overwriting it during export.

Changes:

  • Update detections_to_coco_annotations to read area/iscrowd from detections.data (with sensible fallbacks) and ensure iscrowd is serialized as an int (0/1).
  • Add tests covering preservation of area, preservation of iscrowd when no mask is present, and fallback behavior when metadata is absent.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
src/supervision/dataset/formats/coco.py Preserves area/iscrowd from Detections.data during COCO annotation export and normalizes iscrowd to int.
tests/dataset/formats/test_coco.py Adds regression tests validating the new area/iscrowd export behavior and fallback logic.

Comment thread tests/dataset/formats/test_coco.py Outdated
Comment thread tests/dataset/formats/test_coco.py Outdated
Comment thread tests/dataset/formats/test_coco.py Outdated
Comment thread src/supervision/dataset/formats/coco.py
Borda added 5 commits March 30, 2026 20:07
[resolve #1] Review comment by @copilot (PR #2185):
"isinstance(..., int) does not assert iscrowd isn't a bool because bool is a subclass of int"
[resolve #2] Review comment by @copilot (PR #2185):
"isinstance(..., int) will also pass for bool values — use type(...) is int"
[resolve #3] Review comment by @copilot (PR #2185):
"isinstance(..., int) won't fail if iscrowd is a bool (bool subclasses int)"
[resolve #4] Review comment by @copilot (PR #2185):
"iscrowd is still derived solely from contains_holes/contains_multiple_segments, ignoring data[iscrowd] from COCO"

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.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

@Borda Borda merged commit 38be1be into develop Mar 30, 2026
30 checks passed
@Borda Borda deleted the copilot/fix-as-coco-annotation-saving branch March 30, 2026 18:17
@Borda Borda mentioned this pull request Apr 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

as_coco function not saving the annotations as expected

3 participants