High-performance C++20 reimplementation of the StrongSORT multi-object tracker with Python bindings.
The reference StrongSORT implementation is pure Python/NumPy and struggles to hold real-time rates on embedded hardware. This project reimplements the tracking core — Kalman filter, appearance/motion association, and linear assignment — in C++ with Eigen, exposed to Python via pybind11 as a drop-in tracker for existing detection pipelines. It was developed for real-time tracking on embedded GPUs (NVIDIA Jetson) as part of my MSc thesis at MIPT, Optimisation of the StrongSORT Multi-Object Tracking Algorithm for Embedded Systems (2025), and field-deployed in the MSU Rover Team perception stack.
Measured for the thesis on desktop (Intel Core i7, 3.0 GHz) and embedded ARM (8-core NVIDIA Jetson) against the reference Python implementation, tracking accuracy unchanged on standard MOT benchmarks:
| Component | Python (reference) | C++ (this repo) | Speedup |
|---|---|---|---|
| IoU matrix computation | 18.0 ms | 2.4 ms | 7.5× |
| Tracker update, 100 simultaneous objects | — | 3.1 ms | — |
| Full pipeline, per frame | 87 ms | 74 ms | 1.18× |
| RAM usage | baseline | −15% | — |
The full-pipeline number is dominated by detector and ReID inference; the tracker itself drops from the profile almost entirely.
- Motion model — constant-velocity Kalman filter over
(x, y, aspect, height)with confidence-weighted measurement noise (NSA) and chi-square gating, implemented on Eigen fixed-size matrices. - Appearance model — per-track budget of 512-d ReID embeddings (bring your own extractor, e.g. OSNet) combined with motion cost for association.
- Assignment — rectangular linear sum assignment (Hungarian) adapted from SciPy's C++ solver (
src/lsap). - Cache-friendly layout — structure-of-arrays data paths and preallocated buffers keep the per-frame update allocation-free in steady state.
Requirements: CMake ≥ 3.20, a C++20 compiler, OpenCV (core module only), Eigen 3.4.
git clone --recursive https://github.com/IaroslavSheipak/StrongSort.git
cd StrongSort
# as a pip package (builds the extension with scikit-build-core)
pip install .
# or plain CMake
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -jimport numpy as np
import strongsort_py
tracker = strongsort_py.StrongSort(
max_dist=0.2, # appearance-distance gate
max_iou_distance=0.7, # IoU gate for fallback association
max_age=70, # frames to keep a lost track alive
n_init=3, # consecutive hits to confirm a track
nn_budget=100, # appearance features kept per track
)
# per frame: boxes in absolute pixels as (left, top, width, height)
ltwh = np.array([[100, 200, 80, 160]], dtype=np.float32) # (N, 4)
confidences = np.array([0.9], dtype=np.float32) # (N,)
classes = np.array([0], dtype=np.int32) # (N,)
features = reid_extractor(crops) # (N, 512) float32
tracks = tracker.update(ltwh, confidences, classes, features, (width, height))
for t in tracks:
l, t_, w, h = t.ltwh(width, height)
print(t.track_id, t.class_id, t.confidence, (l, t_, w, h))example.py shows a complete pipeline: YOLOv5 detections + OSNet (torchreid) embeddings feeding the tracker on a video file.
| Member | Description |
|---|---|
StrongSort(max_dist, max_iou_distance, max_age, n_init, nn_budget) |
Construct a tracker. |
update(ltwh, confidences, classes, features, image_size) |
Advance one frame; returns list[TrackedBox] of confirmed tracks. |
track_ids() |
Ids of all tracks currently maintained. |
increment_ages() |
Age tracks on a skipped frame. |
dump_tracks() |
Current track state as a JSON string. |
TrackedBox |
track_id, class_id, confidence, time_since_update, relative x1/y1/x2/y2, and ltwh(w, h) / xyxy(w, h) / array() accessors. |
- Du et al., StrongSORT: Make DeepSORT Great Again, IEEE TMM 2023 — the algorithm this project reimplements; reference code at dyhBUPT/StrongSORT.
src/lsapis adapted from SciPy'slinear_sum_assignmentsolver and retains its BSD-3-Clause license header.
MIT — see LICENSE. The vendored src/lsap solver and src/nlohmann/json.hpp retain their original licenses (BSD-3-Clause and MIT respectively).