pyronear / pyronear/pyro-annotator
Object-split cross-dedup leaves orphan others_bboxes and duplicates sibling objects across overlapping alerts
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 0
- Forks
- 1
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 2
Description
Symptom
On /classify/48 (alert 55757, camera sampzon-ldd-01), the missed-smoke player shows a dashed others_bboxes box at x≈0.81 — to the right of both objects — that corresponds to no object row of this alert. Annotators reasonably ask "why isn't this an object?"
Forensics (local import of 2026-07-27, camera 99)
Two alert-API alerts overlap in time on the same camera:
| platform alert | lane (sequence id) | own track at | window |
|---|---|---|---|
| 55757 | 48 (primary) | x≈0.44 | 15:45–16:25 |
| 55757 | 49 (sibling 1055757001) |
x≈0.72 | 15:45–16:25 |
| 55738 | 51 (primary) | x≈0.81 | 13:39–16:15 |
| 55738 | 52 (sibling 1055738001) |
x≈0.72 | 15:36–16:15 |
From ~16:13 the shared frames carry three boxes (0.44, 0.72, 0.81). Lane 48/49 detections then hold others_bboxes = [0.72, 0.81], e.g.:
48 | 16:13:31 | own [0.438..0.461] | others [[0.721..0.73], [0.807..0.824]]
Why the 0.81 box has no lane in alert 55757
object_split.split_all_records cross-dedups a sibling cluster whose boxes match another alert sequence's own (bbox-sourced) boxes — here the 0.81 cluster matches alert 55738's primary — so it is intentionally not imported again under 55757. Two follow-on effects make this confusing in the UI:
-
Orphan
others_bboxes. The kept lanes'others_bboxeswere rewritten bysplit_sequence_recordsbefore the drop happens insplit_all_records, so they still reference the dropped cluster's boxes. The classify alert view groups lanes strictly byplatform_alert_id, so the annotator sees a dashed box that belongs to no rail object, with no hint that it is tracked as/classify/51under alert 55738. -
Sibling-vs-sibling duplication (double annotation work). Cross-dedup only compares a sibling's boxes against other sequences' own boxes. The 0.72 plume is
others-sourced in both alerts, so it matches neither side's own boxes and gets imported twice — lane 49 (alert 55757) and lane 52 (alert 55738). The same physical object will be classified twice, potentially with conflicting labels, and each copy shows up as a dashed "sibling" box in the other alert.
Possible directions
- Rewrite the kept groups'
others_bboxesafter cross-dedup (drop the deduped cluster's boxes), and/or annotate them with a provenance marker ("tracked in alert N") the frontend can surface as a link instead of an anonymous dashed box. - Extend cross-dedup to sibling-vs-sibling comparison (same bucket-key + rounded coords machinery), keeping one canonical lane — probably under the alert whose window starts first.
- Frontend-only mitigation: in the classify cockpit's whole-alert player, label dashed boxes as "untracked / tracked elsewhere" so they read as hints, not missing objects.
Related: the object-split design in annotation_api/scripts/data_transfer/ingestion/alert_api/object_split.py (see its module docstring, which already notes the dedup is per-run only), issue #166.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with annotation_api/scripts/data_transfer/ingestion/alert_api/object_split.py and its module docstring, then trace split_sequence_records and split_all_records for the orphan-box and sibling-dedup cases. Review the classify cockpit's whole-alert player before choosing a direction. Done means dropped clusters are not shown as anonymous orphan boxes and the shared sibling object is not imported twice, with issue #166 as related context.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python, typescript
- Domain
- backend, data-engineering, frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100