Skip to content

v2.5.0: Pluggable IoU variants + C-BIoU tracker

Latest

Choose a tag to compare

@Borda Borda released this 24 Jun 18:30
1bf611d

📋 Summary

trackers 2.5.0 makes the association step configurable: all four trackers now accept an iou= parameter and ship five built-in IoU variants. The new CBIoUTracker (C-BIoU, WACV 2023) extends the built-in algorithm roster with cascaded buffered matching for fast-moving or small objects. The Tuner gets four new parameters that round out the tuning workflow, and a correctness fix in HOTA evaluation brings numbers in line with TrackEval.

Track IDs are now allocated per-tracker-instance, so multi-camera and class-specific workflows no longer risk duplicate IDs across independent trackers.

ciou.botsort-14s.mp4

✨ Spotlights

🎯 Pluggable IoU variants

All four trackers now accept an iou= parameter that takes any BaseIoU subclass. Five built-in variants:

Variant Score range Best for
IoU [0, 1] Default — strong baseline
GIoU [-1, 1] Boxes that frequently lose overlap (occlusion)
DIoU [-1, 1] Fast-moving objects; centre-distance signal
CIoU [-1, 1] Same as DIoU + aspect-ratio consistency
BIoU [0, 1] Small or very fast objects (buffered boxes)
from trackers import ByteTrackTracker
from trackers.utils.iou import GIoU

tracker = ByteTrackTracker(
    iou=GIoU(),
    minimum_iou_threshold=0.1,  # re-tune for the new score range
)
detections = tracker.update(detections)

Subclass BaseIoU and override _compute to plug in a fully custom metric. The normalize_for_fusion hook handles signed-range variants correctly in BoT-SORT's score-fusion step.

🆕 CBIoUTracker

CBIoUTracker (Yang et al., WACV 2023) expands boxes by a configurable margin before computing IoU and runs two cascade passes with independently tunable buffer ratios:

from trackers import CBIoUTracker

tracker = CBIoUTracker(
    buffer_ratio_first=0.1,  # first pass: small buffer (high-conf dets vs tracks)
    buffer_ratio_second=0.3,  # second pass: larger buffer (confirmed tracks vs low-conf)
)
detections = tracker.update(detections)

Benchmark scores on val sets (default parameters):

Algorithm MOT17 HOTA SportsMOT HOTA SoccerNet HOTA DanceTrack HOTA
SORT 58.4 70.8 81.6 47.2
ByteTrack 60.1 73.0 84.0 53.3
OC-SORT 61.9 71.7 78.4 54.1
BoT-SORT 63.7 73.8 84.5 57.8
C-BIoU 63.0 73.1 82.6 56.7

C-BIoU keeps the computational simplicity of ByteTrack while it can exceed its performance depending on the video characteristics.

See tracker comparison for all metrics, tuned numbers and methodology.

⚙️ Tuner enhancements

Four new Tuner parameters:

from trackers.tune import Tuner
from trackers import BoTSORTTracker

tuner = Tuner(
    tracker_class=BoTSORTTracker,
    gt_dir="data/gt/",
    detections_dir="data/det/",
    images_dir="data/img/",  # new: frames for CMC-enabled trackers
    fixed_params={"enable_cmc": True},  # new: held constant across all trials
    enqueue_defaults=True,  # new: baseline trial before Optuna samples
    seed=42,  # new: reproducible TPE sampling
)
result = tuner.tune()

Migration guide

Breaking: tracklet class-level ID counters removed

If you subclass BaseTracker and called a tracklet's class-level get_next_tracker_id():

# Before (v2.4.0)
tracker_id = SORTTracklet.get_next_tracker_id()

# After (v2.5.0)
tracker_id = self._allocate_tracker_id()  # in your BaseTracker subclass

Users of the public tracker.update() API are not affected.

Deprecations (removed in v3.0)

# SORTTracker.trackers → .tracks
for t in tracker.tracks:  # was: tracker.trackers

