Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

381 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Trackforge logo

Trackforge is a unified, high-performance computer vision tracking library implemented in Rust with Python bindings. It provides real-time multi-object tracking algorithms, optimized for speed and designed as the CPU "glue" between GPU-based object detectors and your tracking pipeline.

Crates.io version Crates.io downloads docs.rs MSRV PyPI version PyPI downloads Python versions CI Coverage dependency status License Conventional Commits prek Cite this repository

Supported Trackers

Tracker Type Re-ID
ByteTrack IoU + confidence association
DeepSORT IoU + cosine distance ✅ pluggable
OC-SORT IoU + velocity direction (OCM)
Deep OC-SORT IoU + velocity (OCM) + appearance ✅ pluggable
BoT-SORT IoU + appearance + camera motion ✅ pluggable
TrackTrack Track-perspective association + track-aware init ✅ pluggable
SORT IoU + Kalman filter

Features

  • 🚀 Native Rust Core Blazingly fast tracking (< 1ms/frame for ByteTrack) with full memory safety
  • 🐍 Python Bindings First-class pip install trackforge support via PyO3
  • 🎯 Multi-Algorithm ByteTrack, OC-SORT, DeepSORT, Deep OC-SORT, BoT-SORT, TrackTrack, and SORT with a unified API
  • 🔌 Pluggable Re-ID The appearance matching is always available; you pass in embeddings. The image based extractor that runs a model over a frame is an opt-in reid-model feature, so the base build stays light
  • 📐 Generic Kalman Filter Configurable position/velocity weighting, gating distance computation

Important

Under active development. APIs and features are subject to change. MSRV: Rust 1.89.

Installation

Python

pip install trackforge

Rust

Add to your Cargo.toml:

[dependencies]
trackforge = "0.3.0"

To build the Python bindings from source (e.g., via maturin develop), enable the python feature:

[dependencies]
trackforge = { version = "0.3.0", features = ["python"] }

Cargo features

The default build is light and pulls no image codecs. Every tracker works on detections you pass in, and the appearance trackers work on embeddings you pass in.

Feature What it adds Extra dependency
default All trackers, embedding based appearance matching, Kalman core none
reid-model The AppearanceExtractor trait plus the DeepSort and DeepOcSort wrappers that run a model over a frame to produce embeddings image
python PyO3 bindings for the Python package pyo3

Enable the image based extractor when you want the library to produce embeddings for you:

[dependencies]
trackforge = { version = "0.3.0", features = ["reid-model"] }

Without it, produce embeddings yourself (any model, any runtime) and drive DeepSortTracker or DeepOcSortTracker directly.

Quick Start

Python - ByteTrack

from trackforge import BYTETRACK

tracker = BYTETRACK(track_thresh=0.5, track_buffer=30, match_thresh=0.8, det_thresh=0.6)

# Format: ([x, y, w, h], confidence, class_id)
detections = [
    ([100.0, 100.0, 50.0, 100.0], 0.9, 0),
    ([200.0, 200.0, 60.0, 120.0], 0.85, 0),
]

tracks = tracker.update(detections)

for track_id, tlwh, score, class_id in tracks:
    print(f"ID: {track_id}, Box: {tlwh}")

Python - DeepSORT

from trackforge import DEEPSORT

tracker = DEEPSORT(
    max_age=30,
    n_init=3,
    max_iou_distance=0.7,
    max_cosine_distance=0.2,
    nn_budget=100,
)

detections = [([100.0, 100.0, 50.0, 100.0], 0.9, 0)]
embeddings = [[0.1, 0.2, 0.3, ...]]  # appearance feature vectors

tracks = tracker.update(detections, embeddings)

for track_id, tlwh, score, class_id in tracks:
    print(f"ID: {track_id}, Box: {tlwh}, Score: {score}")

Python - OC-SORT

from trackforge import OCSORT

tracker = OCSORT(
    max_age=30,
    min_hits=3,
    iou_threshold=0.3,
    delta_t=3,
    inertia=0.2,
)

detections = [
    ([100.0, 100.0, 50.0, 100.0], 0.9, 0),
    ([200.0, 200.0, 60.0, 120.0], 0.85, 0),
]

tracks = tracker.update(detections)

for track_id, tlwh, score, class_id in tracks:
    print(f"ID: {track_id}, Box: {tlwh}")

Python - Deep OC-SORT

from trackforge import DEEPOCSORT

tracker = DEEPOCSORT(
    max_age=30,
    min_hits=3,
    iou_threshold=0.3,
    delta_t=3,
    inertia=0.2,
    appearance_weight=0.5,
    max_cosine_distance=0.2,
    nn_budget=100,
)

detections = [([100.0, 100.0, 50.0, 100.0], 0.9, 0)]
embeddings = [[0.1, 0.2, 0.3]]  # one appearance vector per detection

# Pass embeddings for appearance-aware tracking, or omit them for motion only.
tracks = tracker.update(detections, embeddings)

for track_id, tlwh, score, class_id in tracks:
    print(f"ID: {track_id}, Box: {tlwh}")

Python - BoT-SORT

