feat: Add ByteTrack tracker with IoU matching and Kalman motion#6950
feat: Add ByteTrack tracker with IoU matching and Kalman motion#6950omkar-334 wants to merge 10 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces the ByteTrack multi-object tracking algorithm into libraries/getitrack, adding the matching (IoU + Hungarian assignment) and motion (constant-velocity Kalman filter in xyah) primitives it depends on, along with configuration defaults and unit tests.
Changes:
- Added ByteTrack tracker implementation + config variant and algorithm registration (
bytetrack). - Added matching utilities (IoU matrix / score fusion / threshold-gated Hungarian assignment) and a Kalman motion model with
xyxy↔xyahconversions. - Added SciPy as a dependency (for
linear_sum_assignmentandscipy.linalg) and introduced test coverage for matching, Kalman, config defaults, and ByteTrack behavior.
Reviewed changes
Copilot reviewed 14 out of 15 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| libraries/getitrack/uv.lock | Locks SciPy (marker-split by Python version) and updates resolution markers. |
| libraries/getitrack/pyproject.toml | Adds scipy>=1.13 runtime dependency. |
| libraries/getitrack/configs/default.yaml | Updates defaults for ByteTrack split threshold and motion velocity decay. |
| libraries/getitrack/src/getitrack/init.py | Ensures bundled algorithms are imported/registered on package import; keeps default logging disabled. |
| libraries/getitrack/src/getitrack/algorithms/init.py | Exposes bundled algorithms package and imports ByteTrack to register it. |
| libraries/getitrack/src/getitrack/algorithms/bytetrack.py | Implements ByteTrackTracker + ByteTrackConfig, including association, lifecycle handling, and duplicate suppression. |
| libraries/getitrack/src/getitrack/matching/init.py | Exports matching helpers (IoU + assignment). |
| libraries/getitrack/src/getitrack/matching/iou.py | Implements IoU computation, score fusion, and threshold-gated Hungarian assignment. |
| libraries/getitrack/src/getitrack/motion/init.py | Exports Kalman filter + bbox conversion helpers. |
| libraries/getitrack/src/getitrack/motion/kalman.py | Implements constant-velocity Kalman filter and xyxy↔xyah conversions. |
| libraries/getitrack/src/getitrack/config.py | Updates MotionConfig.velocity_decay default to 1.0 (no damping) and adjusts docstring. |
| libraries/getitrack/tests/unit/test_matching.py | Adds unit tests for IoU, score fusion, and gated assignment behavior. |
| libraries/getitrack/tests/unit/test_kalman.py | Adds unit tests for Kalman filter behavior and bbox conversions. |
| libraries/getitrack/tests/unit/test_config.py | Updates unit test expectation for motion default velocity decay. |
| libraries/getitrack/tests/unit/test_bytetrack.py | Adds ByteTrack behavior tests (registry dispatch, lifecycle, low-score recovery, duplicate suppression, det_indices). |
| motion_cov = self._predict_noise_cov(mean[3]) | ||
| new_mean = self._motion_mat @ mean | ||
| new_covariance = self._motion_mat @ covariance @ self._motion_mat.T + motion_cov | ||
| return new_mean, new_covariance |
| """ | ||
| if means.shape[0] == 0: | ||
| return means, covariances | ||
| motion_covs = np.stack([self._predict_noise_cov(h) for h in means[:, 3]], axis=0) |
| """Per-frame velocity damping in ``(0, 1]``. Values below 1.0 simulate gradual deceleration.""" | ||
| velocity_decay: Annotated[float, Field(gt=0.0, le=1.0)] = 1.0 | ||
| """Per-frame velocity damping in ``(0, 1]``. The default 1.0 matches the | ||
| reference (no damping); values below 1.0 simulate gradual deceleration.""" |
There was a problem hiding this comment.
reference is the bytetrack code - https://github.com/FoundationVision/ByteTrack

| self._first_frame_id = None | ||
| self._frame_det_index.clear() | ||
|
|
||
| def _update_impl(self, detections: Detections) -> TrackedDetections: |
There was a problem hiding this comment.
is there a reason to keep all methods and variables private except for "reset"?
There was a problem hiding this comment.
If you look at BaseTracker - three methods are public - reset, update and from_config, so this same convention is followed in downstream trackers. Only these 3 are prublic and rest are private since they are not user-facing
There was a problem hiding this comment.
For the the Kalman filter, have you considered off-the-shelf implementations like pykalman or similar?
There was a problem hiding this comment.
I did consider pykalman specifically, but i still had to write code for batch-prediction, conversions and other things. it also seems to have reduced maintenance over the last year. so i went with writing our own kalman implementation, since other algorithms can also reuse this
Summary
This pr adds the ByteTrack tracking algorithm and the matching and motion primitives it builds on.
Changes
matching/: IoU distance, score fusion, and threshold-gated Hungarian assignment (scipy.optimize.linear_sum_assignment).motion/: a constant-velocity Kalman filter inxyahstate, withxyxyconversions.algorithms/bytetrack.py:ByteTrackTracker(two-stage high/low-score association, lost-track recovery, class-aware duplicate suppression) andByteTrackConfig, registered underbytetrack.algorithmname, soTrackerConfig.from_yamlandBaseTracker.from_configresolve toByteTrackConfigand constructByteTrackTracker.scipyadded to dependencies;Behavior
high_score_threshold, new tracks require a score0.1above it.Checklist