Repository navigation
Track by appearance as well as motion. Trackers 2.7.0 brings optional Re-ID to BoT-SORT, helping it distinguish similar trajectories using how objects look. Choose standard or adaptive appearance fusion, tune it on your footage, and explore working examples for sports tracking, moving cameras and mask visualization.
- Add appearance matching with standard BoT-SORT or adaptive fusion.
- Tune matching on your footage with distance sampling, plots and frame-gap analysis.
- Configure your tracking runs through grouped CLI options and YAML files.
- Handle camera motion and inspect masks with OC-SORT camera-motion compensation and McByte inspection tools.
- Try three complete notebooks covering Re-ID, camera motion and mask tracking.
Before upgrading, read the Migration guide section below, especially the moved imports and changed defaults.
✨ Highlights
Add appearance matching to BoT-SORT
BoT-SORT can use an appearance encoder from the standalone reid package, or a compatible encoder object, to improve association where appearance is informative. Re-ID remains off by default and augments the first and unconfirmed matching stages; the low-confidence second stage still uses geometry. (#511, #655)
Install the optional model and plotting dependencies with:
pip install 'trackers[reid]==2.7.0'from trackers import BoTSORTTracker, ReIDConfig
tracker = BoTSORTTracker(
reid_model="fastreid_mot17_sbs50",
reid_config=ReIDConfig(appearance_threshold=0.25),
)
# Supply your detector's supervision.Detections and its BGR frame:
tracked = tracker.update(detections, frame=frame_bgr)The extra pins reid==0.1.0; the integration uses the package's extract_embeddings API (#615). Model-source strings load when the tracker is constructed; importing trackers alone does not load reid or torch. Model availability and downloads remain external prerequisites for this example.
Tune matching on your footage
ReIDConfig(fusion="botsort") uses the better of the geometry and appearance scores after proximity and appearance checks. fusion="adaptive" adds an appearance term whose weight increases when the best candidate stands apart from the runner-up; this incorporates Deep OC-SORT's appearance weighting, not the complete tracker. (#511, #571)
Both methods use appearance_threshold as a maximum distance, 0.5 * (1 - cosine similarity), defaulting to 0.25. Adaptive fusion changes the score range, so retune the first and unconfirmed association thresholds when switching; it is not a guaranteed accuracy improvement on every dataset.
The new trackers.reid tools extract ground-truth embeddings, sample same/different-identity distances, report acceptance rates and ROC AUC, and plot results across frame gaps. Tuner adds per-run search spaces, fixed constructor defaults and optional embedding caching, with conditional Re-ID parameters when an encoder is supplied.
The Re-ID documentation also explains the tracking-speed cost of appearance matching (#621).
Configure tracking runs and inspect mask behavior
The CLI now supports grouped options and --config YAML files, including tracker IoU variants, state estimators and McByte mask settings. Existing semantic spellings generally remain as warning-emitting aliases until 2.10.0. (#413, #552)
trackers track --source clip.mp4 --tracker botsort \
--detection.mot_file detections.txt \
--tracker.enable_cmc true --output.video tracked.mp4trackers benchmark mcbyte writes MOTChallenge results for supported benchmark datasets. trackers inspect sam, cutie, mask-manager and mcbyte provide visual checks of mask generation, propagation, lifecycle and tracking. (#541, #543)
Compensate camera motion and configure evaluation
OC-SORT gains opt-in camera-motion compensation that updates both the live track state and its observation history. BoT-SORT also accepts a precomputed per-frame affine transform when no frame is supplied; use internal frame-based CMC when enabling Re-ID. (#611, #610)
Evaluation now supports MOTClassConfig, a MOT20 preset and custom scored/distractor classes. MOT17 remains the default, while MOT20-like sequence names trigger a warning when evaluated under that default. (#597, #598)
Try three complete tracking notebooks
The repository includes notebooks for Re-ID and threshold analysis, BoT-SORT on a moving camera, and McByte mask tracking. They target 2.7.0 and require their documented models, datasets and optional dependencies. (#511, #623, #630)
🔄 Migration guide
- BoT-SORT constructor: positional calls supported by 2.6.1 remain supported. The development regression introduced in #611 was corrected before release in #658.
- Changed defaults: McByte uses
cmc_downscale=6instead of2; CLI tracking now uses detected source FPS unless overridden. Set the former values explicitly when reproducing old runs. - Imports and CLI: replace
trackers.scriptswith the console command orpython -m trackers.cli; move deep mask imports totrackers.core.masks. Package-level mask compatibility shims are deprecated until 3.0. - Dependencies: Python remains 3.10+, but Supervision now requires 0.31.0+. The base installation adds
jsonargparse>=4.48.0,<5. - Results: empty detection results preserve input fields and optional
Nonevalues; non-finite boxes raise before state changes. Evaluation sequence names and hidden-directory discovery also change.
Migration guide: examples and detailed upgrade instructions
1. BoT-SORT positional calls remain supported
The constructor retains the positional parameter order supported by 2.6.1.
The development regression introduced in #611 was corrected before release
in #658.
No positional-argument migration is required. Existing calls can also use
the new reid_model and reid_config options by keyword.
2. Check dependencies and reproducibility settings
Install with pip install 'trackers==2.7.0', or select extras such as 'trackers[reid,tune]==2.7.0' for appearance-assisted tuning.
| Setting | 2.6.1 | 2.7.0 / action |
|---|---|---|
| Python | >=3.10 |
Unchanged; CI build job using 3.12 does not raise the minimum. |
| Supervision | >=0.26.1 |
>=0.31.0; resolve downstream constraints against this floor. |
| CLI parser | argparse implementation | New base dependency jsonargparse>=4.48.0,<5. |
| Re-ID extra | Unavailable | reid==0.1.0, matplotlib>=3.7.0; model weights are external. |
McByte cmc_downscale |
2 |
6; set McByteTracker(cmc_downscale=2) to retain the former setting. |
| CLI tracker frame rate | Constructor default, normally 30 FPS | Finite positive source FPS unless explicitly overridden; --tracker.frame_rate 30 restores the old CLI setting. |
| OC-SORT CMC | Unavailable | Off by default; opt in with enable_cmc=True. |
| BoT-SORT Re-ID | Unavailable | Off by default (reid_model=None). |
CMC downscale can affect accuracy as well as latency. The existing McByte benchmark rationale used masks disabled and aggregate dataset criteria, with some clips regressing; it does not establish a universal speed/quality gain.
3. Migrate CLI commands and implementation imports
The trackers executable remains. Replace python -m trackers.scripts with python -m trackers.cli; the old trackers.scripts package and its direct imports have no compatibility shim.
# Before
trackers track --source clip.mp4 --model rfdetr-base \
--classes person,car --tracker bytetrack --output tracked.mp4
# After
trackers track --source clip.mp4 --detection.model rfdetr-base \
--filters.classes '[person,car]' --tracker bytetrack \
--output.video tracked.mp4The detector example needs the detection extra and any model credentials/resources. Quote bracket lists in shells such as zsh.
| Legacy form | Current form |
|---|---|
--detections |
--detection.mot_file |
--model.confidence, --model.device, --model.api_key |
--detection.confidence, --detection.device, --detection.api_key |
--track_ids |
--filters.track_ids '[1,3,5]' |
--mot-output, --overwrite |
--output.mot_results, --output.overwrite |
--show-boxes, --no-boxes, --no-ids |
--show.boxes, --show.no_boxes, --show.no_ids |
--tracker.minimum_consecutive_frames |
--tracker.min_consecutive_frames |
--tracker.minimum_iou_threshold |
--tracker.min_iou_threshold (only trackers with that parameter) |
--tracker.iou |
--tracker.iou_variant |
eval --tracker, eval --tracker_dir |
eval --predictions, eval --predictions_dir |
download mot17 |
download --name mot17 |
--metrics CLEAR HOTA |
--metrics '["CLEAR","HOTA"]' |
Legacy semantic aliases warn with removal scheduled for 2.10.0. Do not pass both an old option and its replacement; --tracker NAME remains supported without warning as shorthand for --tracker.name NAME.
Use explicit tracker boolean values: --tracker.enable_cmc true or false. The legacy bare flag preserves its previous toggle behavior (false for default-true BoT-SORT/McByte), which can be surprising; regular grouped booleans use forms such as --show.no_boxes.
Python constructor, tuning fixed_params and search_space keys keep their full minimum_/maximum_ names. The shortened names are CLI aliases only.
YAML configuration is new relative to published 2.6.1. Both track and tune use a nested tracker selector, for example:
tracker:
name: bytetrackPass YAML using --config; explicit CLI values override configuration. See the complete CLI migration reference for all aliases.
4. Update mask-stack imports
# Before
from trackers.core.mcbyte.masks.sam import SAMBoxMaskGenerator
from trackers.core.mcbyte.mask_manager import MaskManager
# After
from trackers.core.masks.sam import SAMBoxMaskGenerator
from trackers.core.masks.manager import MaskManagerMaskGenerator, MaskPropagator, MaskOutput, and TrackletSnapshot now live at trackers.core.masks. Their old package-level exports and the old MaskManager path have deprecated shims scheduled for removal in 3.0; old deep modules .base, .sam, .cutie, and .dummy are already gone. Some shims proxy classes rather than preserving class identity, so migrate code using is comparisons as well.
McByte's mask_config Python argument is unchanged; the new CLI group is --tracker.mask.*. McByte still requires RGB frames for its mask pipeline; BoT-SORT and OC-SORT use BGR frames.
5. Enable Re-ID deliberately and retune when switching fusion
from trackers import BoTSORTTracker, ReIDConfig
tracker = BoTSORTTracker(
reid_model="fastreid_mot17_sbs50",
reid_config=ReIDConfig(
fusion="adaptive",
ema_alpha=0.9,
appearance_threshold=0.25,
proximity_threshold=0.5,
appearance_weight=0.75,
adaptive_weight_cap=0.5,
),
)
tracked = tracker.update(detections, frame=frame_bgr)detections and frame_bgr must come from your own frame/detector loop. Strings load through reid.ReIDModel.from_pretrained; pass a compatible encoder object when choosing device/loading behavior yourself. ReIDEncoder.extract_embeddings(detections, frame) receives BGR frames and returns a float32 matrix with one embedding per detection.
A reid_config without reid_model raises ValueError. With a model, every update() requires a frame, including empty detections. The CLI uses --reid.model (or --reid.enable for the default model) and --tracker.reid_config.*; Re-ID integration is currently for BoT-SORT only.
Both fusion modes gate appearance distance 0.5 * (1 - cosine) at appearance_threshold=0.25 and allow appearance to contribute only when standard IoU is at least 1 - proximity_threshold (default 0.5). Pairs outside this gate can still match through geometry alone. proximity_threshold=1.0 disables that geometric gate and needs careful domain-specific evaluation.
fusion="botsort" is the default. Adaptive fusion can reach 1 + appearance_weight + adaptive_weight_cap (2.25 by default), so retune minimum_iou_threshold_first_assoc and minimum_iou_threshold_unconfirmed_assoc; the low-confidence second association remains geometry-only. Adaptive weighting does not add the full Deep OC-SORT algorithm or its velocity-direction cost.
Use extract_ground_truth_embeddings, sample_appearance_distances, AppearanceDistances.rates_at, roc_auc, sweep_frame_gap and the plotting helpers in trackers.reid to calibrate the gate on labeled footage. Sampling defaults to a 1–30 frame gap; choose a gap consistent with the tracker buffer and frame rate rather than copying a threshold from a different encoder.
For tuning, supply a fixed encoder and images_dir containing <sequence>/img1/. Tuner(..., search_space=..., fixed_defaults=..., cache_embeddings=True) can override search ranges, hold constructor defaults and reuse embeddings across trials; caching defaults to false and uses memory proportional to cached detections. Explicit fixed_params wins over fixed_defaults; nested reid_config.* fields use full Python names. CLI tune exposes Re-ID, search-space and fixed-default options but does not expose cache_embeddings directly.
6. Respect CMC input constraints
from trackers import OCSORTTracker
tracker = OCSORTTracker(enable_cmc=True, cmc_method="sparseOptFlow", cmc_downscale=2)
tracked = tracker.update(detections, frame=frame_bgr)OC-SORT CMC remains off by default; when enabled without a frame it skips compensation and warns. It compensates observation history and ORU state as well as the live Kalman state.
BoT-SORT's alternative update(detections, cmc_transform=affine) takes a finite real (2, 3) transform from the previous frame to the current frame, not a cumulative transform or 3×3 homography. It applies regardless of enable_cmc, resets the internal estimator, and cannot be supplied together with frame.
Consequently precomputed CMC cannot be combined with Re-ID in 2.7.0, because Re-ID requires frame. Use internal frame-based CMC with Re-ID. C-BIoU accepts the transform keyword only to match the parent signature, warns and ignores it; McByte and OC-SORT do not expose that keyword.
7. Adapt result handling and evaluation scripts
All six trackers now reject NaN/inf boxes before state changes. Filter invalid detections before calling update() if your detector can emit them; low-confidence invalid rows are not exempt.
Empty results preserve input data keys, masks, metadata and dtypes. result.confidence or result.class_id can be None when absent on input, so code that assumed empty arrays should check for None; obtain track IDs from the returned detections.
For MOT20, select the appropriate evaluator preset:
trackers eval --gt data/MOT20-01/gt/gt.txt \
--predictions predictions/MOT20-01.txt \
--class_config mot20 --metrics '["CLEAR","HOTA","Identity"]'Python evaluate_mot_sequence and evaluate_mot_sequences accept class_config="mot20" or a MOTClassConfig. MOT17 remains the default; MOT20 adds class 6 to distractors. Custom scored classes must be nonempty, integer-valued and disjoint from distractors. Tuner does not expose class_config, so do not assume selecting a MOT20 evaluation preset changes tuning preprocessing.
Both evaluators reject unknown metric families; use CLEAR, HOTA, or Identity. A path <sequence>/gt/gt.txt now reports <sequence> instead of gt in result names and JSON; update downstream name matching. Hidden sequence directories are skipped by automatic discovery; include intentional hidden sequences explicitly in a seqmap.
OC-SORT reacquisition using XCYCWHStateEstimator now encodes interpolated boxes correctly; affected trajectories and metrics can change. Converter dtype behavior and OC-SORT low-confidence tracker_id=-1 rows already shipped in 2.6.1 and are not new migrations from that version.
📝 Notable changes
Fixed
- Empty results from all six trackers retain the input's data keys, masks, metadata and dtypes. Missing confidence/class fields remain
None. (#638) - Non-finite bounding boxes are rejected before predictions, timestamp changes or ID allocation, including low-confidence rows previously discarded by some trackers. (#613)
- OC-SORT's observation-centric re-update correctly encodes virtual boxes for
XCYCWHStateEstimator, fixing reacquisition after missed frames. (#614) - MOT-layout evaluation names sequences after their directory and skips hidden sequence directories during automatic discovery. (#635, #642)
Changed
- Evaluation reduces ID-remapping and overlap-allocation work; Kalman prediction avoids unnecessary covariance and box reconstruction; McByte skips mask-only association work without mask evidence. (#572, #573, #574, #576, #577, #578, #579, #580)
- BoT-SORT and McByte share scale-aware noise machinery. Documentation navigation, CLI guides, development tooling and dependency locks have also been updated. (#596, #548, #549, #551, #625, #648)
Fixes already published in 2.6.1—including malformed-box GIoU handling, OC-SORT low-confidence output rows, durable McByte mask cleanup, split Kalman noise refresh, converter dtype handling, natural image ordering and documentation URLs—remain in the historical changelog. They are not new 2.7.0 features.
🏆 Contributors
- Alexander Bodner (@AlexBodner, LinkedIn) — BoT-SORT Re-ID integration and analysis tools; tracking cookbooks; the pinned Re-ID dependency.
- Tomasz Stańczyk (@tstanczyk95, LinkedIn) — release preparation, technical supervision, guidance and expertise; compatibility fixes and notebook validation.
- Jirka Borovec (@Borda, LinkedIn) — CLI/configuration and mask tooling; tracking and evaluation integration; documentation and maintenance.
- Jesús Royeth (@JESUSROYETH, LinkedIn) — evaluation and Kalman performance improvements; McByte association optimization; source-FPS propagation.
- Ruben (@RubenHaisma, LinkedIn) — opt-in camera-motion compensation for OC-SORT.
- 9cvele3 (@9cvele3) — precomputed camera-motion transforms for BoT-SORT.
- Omkar Kabde (@omkar-334, LinkedIn) — configurable MOT ground-truth class handling.
- Devraj Pal (@itzzdev09) — MOT20 evaluation support and shared scale-aware tracklet machinery.
- Lương Thanh Hoàng Phú (@lthphuw, LinkedIn) — non-finite detection validation and OC-SORT virtual-box encoding.
- Kari Pikkarainen (@kari-pikkarainen, LinkedIn) — preservation of input fields in empty results and Supervision-compatible validation tests.
- Raphael Fakhri (@RaphaelFakhri, LinkedIn) — MOT-layout sequence naming.
- Maidul Hasan Masum (@mh-masum6875, LinkedIn) — hidden-directory filtering in evaluation discovery.
- Piotr Skalski (@SkalskiP, LinkedIn) — repository code-owner maintenance.
Automated contributions: @Copilot, @claude[bot], @dependabot[bot], @pre-commit-ci[bot], Claude Code, Claude Fable 5, Claude Fable 5.1, Claude Opus 4.8, Claude Opus 5, Claude Opus 5.5, Codex, Cursor, OpenAI Codex
Full changelog: Trackers 2.7.0 changelog.
Compare 2.6.1 and 2.7.0. This comparison crosses divergent branches and includes already-shipped work; the changelog separates the release history.
New Contributors
- @MahathirMohammadShuvo made their first contribution in #589
- @itzzdev09 made their first contribution in #596
- @lthphuw made their first contribution in #613
- @9cvele3 made their first contribution in #610
- @RaphaelFakhri made their first contribution in #635
- @kari-pikkarainen made their first contribution in #638
- @mh-masum6875 made their first contribution in #642
Full Changelog: 2.6.0...2.7.0