from trackforge import BOTSORT

tracker = BOTSORT(
    track_thresh=0.5,
    track_buffer=30,
    match_thresh=0.8,
    det_thresh=0.6,
    proximity_thresh=0.5,
    appearance_thresh=0.25,
)

detections = [([100.0, 100.0, 50.0, 100.0], 0.9, 0)]
embeddings = [[0.1, 0.2, 0.3]]  # one appearance vector per detection

# Pass embeddings for appearance-aware tracking, or omit them for motion only.
tracks = tracker.update(detections, embeddings)

# Moving camera: pass a [a, b, tx, c, d, ty] affine mapping the previous frame
# to the current one.
tracks = tracker.update(detections, embeddings, [1.0, 0.0, 12.0, 0.0, 1.0, -4.0])

for track_id, tlwh, score, class_id in tracks:
    print(f"ID: {track_id}, Box: {tlwh}")

Python - TrackTrack

from trackforge import TRACKTRACK

tracker = TRACKTRACK(det_thresh=0.6, match_thresh=0.7, track_buffer=30, min_hits=3)

detections = [([100.0, 100.0, 50.0, 100.0], 0.9, 0)]

# Pass embeddings for appearance-aware tracking, or omit them for motion only.
tracks = tracker.update(detections)

for track_id, tlwh, score, class_id in tracks:
    print(f"ID: {track_id}, Box: {tlwh}")

Rust - ByteTrack

use trackforge::trackers::byte_track::ByteTrack;

let mut tracker = ByteTrack::new(0.5, 30, 0.8, 0.6);

// Format: ([x, y, w, h], confidence, class_id)
let detections = vec![
    ([100.0, 100.0, 50.0, 100.0], 0.9, 0),
    ([200.0, 200.0, 60.0, 120.0], 0.85, 0),
];

let tracks = tracker.update(detections);

for t in tracks {
    println!("ID: {}, Box: {:?}", t.track_id, t.tlwh);
}

Rust - DeepSORT

use trackforge::trackers::deepsort::DeepSort;

// `extractor` implements the AppearanceExtractor trait (plug in any Re-ID model).
let mut tracker = DeepSort::new(extractor, 30, 3, 0.7, 0.2, 100);

let detections = vec![(BoundingBox::new(100.0, 100.0, 50.0, 100.0), 0.9, 0)];
let tracks = tracker.update(&image, detections)?;

for t in tracks {
    println!("ID: {}, Box: {:?}", t.track_id, t.to_tlwh());
}

Rust - OC-SORT

use trackforge::trackers::ocsort::OcSort;

let mut tracker = OcSort::new(30, 3, 0.3, 3, 0.2);

let detections = vec![
    ([100.0, 100.0, 50.0, 100.0], 0.9, 0),
    ([200.0, 200.0, 60.0, 120.0], 0.85, 0),
];

let tracks = tracker.update(detections);

for t in tracks {
    println!("ID: {}, Box: {:?}", t.track_id, t.tlwh);
}

Rust - Deep OC-SORT

use trackforge::trackers::deep_ocsort::DeepOcSort;

// `extractor` implements AppearanceExtractor (plug in any Re-ID model).
let mut tracker = DeepOcSort::new(extractor, 30, 3, 0.3, 3, 0.2, 0.5, 0.2, 100);

let tracks = tracker.update(&image, detections)?;

for t in tracks {
    println!("ID: {}, Box: {:?}", t.track_id, t.tlwh);
}

Rust - BoT-SORT

use trackforge::trackers::botsort::BotSort;

let mut tracker = BotSort::new(0.5, 30, 0.8, 0.6, 0.5, 0.25);

let detections = vec![([100.0, 100.0, 50.0, 100.0], 0.9, 0)];
let embeddings = vec![vec![0.1, 0.2, 0.3]]; // one appearance vector per detection
let tracks = tracker.update(detections, &embeddings);

for t in tracks {
    println!("ID: {}, Box: {:?}", t.track_id, t.tlwh);
}

Rust - SORT

use trackforge::trackers::sort::Sort;

let mut tracker = Sort::new(1, 3, 0.3);

let detections = vec![([100.0, 100.0, 50.0, 100.0], 0.9, 0)];
let tracks = tracker.update(detections);

for t in tracks {
    println!("ID: {}, Box: {:?}", t.track_id, t.tlwh);
}

Rust - TrackTrack

use trackforge::trackers::tracktrack::TrackTrack;

let mut tracker = TrackTrack::new();

let detections = vec![([100.0_f32, 100.0, 50.0, 100.0], 0.9_f32, 0_i64)];
// Pass embeddings for appearance-aware tracking, or an empty slice for motion only.
let tracks = tracker.update(detections, &[]);

for t in &tracks {
    println!("ID: {}, Box: {:?}", t.track_id, t.tlwh);
}

Examples

Runnable demos live under examples/, with both a Python and a Rust entry per tracker.