# CMC import path
from trackers.utils.cmc import CMC, CMCConfig, CMCMethod  # was: trackers.core.botsort.cmc
from trackers import CMC  # also works

# CMC.apply_to_xyxy → CMC.warp_xyxy_corners
warped = cmc.warp_xyxy_corners(H, boxes)  # was: apply_to_xyxy

# BoTSORTTracker.apply_cmc_batch → CMC.apply_batch
cmc.apply_batch(H, tracker.tracks)  # was: tracker.apply_cmc_batch(H)

# CMCTMethod → CMCMethod
from trackers.utils.cmc import CMCMethod  # was: CMCTMethod

Notable changes

🚀 Added

  • Pluggable IoU variantsiou= parameter on SORTTracker, ByteTrackTracker, OCSORTTracker, BoTSORTTracker; five built-in variants plus BaseIoU ABC for custom metrics. (#403)
  • CBIoUTracker — Cascaded-Buffered IoU tracker (Yang et al., WACV 2023). (#417)
  • Tuner paramsenqueue_defaults, fixed_params, images_dir, seed. (#427)
  • py.typed marker — PEP 561 compliance; downstream type checkers now recognise the package as typed.

⚠️ Breaking Changes

  • Tracklet class-level ID counters removed*Tracklet.get_next_tracker_id() class methods removed from all tracklet subclasses. Use self._allocate_tracker_id() (from BaseTracker) instead. Only affects custom BaseTracker subclassers. (#419)

🌱 Changed

  • CMC, CMCConfig, CMCMethod moved to trackers.utils.cmc, re-exported from top-level trackers; old trackers.core.botsort.cmc path kept as deprecated shim. (#414)
  • CMC.apply_batch homogeneity guard — raises TypeError on mixed state-estimator tracklet lists. (#414)
  • OC-SORT OCR step always uses standard IoU regardless of configured iou= variant, matching the paper. (#403)

🗑️ Deprecated

  • SORTTracker.trackers.tracks (FutureWarning, removed in v3.0). (#460)
  • trackers.core.botsort.cmc import path → trackers.utils.cmc (DeprecationWarning, removed in v3.0). (#414)
  • BoTSORTTracker.apply_cmc_batchCMC.apply_batch(H, tracker.tracks) (removed in v3.0). (#414)
  • CMCTMethodCMCMethod (removed in v3.0). (#414)
  • CMC.apply_to_xyxyCMC.warp_xyxy_corners (removed in v3.0). (#414)

🔧 Fixed

  • BoT-SORT score fusion — signed IoU variants (GIoU/DIoU/CIoU) now normalised before fusion via normalize_for_fusion, preventing track-ranking inversion. (#403)
  • Non-finite box coordinatesBaseIoU.compute raises ValueError with a clear message for NaN/inf inputs instead of propagating into SciPy's linear_sum_assignment. (#403)
  • ByteTrack confidence=None — detections without confidence now treated as high-confidence (SORT-like); previously produced no tracks. (#415)
  • HOTA evaluation accuracy — per-frame alpha loop vectorized; MOT distractor class filtering now matches TrackEval, correcting reported HOTA on MOT17. (#462, #466)
  • Tracker instances no longer share ID counters — resetting one tracker no longer affects another's ID allocator. (#419)

🏆 Contributors

  • Alexander Bodner (@AlexBodner, LinkedIn) — C-BIoU tracker, IoU variants, tuner enhancements, DanceTrack benchmark results
  • Tomasz Stańczyk (@tstanczyk95) (LinkedIn) — C-BIoU and IoU variants - expertise sharing and supervision
  • Christoph Deil (@cdeil, LinkedIn) — per-instance ID allocators, ByteTrack confidence fix
  • Manan Gupta (@manan152003, LinkedIn) — SORTTracker deprecation docs
  • Ruben Haisma (@RubenHaisma, LinkedIn) — HOTA vectorization, MOT distractor class fix
  • Jirka Borovec (@Borda, LinkedIn) — review, docs, test infrastructure

Full changelog: 2.4.0...v2.5.0