Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
118 commits
Select commit Hold shift + click to select a range
7fd8ec8
ocsort with piotr's review changes
AlexBodner Jan 29, 2026
01cd73d
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] Jan 29, 2026
481de00
trackers/core/ocsort
AlexBodner Jan 29, 2026
3a90628
fixed pre commit
AlexBodner Jan 29, 2026
81203f7
fixed pre commit
AlexBodner Jan 29, 2026
27a2322
Merge branch 'feat/core/ocsort-release' of https://github.com/roboflo…
AlexBodner Jan 29, 2026
56bd50b
trying original kalman filter
AlexBodner Jan 30, 2026
8598547
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] Jan 30, 2026
e153183
trying fix
AlexBodner Jan 30, 2026
3cfb483
Merge branch 'feat/core/ocsort-release' of https://github.com/roboflo…
AlexBodner Jan 30, 2026
0db6ab1
trying fix
AlexBodner Jan 30, 2026
c6e2fb0
trying fix
AlexBodner Jan 30, 2026
03faa93
added F initialization
AlexBodner Jan 30, 2026
d16ecfb
possible fix by transforming cosine_sim
AlexBodner Feb 5, 2026
81fed51
changed indexing fro initializing new tracklets when ocr unmatched an…
AlexBodner Feb 5, 2026
fa42061
now in frames before minimum consecutive frames we output an id
AlexBodner Feb 5, 2026
f801c78
now in frames before minimum consecutive frames we output an id
AlexBodner Feb 5, 2026
457841c
now in frames before minimum consecutive frames we output an id
AlexBodner Feb 5, 2026
e02996a
bug fix regarding last commits
AlexBodner Feb 6, 2026
25e6f5a
bug fix regarding last commits
AlexBodner Feb 6, 2026
ac1b490
possbile fix by activating track id when just matured
AlexBodner Feb 6, 2026
89de476
now doing batch calculation of direction consistency, faster tracking
AlexBodner Feb 6, 2026
bc74315
nice docs in utils
AlexBodner Feb 6, 2026
ac3258f
trying independence on original KF
AlexBodner Feb 6, 2026
2625c2d
fixed pre commit, deleted 2nd kalman filter
AlexBodner Feb 9, 2026
475c07b
added XYXY and XCTCSR possible reps
AlexBodner Feb 9, 2026
146907d
code looking good
AlexBodner Feb 9, 2026
e94b207
added metrics
AlexBodner Feb 9, 2026
517b1e1
trying interpolation in xyxy system
AlexBodner Feb 10, 2026
0da45f5
rollback interpolation in xyxy system
AlexBodner Feb 10, 2026
0480a18
kf annotations fix and removed example
AlexBodner Feb 11, 2026
82c7345
merge develop
AlexBodner Feb 11, 2026
7e2cfaf
added oc-sort final numbers
AlexBodner Feb 11, 2026
2cfd0e7
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] Feb 11, 2026
990bdd2
readme with final numbers, utils with _ and ocsort in docs/api
AlexBodner Feb 11, 2026
6e6f309
Merge branch 'feat/core/ocsort-release' of https://github.com/roboflo…
AlexBodner Feb 11, 2026
cf5ae7e
readme with final numbers, utils with _ and ocsort in docs/api
AlexBodner Feb 11, 2026
80753fb
added headers and changed parameters name high_conf_det_threshold -> …
AlexBodner Feb 11, 2026
8e07a25
rollback parameter name changed
AlexBodner Feb 11, 2026
a967b61
removed typings from docstring
AlexBodner Feb 11, 2026
be508ab
added change from PR to prevent in place mutation:
AlexBodner Feb 12, 2026
58f793e
trying to add delta_t
AlexBodner Feb 16, 2026
f1ac163
trying fix to delta_t: velocity not computed until second match, fram…
AlexBodner Feb 17, 2026
44ec83d
reverted <= change
AlexBodner Feb 17, 2026
fc8a2fd
aligned to original initialization of time_since_update and changes i…
AlexBodner Feb 17, 2026
154c830
added headers to utils
AlexBodner Feb 19, 2026
c506b72
Merge branch 'develop' into feat/core/ocsort-release
AlexBodner Feb 20, 2026
09a62cb
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] Feb 20, 2026
2f593e1
modular state representation
AlexBodner Feb 20, 2026
fd68de9
Merge branch 'feat/core/ocsort-release' of https://github.com/roboflo…
AlexBodner Feb 23, 2026
4b9bfba
changed state representations to KF classes
AlexBodner Feb 23, 2026
c9ef80b
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] Feb 23, 2026
b6f1d2a
Merge branch 'develop' into feat/core/ocsort-release
SkalskiP Feb 23, 2026
03b6c0e
register OCSORTTracker for CLI and public API
SkalskiP Feb 23, 2026
7b66fe9
remove duplicate headers and forbidden comments in utils
SkalskiP Feb 23, 2026
765f1ba
Use mkdocstrings-compatible single backticks instead of Sphinx-style
SkalskiP Feb 23, 2026
31b5be1
wrap OCSORTTracker docstring to fit 88-char line limit
SkalskiP Feb 24, 2026
39c7fd3
docs: improve docstrings for mkdocs compatibility and clarity
SkalskiP Feb 24, 2026
4abffc6
- Add functions to trackers/__init__.py exports
SkalskiP Feb 24, 2026
ee5fb54
Applying changes requested by Piotr
AlexBodner Feb 24, 2026
cce1f47
Applying changes requested by Piotr
AlexBodner Feb 24, 2026
81b34db
Fixed pre commit
AlexBodner Feb 24, 2026
7a95de0
try removing activate tracklets in activate_or_kill_tracklets as it s…
AlexBodner Feb 24, 2026
ae1fc86
completely corrected activate_or_kill_tracklets to kill_tracklets aft…
AlexBodner Feb 24, 2026
b35e353
changed BaseKalmanFilter to BaseStateEstimator and same for other typ…
AlexBodner Feb 24, 2026
081c4e2
initial commit adding abstract BaseTraclet and inheriting it in ocsor…
AlexBodner Feb 25, 2026
d7ac41d
sort might be done
AlexBodner Feb 25, 2026
2eb7f19
tracker changed by tracklet in byte
AlexBodner Feb 25, 2026
e1ba0e8
before merge
AlexBodner Feb 26, 2026
390e628
Merge remote-tracking branch 'origin/develop' into feat/core/refactor…
AlexBodner Feb 26, 2026
ef048d5
possible optimization by copying detections only once per update
AlexBodner Feb 26, 2026
1908f32
changes from merge
AlexBodner Feb 26, 2026
7dc0a2f
merged piotr optimizations
AlexBodner Mar 3, 2026
5704ce4
version with tracklets ready to test, bytetrack values might change b…
AlexBodner Mar 3, 2026
8a78611
small bug fix in sort, passed detections instead of confidence
AlexBodner Mar 4, 2026
8f9cc44
trying oc-sort style initialization in bytetrack
AlexBodner Mar 4, 2026
b33f3d1
rollback trying oc-sort style initialization in bytetrack, now it use…
AlexBodner Mar 4, 2026
bb3199e
aligned format
AlexBodner Mar 5, 2026
50e5117
default in sort is XYXY now
AlexBodner Mar 10, 2026
9a41629
now sort tracklets initialize number_of_successful_consecutive_updates
AlexBodner Mar 10, 2026
6207d09
initializing parameters like old version
AlexBodner Mar 10, 2026
8adae83
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] Mar 10, 2026
1428b73
Now SORT uses number_of_succesful_updates (not consecutive)
AlexBodner Mar 10, 2026
2f398e6
Now SORT uses number_of_succesful_updates (not consecutive)
AlexBodner Mar 10, 2026
ae46434
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] Mar 10, 2026
9369c6b
Now SORT uses number_of_succesful_updates (not consecutive)
AlexBodner Mar 10, 2026
e7e5663
Merge branch 'feat/core/refactor-tracklet-kalman-filter' of https://g…
AlexBodner Mar 10, 2026
c2f2daf
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] Mar 10, 2026
3c54462
fix bytetrack broken because of usage of sort utility
AlexBodner Mar 11, 2026
56975d1
Merge branch 'feat/core/refactor-tracklet-kalman-filter' of https://g…
AlexBodner Mar 11, 2026
ea622dc
Merge remote-tracking branch 'origin/develop' into feat/core/refactor…
AlexBodner Mar 12, 2026
d849ab8
updated numbers
AlexBodner Mar 12, 2026
6ed1c8b
Merge remote-tracking branch 'origin/develop' into feat/core/refactor…
AlexBodner Mar 13, 2026
c22babb
changed kalman filter name in tracklet to state_estimator
AlexBodner Mar 13, 2026
668cf30
added first version of docs for custom kalmans
AlexBodner Mar 13, 2026
15e95ba
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] Mar 13, 2026
c105d37
removed copy from being passed to tracker
AlexBodner Mar 16, 2026
33dc2d1
Merge branch 'feat/core/refactor-tracklet-kalman-filter' of https://g…
AlexBodner Mar 16, 2026
cdf2463
added first numbers on state estimators and video
AlexBodner Mar 24, 2026
257c038
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] Mar 24, 2026
ef48658
fixed video display
AlexBodner Mar 24, 2026
b60ce89
Merge branch 'feat/core/refactor-tracklet-kalman-filter' of https://g…
AlexBodner Mar 24, 2026
e03dc46
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] Mar 24, 2026
5b54591
finished putting the explained numbers for StateEstimators comparison
AlexBodner Mar 24, 2026
581112b
finished putting the explained numbers for StateEstimators comparison
AlexBodner Mar 24, 2026
b908a31
added baseIoU and GIoU
AlexBodner Mar 30, 2026
851b479
added DIoU, CIoU, tests and small refactor on usage
AlexBodner Mar 31, 2026
afdf33a
added IoU to docs API reference and added BIoU
AlexBodner Apr 1, 2026
158e8ce
default parameters is basic IoU
AlexBodner Apr 1, 2026
b661fcb
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] Apr 1, 2026
0c7a8af
Updated uv lock and pyproject.toml for including torch and torchvision
AlexBodner Apr 1, 2026
e913e02
Merge branch 'feat/core/IoU-variants' of https://github.com/roboflow/…
AlexBodner Apr 1, 2026
1677812
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] Apr 1, 2026
db62244
version of IoU.md where we have decoupled examples from formulas
AlexBodner Apr 8, 2026
04f5bba
better iou docs
AlexBodner Apr 9, 2026
5632c86
Merge branch 'feat/core/IoU-variants' of https://github.com/roboflow/…
AlexBodner Apr 9, 2026
46449ca
changed iou.md from api ref to guide
AlexBodner Apr 9, 2026
48b2c34
changed title
AlexBodner Apr 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
Binary file not shown.
Binary file added docs/assets/iou_vs_CIoU_v_0kUtTtmLaJA_c006.mp4
Binary file not shown.
Binary file added docs/assets/iou_vs_DIoU_v_0kUtTtmLaJA_c006.mp4
Binary file not shown.
Binary file added docs/assets/iou_vs_GIoU_v_0kUtTtmLaJA_c006.mp4
Binary file not shown.
10 changes: 10 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,14 @@ Try trackers in your browser with our [Hugging Face Playground](https://huggingf

[:simple-googlecolab: Run Google Colab](https://colab.research.google.com/github/roboflow-ai/notebooks/blob/main/notebooks/how-to-track-objects-with-bytetrack-tracker.ipynb)

- **How to Track Objects with OC-SORT**

---

[![](url-to-image)](https://colab.research.google.com/github/roboflow-ai/notebooks/blob/main/notebooks/how-to-track-objects-with-ocsort-tracker.ipynb)

End-to-end example showing how to run RF-DETR detection with the OC-SORT tracker.

[:simple-googlecolab: Run Google Colab](https://colab.research.google.com/github/roboflow-ai/notebooks/blob/main/notebooks/how-to-track-objects-with-ocsort-tracker.ipynb)

</div>
12 changes: 12 additions & 0 deletions docs/javascripts/mathjax.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
window.MathJax = {
tex: {
inlineMath: [["\\(", "\\)"], ["$", "$"]],
displayMath: [["\\[", "\\]"], ["$$", "$$"]],
processEscapes: true,
processEnvironments: true,
},
options: {
ignoreHtmlClass: "^((?!arithmatex).)*$",
processHtmlClass: "arithmatex",
},
};
251 changes: 251 additions & 0 deletions docs/learn/iou.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
# IoU variants

IoU variants are pluggable similarity metrics used during detection-to-track
association. You pass one of these classes to a tracker via the `iou=` argument.

## Quick Start

```python
from trackers import SORTTracker
from trackers.utils.iou import IoU

tracker = SORTTracker(
iou=IoU(),
minimum_iou_threshold=0.3,
)
```

## Overview

| Variant | Score range | When to use |
| :------ | :---------- | :---------- |
| `IoU` | `[0, 1]` | Default — strong baseline for most scenes |
| `GIoU` | `[-1, 1]` | Scenes where boxes frequently lose overlap (occlusion, re-entry) |
| `DIoU` | `[-1, 1]` | Fast-moving objects; centre-distance signal without aspect sensitivity |
| `CIoU` | `(−∞, 1]` | Same as DIoU plus aspect-ratio consistency |
| `BIoU` | `[0, 1]` | Very small or very fast objects where raw boxes rarely overlap |

Negative thresholds are meaningful for `GIoU`, `DIoU`, and `CIoU` because they extend their range to give a signal even when there is no pixel overlap. For `IoU` and `BIoU` thresholds
must be non-negative.

---

## IoU

**Standard Intersection over Union** — the classic baseline.

\[
\mathrm{IoU}(A, B) = \frac{|A \cap B|}{|A \cup B|}
\]

Scores are `0` (no overlap) to `1` (perfect overlap). Because it returns `0` whenever
boxes do not intersect, the tracker gets no gradient to recover a lost track; a
variant from the list below can help in those cases.

```python
from trackers import SORTTracker
from trackers.utils.iou import IoU

tracker = SORTTracker(iou=IoU(), minimum_iou_threshold=0.3)
```

---

## GIoU

**Generalised IoU** (Rezatofighi et al., 2019) — penalises the gap inside the
smallest enclosing box `C` that neither `A` nor `B` fills.

\[
\mathrm{GIoU}(A, B) = \mathrm{IoU} - \frac{|C \setminus (A \cup B)|}{|C|}
\]

When boxes do not overlap at all, IoU is flat at `0`, but the penalty term still
changes as boxes move closer or farther apart — giving the tracker a meaningful
signal to bridge short gaps.

```python
from trackers import OCSORTTracker
from trackers.utils.iou import GIoU

# Negative thresholds are valid and often optimal for GIoU
tracker = OCSORTTracker(iou=GIoU(), minimum_iou_threshold=-0.3)
```

**Example — SportsMOT `v_0kUtTtmLaJA_c006`**

| | HOTA (%) | Δ (pts) |
| :- | ------: | ------: |
| Best IoU | 73.07 | — |
| Best GIoU | 89.31 | **+16.24** |


Left: IoU. Right: GIoU. Camera movements confuses IoU by introducing an external movement, producing ID switches when this lands in other object. GIoU gives a partial solution to this by considering how similar the boxes are, which keeps most of the tracks that with IoU are confused or lost due direction changes and non linear motion. E.g: tracks 5, 12/13.

<video width="100%" controls muted loop>
<source src="../../assets/iou_vs_GIoU_v_0kUtTtmLaJA_c006.mp4" type="video/mp4">
</video>


---

## DIoU

**Distance IoU** (Zheng et al., 2019) — adds a centre-distance penalty to IoU,
normalised by the enclosing box diagonal.

\[
\mathrm{DIoU}(A, B) = \mathrm{IoU} - \frac{d^2}{c^2 + \epsilon}
\]

where `d` is the Euclidean distance between box centres and `c` is the diagonal of
the smallest enclosing rectangle. This encourages centre alignment independently of
aspect ratio and tends to produce smoother associations in fast-motion sequences.

```python
from trackers import OCSORTTracker
from trackers.utils.iou import DIoU

tracker = OCSORTTracker(iou=DIoU(), minimum_iou_threshold=-0.3)
```

**Example — SportsMOT `v_0kUtTtmLaJA_c006`**

| | HOTA (%) | Δ (pts) |
| :- | ------: | ------: |
| Best IoU | 73.07 | — |
| Best DIoU | 86.53 | **+13.46** |

Left: IoU. Right: DIoU. Camera movements confuses IoU by introducing an external movement, producing ID switches when this prediction runs into another object. Watch how the centre-distance term keeps track IDs stable
when camera accelerates quickly, so that objects geometrically close would lose the track with IoU. E.g: tracks 3, 4 and 5.

<video width="100%" controls muted loop>
<source src="../../assets/iou_vs_DIoU_v_0kUtTtmLaJA_c006.mp4" type="video/mp4">
</video>

---

## CIoU

**Complete IoU** (Zheng et al., 2019) — extends DIoU with a penalty for aspect-ratio
mismatch between the two boxes.

\[
\mathrm{CIoU}(A, B) = \mathrm{DIoU} - \alpha v
\]

\[
v = \frac{4}{\pi^2}\!\left(\arctan\frac{w_A}{h_A} - \arctan\frac{w_B}{h_B}\right)^2, \quad
\alpha = \frac{v}{1 - \mathrm{IoU} + v + \epsilon}
\]

`v` measures aspect-ratio divergence; `α` scales it so the penalty is low when IoU
is already high. On tracking benchmarks CIoU and DIoU behave nearly identically —
the aspect term rarely changes which assignment wins.

```python
from trackers import OCSORTTracker
from trackers.utils.iou import CIoU

tracker = OCSORTTracker(iou=CIoU(), minimum_iou_threshold=-0.3)
```

**Example — SportsMOT `v_0kUtTtmLaJA_c006`**

| | HOTA (%) | Δ (pts) |
| :- | ------: | ------: |
| Best IoU | 73.07 | — |
| Best CIoU | 86.53 | **+13.46** |

Left: IoU. Right: CIoU. The gain here mirrors DIoU. The aspect-ratio term adds
a small tweak for boxes that differ in shape.

<video width="100%" controls muted loop>
<source src="../../assets/iou_vs_CIoU_v_0kUtTtmLaJA_c006.mp4" type="video/mp4">
</video>

---

## BIoU

**Buffered IoU** (Yang et al., 2022) — dilates each box by a relative margin `r`
before computing standard IoU. Let `w = x2 − x1`, `h = y2 − y1`:

\[
A^r = (x_1 - rw,\; y_1 - rh,\; x_2 + rw,\; y_2 + rh)
\]

\[
\mathrm{BIoU}_r(A, B) = \mathrm{IoU}(A^r, B^r)
\]

`r = 0` recovers plain IoU exactly. Enlarging boxes creates artificial overlap for
objects that are geometrically close, which is useful when detections are very small
or objects move fast enough so that consecutive boxes miss each other entirely.

```python
from trackers import SORTTracker
from trackers.utils.iou import BIoU

tracker = SORTTracker(iou=BIoU(buffer_ratio=0.15), minimum_iou_threshold=0.3)
```

**Example — SportsMOT `v_9MHDmAMxO5I_c004`**

| | HOTA (%) | Δ (pts) |
| :- | ------: | ------: |
| Best IoU | 80.54 | — |
| Best BIoU | 88.00 | **+7.46** |

Left: IoU. Right: BIoU. Notice how ID switches happen when fast players
temporarily produce non-overlapping boxes between frames. The buffer closes
that gap and keeps the same ID. E.g: tracks 7 and 8.

<video width="100%" controls muted loop>
<source src="../../assets/iou_vs_BIoU_v_9MHDmAMxO5I_c004.mp4" type="video/mp4">
</video>

---

## Empirical HOTA deltas

The following numbers come from running **OC-SORT** on **MOT17 train (FRCNN)** and
**SportsMOT val**: for each sequence the best HOTA over the IoU threshold grid is
taken separately for each variant, and **Δ = HOTA(variant) − HOTA(IoU)**. On
SportsMOT detections are derived from GT boxes (oracle feed); on MOT17 the FRCNN
public detections are used.

HOTA is shown as a **percentage** (0–100 scale); **Δ** is percentage points.

| Dataset | Sequences | GIoU mean Δ | DIoU mean Δ | CIoU mean Δ | BIoU mean Δ |
| :------ | --------: | ----------: | ----------: | ----------: | ----------: |
| MOT17 train (FRCNN) | 7 | +0.35 | −0.10 | −0.10 | +0.66 |
| SportsMOT val | 45 | +1.15 | +0.89 | +0.89 | +0.74 |

---

## API Reference

### BaseIoU

::: trackers.utils.iou.BaseIoU

### IoU

::: trackers.utils.iou.IoU

### GIoU

::: trackers.utils.iou.GIoU

### DIoU

::: trackers.utils.iou.DIoU

### CIoU

::: trackers.utils.iou.CIoU

### BIoU

::: trackers.utils.iou.BIoU
Loading