Tracker Python Rust
ByteTrack byte_track_demo.py (YOLO11) byte_track_demo.rs
DeepSORT deepsort_demo.py (YOLO + ResNet18) deepsort_simple.rs, deepsort_ort.rs (ONNX)
OC-SORT ocsort_demo.py
Deep OC-SORT deep_ocsort_demo.py (YOLO + ResNet18)
BoT-SORT botsort_demo.py (YOLO + ResNet18)
SORT sort_yolo_demo.py (YOLO), sort_rtdetr_demo.py (RT-DETR)
Comparison tracker_comparison.py (ByteTrack vs SORT side-by-side)
# Python
python examples/python/byte_track_demo.py

# Rust
cargo run --example byte_track_demo
cargo run --example deepsort_simple
cargo run --example deepsort_ort --features advanced_examples

The Python demos use the usual detector stacks: ultralytics (YOLO), transformers + torch (RT-DETR), and torch + torchvision (ResNet Re-ID); install what a given demo imports. The deepsort_ort Rust demo needs the advanced_examples feature (ONNX Runtime + OpenCV).

API Reference

Python API Rust API Guide

Parameters

Each tracker's parameters and defaults (identical across Python and Rust) are documented on the Parameters page.

Development

Prerequisites

  • Rust 1.89+ (MSRV)
  • Python 3.8+ and maturin for the bindings
  • prek for git hooks (optional but recommended)

Setup

git clone https://github.com/onuralpszr/trackforge.git
cd trackforge

# Rust core
cargo build
cargo test

# Python bindings (build into the active virtualenv)
maturin develop

Checks

These mirror CI, run them before opening a PR:

cargo fmt --all -- --check          # formatting
cargo clippy --all-targets -- -D warnings   # lint, warnings are errors
cargo test                          # unit, integration, and doc tests
cargo llvm-cov --summary-only       # coverage (cargo install cargo-llvm-cov)
prek run --all-files                # all pre-commit hooks at once

Feature flags

  • python builds the PyO3 bindings.
  • advanced_examples enables the ONNX/OpenCV-backed examples (deepsort_ort), which need ONNX Runtime and OpenCV on the system.
cargo test --features python
cargo run --example deepsort_ort --features advanced_examples

Run a Python example

# After `maturin develop`:
python examples/python/deepsort_demo.py --video your_video.mp4

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

  • For major changes, open an issue first to discuss what you would like to change.
  • PRs should pass CI: cargo fmt, cargo clippy -- -D warnings, cargo test.
  • Use Commitizen for commit messages: cz commit.

Roadmap

Planned trackers and milestones live on the Roadmap page.

Citation

If you use trackforge in your research or project, please cite it. GitHub's "Cite this repository" button reads the CITATION.cff metadata, or use:

@software{trackforge,
  author  = {Sezer, Onuralp},
  title   = {trackforge: A unified, high-performance multi-object tracking library},
  url     = {https://github.com/onuralpszr/trackforge},
  license = {MIT}
}

trackforge provides clean-room implementations of published tracking algorithms. Please also cite the paper for the tracker you use:

Per-tracker citations
@inproceedings{bewley2016sort,
  title={Simple Online and Realtime Tracking},
  author={Bewley, Alex and Ge, Zongyuan and Ott, Lionel and Ramos, Fabio and Upcroft, Ben},
  booktitle={IEEE International Conference on Image Processing (ICIP)},
  year={2016}
}

@inproceedings{wojke2017deepsort,
  title={Simple Online and Realtime Tracking with a Deep Association Metric},
  author={Wojke, Nicolai and Bewley, Alex and Paulus, Dietrich},
  booktitle={IEEE International Conference on Image Processing (ICIP)},
  year={2017}
}

@inproceedings{zhang2022bytetrack,
  title={ByteTrack: Multi-Object Tracking by Associating Every Detection Box},
  author={Zhang, Yifu and Sun, Peize and Jiang, Yi and Yu, Dongdong and Weng, Fucheng and Yuan, Zehuan and Luo, Ping and Liu, Wenyu and Wang, Xinggang},
  booktitle={Proceedings of the European Conference on Computer Vision (ECCV)},
  year={2022}
}

@inproceedings{cao2023ocsort,
  title={Observation-Centric SORT: Rethinking SORT for Robust Multi-Object Tracking},
  author={Cao, Jinkun and Pang, Jiangmiao and Weng, Xinshuo and Khirodkar, Rawal and Kitani, Kris},
  booktitle={Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition (CVPR)},
  year={2023}
}

@inproceedings{maggiolino2023deepocsort,
  title={Deep OC-SORT: Multi-Pedestrian Tracking by Adaptive Re-Identification},
  author={Maggiolino, Gerard and Ahmad, Adnan and Cao, Jinkun and Kitani, Kris},
  booktitle={IEEE International Conference on Image Processing (ICIP)},
  year={2023}
}

@article{aharon2022botsort,
  title={BoT-SORT: Robust Associations Multi-Pedestrian Tracking},
  author={Aharon, Nir and Orfaig, Roy and Bobrovsky, Ben-Zion},
  journal={arXiv preprint arXiv:2206.14651},
  year={2022}
}

License

Distributed under the MIT License. See LICENSE for details.

Releases

Packages

Contributors

Languages