Replace global class-variable track ID counters with per-instance allocators#419
Open
cdeil wants to merge 1 commit into
Open
Replace global class-variable track ID counters with per-instance allocators#419cdeil wants to merge 1 commit into
cdeil wants to merge 1 commit into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes duplicate track IDs when multiple tracker instances of the same type coexist by moving track ID allocation from global (tracklet class-level) counters to per-tracker-instance allocators.
Changes:
- Removed
BaseTracklet.count_id/get_next_tracker_id()and all tracklet subclass counters. - Added per-instance ID allocation helpers to
BaseTracker, and updated SORT/ByteTrack/OC-SORT/BoT-SORT to use them (including onreset()). - Updated tests to cover the “two live instances must not share/reset each other’s IDs” regression, and removed the now-obsolete class-counter test.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| tests/core/test_tracklets.py | Removes the test that asserted per-tracklet-subclass global counters (no longer applicable). |
| tests/core/test_trackers.py | Adds a regression test ensuring two tracker instances don’t share ID allocation; adds a small detections helper. |
| src/trackers/utils/base_tracklet.py | Removes the global class-variable ID counter and allocator from the base tracklet. |
| src/trackers/core/sort/tracklet.py | Removes SORT tracklet’s class-level ID counter. |
| src/trackers/core/sort/tracker.py | Switches SORT to per-instance ID allocation and resets allocator on init/reset. |
| src/trackers/core/ocsort/tracklet.py | Removes class-level counter and threads an allocator callable into resolve_tracker_id(). |
| src/trackers/core/ocsort/tracker.py | Uses per-instance allocator and passes it into resolve_tracker_id(); resets allocator on init/reset. |
| src/trackers/core/bytetrack/tracklet.py | Removes ByteTrack tracklet’s class-level ID counter. |
| src/trackers/core/bytetrack/tracker.py | Switches ByteTrack to per-instance ID allocation and resets allocator on init/reset. |
| src/trackers/core/botsort/tracklet.py | Removes BoT-SORT tracklet’s class-level ID counter. |
| src/trackers/core/botsort/tracker.py | Switches BoT-SORT to per-instance ID allocation and resets allocator on init/reset. |
| src/trackers/core/base.py | Adds _reset_id_allocator() / _allocate_tracker_id() helpers to BaseTracker. |
| CHANGELOG.md | Documents the internal breaking change and the user-facing fix. |
Collaborator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Fix duplicate track IDs when multiple tracker instances of the same type are used in one process.
Track IDs are the labels returned in
detections.tracker_id, for example person A getstracker_id=0, person B getstracker_id=1, and the next new track should gettracker_id=2. Previously, that "next ID" counter lived on the internal tracklet class, so allSORTTracker()instances shared it.That meant resetting one tracker could accidentally affect another live tracker:
This PR moves the counter to each tracker instance.
tracker_b.reset()still restarts IDs from zero fortracker_b, but it no longer changes the IDs thattracker_awill allocate.This can affect normal scripts and notebooks, not only multi-threaded applications. It is enough to have two trackers of the same type alive at once, for example in multi-camera tracking, class-specific tracking, side-by-side config comparisons, services handling multiple requests, or notebook experiments.
Type of Change
I think this is a bug fix with a small internal breaking change:
BaseTracklet.count_id/Tracklet.get_next_tracker_id()were removed because tracklets no longer own ID allocation.Testing
Red/green TDD:
test_tracker_instances_do_not_share_id_allocators, which failed for SORT, ByteTrack, OC-SORT, and BoT-SORT with duplicate live IDs[0, 0].Checklist