Skip to content

Commit b5356f4

Browse files
AlexBodnerpre-commit-ci[bot]SkalskiP
authored
OC-SORT on top of 2.1.0 (#207)
* ocsort with piotr's review changes * fix(pre_commit): 🎨 auto format pre-commit hooks * trackers/core/ocsort * fixed pre commit * fixed pre commit * trying original kalman filter * fix(pre_commit): 🎨 auto format pre-commit hooks * trying fix * trying fix * trying fix * added F initialization * possible fix by transforming cosine_sim * changed indexing fro initializing new tracklets when ocr unmatched and update also when unmatched detections = 0 * now in frames before minimum consecutive frames we output an id * now in frames before minimum consecutive frames we output an id * now in frames before minimum consecutive frames we output an id * bug fix regarding last commits * bug fix regarding last commits * possbile fix by activating track id when just matured * now doing batch calculation of direction consistency, faster tracking * nice docs in utils * trying independence on original KF * fixed pre commit, deleted 2nd kalman filter * added XYXY and XCTCSR possible reps * code looking good * added metrics * trying interpolation in xyxy system * rollback interpolation in xyxy system * kf annotations fix and removed example * added oc-sort final numbers * fix(pre_commit): 🎨 auto format pre-commit hooks * readme with final numbers, utils with _ and ocsort in docs/api * readme with final numbers, utils with _ and ocsort in docs/api * added headers and changed parameters name high_conf_det_threshold -> high_conf_detect_threshold * rollback parameter name changed * removed typings from docstring * added change from PR to prevent in place mutation: * trying to add delta_t * trying fix to delta_t: velocity not computed until second match, frame count<=minimum_consecutive_frames (before was <, now it is aligned with original repo) * reverted <= change * aligned to original initialization of time_since_update and changes in re-update cycle * added headers to utils * fix(pre_commit): 🎨 auto format pre-commit hooks * modular state representation * changed state representations to KF classes * fix(pre_commit): 🎨 auto format pre-commit hooks * register OCSORTTracker for CLI and public API - Add `tracker_id = "ocsort"` class variable to enable CLI auto-registration via BaseTracker's registry mechanism - Export OCSORTTracker in `__all__` for public API discoverability * remove duplicate headers and forbidden comments in utils - Remove module-level docstring from state_representations.py - Remove section divider comment from state_representations.py - Remove duplicate/truncated headers from converters.py and kalman_filter.py * Use mkdocstrings-compatible single backticks instead of Sphinx-style double backticks in state_representations.py. * wrap OCSORTTracker docstring to fit 88-char line limit * docs: improve docstrings for mkdocs compatibility and clarity - Add backticks to variable references (`x1`, `y1`, `scale`, etc.) - Replace Sphinx-style :class:/:meth: with plain backticks - Remove bullet points (poor mkdocs rendering) - Expand StateRepresentation, XCYCSRKalmanFilter, XYXYKalmanFilter docstrings with variable explanations and behavioral implications * - Add functions to trackers/__init__.py exports - Add doctests with full input/output examples - Add unit tests covering conversions, edge cases, and round-trips - Add API documentation under Trackers > Utilities section * Applying changes requested by Piotr * Fixed pre commit * try removing activate tracklets in activate_or_kill_tracklets as it seemed redundant because oc-sort activates them earlier * completely corrected activate_or_kill_tracklets to kill_tracklets after evaluating in sportsmot and getting same metrics * changed BaseKalmanFilter to BaseStateEstimator and same for other types of StateKalmanFilters * Update OC-SORT docs and improve tracker API consistency docs/index.md: - Mark OC-SORT as supported, move BoT-SORT and McByte to "coming soon" - Remove MOT17 IDF1 and MOT17 MOTA columns from comparison table - Remove OC-SORT tutorial card (not yet ready) trackers/core/ocsort/tracker.py: - Align update/reset docstrings with SORT and ByteTrack style - Remove paper reference from delta_t parameter description - Rename _kill_tracklets to _prune_expired_tracklets for clarity * Standardize tracker class docstrings across SORT, ByteTrack, and OC-SORT Replace brief algorithm descriptions with comprehensive two-paragraph docstrings for all tracker classes. Each docstring now covers the algorithm's core mechanism in the first paragraph and its strengths and limitations in the second. Reformat OCSORTTracker Args section to match SORT/ByteTrack style, using consistent `type` specifying pattern and concise parameter descriptions. * removed unused functions * Changed utils so that now only the math happens there and the custom classes dealing happens where it should * fix(pre_commit): 🎨 auto format pre-commit hooks * fixed pre commit * Standardize ocsort utility function signatures and improve docstrings * fix(pre_commit): 🎨 auto format pre-commit hooks --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Piotr Skalski <piotr.skalski92@gmail.com>
1 parent 0e2e7c7 commit b5356f4

File tree

16 files changed

+1690
-15
lines changed

16 files changed

+1690
-15
lines changed

docs/api/trackers.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,13 @@
77
## ByteTrack
88

99
::: trackers.core.bytetrack.tracker.ByteTrackTracker
10+
11+
## OC-SORT
12+
13+
::: trackers.core.ocsort.tracker.OCSORTTracker
14+
15+
## Utilities
16+
17+
::: trackers.utils.converters.xyxy_to_xcycsr
18+
19+
::: trackers.utils.converters.xcycsr_to_xyxy

docs/index.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,15 @@ You can install and use `trackers` in a [**Python>=3.10**](https://www.python.or
6161

6262
## Tracking Algorithms
6363

64-
`trackers` gives you clean, modular re-implementations of leading multi-object tracking algorithms. The package currently supports [SORT](https://arxiv.org/abs/1602.00763) and [ByteTrack](https://arxiv.org/abs/2110.06864). [OC-SORT](https://arxiv.org/abs/2203.14360), [BoT-SORT](https://arxiv.org/abs/2206.14651), and [McByte](https://arxiv.org/abs/2506.01373) support is coming soon. For comparisons, see the [tracker comparison](trackers/comparison.md) page.
65-
66-
| Algorithm | MOT17 HOTA | MOT17 IDF1 | MOT17 MOTA | SportsMOT HOTA | SoccerNet HOTA |
67-
| :-------: | :--------: | :--------: | :--------: | :------------: | :------------: |
68-
| SORT | 58.4 | 69.9 | 67.2 | 70.9 | 81.6 |
69-
| ByteTrack | **60.1** | **73.2** | **74.1** | **73.0** | **84.0** |
70-
| OC-SORT | | || | |
71-
| BoT-SORT || || ||
72-
| McByte || || ||
64+
`trackers` gives you clean, modular re-implementations of leading multi-object tracking algorithms. The package currently supports [SORT](https://arxiv.org/abs/1602.00763), [ByteTrack](https://arxiv.org/abs/2110.06864), and [OC-SORT](https://arxiv.org/abs/2203.14360). [BoT-SORT](https://arxiv.org/abs/2206.14651) and [McByte](https://arxiv.org/abs/2506.01373) support is coming soon. For comparisons, see the [tracker comparison](trackers/comparison.md) page.
65+
66+
| Algorithm | MOT17 HOTA | SportsMOT HOTA | SoccerNet HOTA |
67+
| :-------: | :--------: | :------------: | :------------: |
68+
| SORT | 58.4 | 70.9 | 81.6 |
69+
| ByteTrack | 60.1 | **73.0** | **84.0** |
70+
| OC-SORT | **61.9** | 71.5 | 78.6 |
71+
| BoT-SORT ||||
72+
| McByte ||||
7373

7474
## Integration
7575

docs/trackers/comparison.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Pedestrian tracking with crowded scenes and frequent occlusions. Strongly tests
1010
| :-------: | :--: | :--: | :--: |
1111
| SORT | 58.4 | 69.9 | 67.2 |
1212
| ByteTrack | 60.1 | 73.2 | 74.1 |
13+
| OC-SORT | 61.9 | 76.1 | 76.7 |
1314

1415
## SportsMOT
1516

@@ -19,6 +20,7 @@ Sports broadcast tracking with fast motion, camera pans, and similar-looking tar
1920
| :-------: | :--: | :--: | :--: |
2021
| SORT | 70.9 | 68.9 | 95.7 |
2122
| ByteTrack | 73.0 | 72.5 | 96.4 |
23+
| OC-SORT | 71.5 | 71.2 | 95.2 |
2224

2325
## SoccerNet-tracking
2426

@@ -28,3 +30,4 @@ Long sequences with dense interactions and partial occlusions. Tests long-term I
2830
| :-------: | :--: | :--: | :--: |
2931
| SORT | 81.6 | 76.2 | 95.1 |
3032
| ByteTrack | 84.0 | 78.1 | 97.8 |
33+
| OC-SORT | 78.6 | 72.7 | 94.5 |

docs/trackers/ocsort.md

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
---
2+
comments: true
3+
---
4+
5+
# OC-SORT
6+
7+
## Overview
8+
9+
OC-SORT remains Simple, Online, and Real-Time like ([SORT](../sort/tracker.md)) but improves robustness during occlusion and non-linear motion.
10+
It recognizes limitations from SORT and the linear motion assumption of the Kalman filter, and adds three mechanisms to enhance tracking. These
11+
mechanisms help having better Kalman Filter parameters after an occlusion, add a term to the association process to incorporate how consistent is the direction with the new association with respect to the tracks' previous direction and add a second-stage association step between the last observation of unmatched tracks and the unmatched observations after the usual association to attempt to recover tracks that were lost
12+
due to object stopping or short-term occlusion.
13+
14+
## Comparison
15+
16+
For comparisons with other trackers, plus dataset context and evaluation details, see the [tracker comparison](comparison.md) page.
17+
18+
| Dataset | HOTA | IDF1 | MOTA |
19+
| :-------: | :--: | :--: | :--: |
20+
| MOT17 | 61.9 | 76.1 | 76.7 |
21+
| SportsMOT | 71.5 | 71.2 | 95.2 |
22+
| SoccerNet | 78.6 | 72.7 | 94.5 |
23+
24+
## Run on video, webcam, or RTSP stream
25+
26+
These examples use OpenCV for decoding and display. Replace `<SOURCE_VIDEO_PATH>`, `<WEBCAM_INDEX>`, and `<RTSP_STREAM_URL>` with your inputs. `<WEBCAM_INDEX>` is usually 0 for the default camera.
27+
28+
=== "Video"
29+
30+
```python
31+
import cv2
32+
import supervision as sv
33+
from rfdetr import RFDETRMedium
34+
from trackers import OCSORTTracker
35+
36+
tracker = OCSORTTracker()
37+
model = RFDETRMedium()
38+
39+
box_annotator = sv.BoxAnnotator()
40+
label_annotator = sv.LabelAnnotator()
41+
42+
video_capture = cv2.VideoCapture("<SOURCE_VIDEO_PATH>")
43+
if not video_capture.isOpened():
44+
raise RuntimeError("Failed to open video source")
45+
46+
while True:
47+
success, frame_bgr = video_capture.read()
48+
if not success:
49+
break
50+
51+
frame_rgb = cv2.cvtColor(frame_bgr, cv2.COLOR_BGR2RGB)
52+
detections = model.predict(frame_rgb)
53+
detections = tracker.update(detections)
54+
55+
annotated_frame = box_annotator.annotate(frame_bgr, detections)
56+
annotated_frame = label_annotator.annotate(
57+
annotated_frame, detections, labels=detections.tracker_id
58+
)
59+
60+
cv2.imshow("RF-DETR + OC-SORT", annotated_frame)
61+
if cv2.waitKey(1) & 0xFF == ord("q"):
62+
break
63+
64+
video_capture.release()
65+
cv2.destroyAllWindows()
66+
```
67+
68+
=== "Webcam"
69+
70+
```python
71+
import cv2
72+
import supervision as sv
73+
from rfdetr import RFDETRMedium
74+
from trackers import OCSORTTracker
75+
76+
tracker = OCSORTTracker()
77+
model = RFDETRMedium()
78+
79+
box_annotator = sv.BoxAnnotator()
80+
label_annotator = sv.LabelAnnotator()
81+
82+
video_capture = cv2.VideoCapture("<WEBCAM_INDEX>")
83+
if not video_capture.isOpened():
84+
raise RuntimeError("Failed to open webcam")
85+
86+
while True:
87+
success, frame_bgr = video_capture.read()
88+
if not success:
89+
break
90+
91+
frame_rgb = cv2.cvtColor(frame_bgr, cv2.COLOR_BGR2RGB)
92+
detections = model.predict(frame_rgb)
93+
detections = tracker.update(detections)
94+
95+
annotated_frame = box_annotator.annotate(frame_bgr, detections)
96+
annotated_frame = label_annotator.annotate(
97+
annotated_frame, detections, labels=detections.tracker_id
98+
)
99+
100+
cv2.imshow("RF-DETR + OC-SORT", annotated_frame)
101+
if cv2.waitKey(1) & 0xFF == ord("q"):
102+
break
103+
104+
video_capture.release()
105+
cv2.destroyAllWindows()
106+
```
107+
108+
=== "RTSP"
109+
110+
```python
111+
import cv2
112+
import supervision as sv
113+
from rfdetr import RFDETRMedium
114+
from trackers import OCSORTTracker
115+
116+
tracker = OCSORTTracker()
117+
model = RFDETRMedium()
118+
119+
box_annotator = sv.BoxAnnotator()
120+
label_annotator = sv.LabelAnnotator()
121+
122+
video_capture = cv2.VideoCapture("<RTSP_STREAM_URL>")
123+
if not video_capture.isOpened():
124+
raise RuntimeError("Failed to open RTSP stream")
125+
126+
while True:
127+
success, frame_bgr = video_capture.read()
128+
if not success:
129+
break
130+
131+
frame_rgb = cv2.cvtColor(frame_bgr, cv2.COLOR_BGR2RGB)
132+
detections = model.predict(frame_rgb)
133+
detections = tracker.update(detections)
134+
135+
annotated_frame = box_annotator.annotate(frame_bgr, detections)
136+
annotated_frame = label_annotator.annotate(
137+
annotated_frame, detections, labels=detections.tracker_id
138+
)
139+
140+
cv2.imshow("RF-DETR + OC-SORT", annotated_frame)
141+
if cv2.waitKey(1) & 0xFF == ord("q"):
142+
break
143+
144+
video_capture.release()
145+
cv2.destroyAllWindows()
146+
```

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ nav:
117117
- Comparison: trackers/comparison.md
118118
- SORT: trackers/sort.md
119119
- ByteTrack: trackers/bytetrack.md
120+
- OC-SORT: trackers/ocsort.md
120121
- Guides:
121122
- Install: learn/install.md
122123
- Track: learn/track.md

0 commit comments

Comments
 (0)