Skip to content

Feat/core/bytetrack #40

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 80 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
0ba61af
First version of ByteTrack, still pending some docs and tests
AlexBodner Apr 28, 2025
860ce3c
Docs improved
AlexBodner Apr 28, 2025
ca68069
Updated __init__ to import bytetrack
AlexBodner Apr 29, 2025
cbd222c
Updated __init__ to import bytetrack
AlexBodner Apr 29, 2025
99ce486
mini bug fix
AlexBodner Apr 29, 2025
27307db
mini bug fix
AlexBodner Apr 29, 2025
8ff0eaf
trying dimension fix for low probability detections
AlexBodner Apr 29, 2025
872d855
trying dimension fix for low probability detections
AlexBodner Apr 29, 2025
654bac3
added rakshit change of the feature extractor
AlexBodner Apr 30, 2025
d641243
added change of the feature extractor and associated indices with Jon…
AlexBodner Apr 30, 2025
07264b4
added change of the feature extractor and associated indices with Jon…
AlexBodner Apr 30, 2025
fddc4e9
added tests and example usage
AlexBodner May 5, 2025
05e5d4b
added IoU test and deepsort feature extractor is like main
AlexBodner May 5, 2025
4dd7a59
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] May 5, 2025
29f08f7
Update feature_extractor.py
AlexBodner May 5, 2025
d50a629
Changed comments and typing
AlexBodner May 6, 2025
324c394
Merge branch 'feat/core/bytetrack' of https://github.com/roboflow/tra…
AlexBodner May 6, 2025
ddff709
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] May 6, 2025
fa92b5c
Changed Raif's suggestion on having get_alive_trackers on update
AlexBodner May 7, 2025
a9ac034
Merge branch 'feat/core/bytetrack' of https://github.com/roboflow/tra…
AlexBodner May 7, 2025
9f61003
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] May 7, 2025
ad9764a
Changed feature extractor comment and removed test files
AlexBodner May 7, 2025
c88ac41
Changed feature extractor comment and removed test files
AlexBodner May 7, 2025
98906b2
Merge branch 'feat/core/bytetrack' of https://github.com/roboflow/tra…
AlexBodner May 7, 2025
df6142b
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] May 7, 2025
3689c21
Added bytetrack docs and all piotr reviews are ok
AlexBodner May 7, 2025
ba0cc29
Merge branch 'feat/core/bytetrack' of https://github.com/roboflow/tra…
AlexBodner May 7, 2025
a41ea92
Added bytetrack docs and all piotr reviews are ok
AlexBodner May 7, 2025
071fa02
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] May 7, 2025
9cbdb54
Fixed ruff errors and added Soumik requested docs
AlexBodner May 8, 2025
6d9205a
Fixed ruff errors and added Soumik requested docs
AlexBodner May 8, 2025
d6c295d
Merge branch 'feat/core/bytetrack' of https://github.com/roboflow/tra…
AlexBodner May 8, 2025
78cdfe0
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] May 8, 2025
5fa2951
fixed mypy errors
AlexBodner May 8, 2025
4d8492c
Merge branch 'feat/core/bytetrack' of https://github.com/roboflow/tra…
AlexBodner May 8, 2025
7dafa3a
fixed mypy errors
AlexBodner May 8, 2025
b913011
fix(pre_commit): 🎨 update pre-commit configuration for improved forma…
onuralpszr May 8, 2025
08aa7bb
Merge branch 'main' into feat/core/bytetrack
onuralpszr May 8, 2025
9ae88f0
feat: add MyPy test workflow and update configuration files
onuralpszr May 8, 2025
0330bf2
possible fix of mypy any problems
AlexBodner May 8, 2025
43150c0
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] May 8, 2025
4486578
possible fix to mypy and ruff errors
AlexBodner May 8, 2025
078aab5
possible fix to mypy and ruff errors
AlexBodner May 8, 2025
6a9af9e
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] May 8, 2025
4002294
possible fix to mypy and ruff errors
AlexBodner May 8, 2025
f172a97
Merge branch 'feat/core/bytetrack' of https://github.com/roboflow/tra…
AlexBodner May 8, 2025
9d3b53d
chore: 🧹 better docstring formatting for init warning messages
onuralpszr May 9, 2025
76be1d5
fix: 🐛 update keywords and dependencies in pyproject.toml
onuralpszr May 9, 2025
a8d3a43
chore: 🧹 improve docstring formatting and clarity in _similarity_step…
onuralpszr May 9, 2025
3a293ea
fix: 🐛 correct exclusion pattern for test folder in MyPy test workflow
onuralpszr May 9, 2025
97d5caa
rearranged ByteTrack tracker parameters to be like DeepSORT
AlexBodner May 9, 2025
03ae11a
Merge branch 'feat/core/bytetrack' of https://github.com/roboflow/tra…
AlexBodner May 9, 2025
4eeb807
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] May 9, 2025
4376e59
Fixed example highlight and added examples with and without feature e…
AlexBodner May 9, 2025
ae30973
Merge branch 'feat/core/bytetrack' of https://github.com/roboflow/tra…
AlexBodner May 9, 2025
a22bda0
now ByteTrackTracker._update_detections return the updated list
AlexBodner May 9, 2025
d9dc615
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] May 9, 2025
6747901
Merge branch 'main' into feat/core/bytetrack
onuralpszr May 12, 2025
41d0452
ci: 👷 type groups are added into mypy workflow
onuralpszr May 12, 2025
e51bd50
fix(pre_commit): 🎨 auto format pre-commit hooks
pre-commit-ci[bot] May 12, 2025
ef5d72c
slight md change
AlexBodner May 12, 2025
ecaa50c
Merge branch 'feat/core/bytetrack' of https://github.com/roboflow/tra…
AlexBodner May 16, 2025
d008b01
Merge branch 'main' into feat/core/bytetrack
AlexBodner May 16, 2025
4c326f4
Adding ReID model instead of DeepSORT feature extractor breaks the usage
AlexBodner May 16, 2025
0e7ade6
modified workflow that installed deepsort, now installs reid
AlexBodner May 16, 2025
0a06902
fix: 🐞 add additional metrics dependencies for mypy check to GH Action
onuralpszr May 19, 2025
727ea04
fix: 🐞 update feature extraction method parameters order in DeepSORTT…
onuralpszr May 19, 2025
f5ff96c
fix: 🐞 simplify random_state type annotation in get_market1501_datase…
onuralpszr May 19, 2025
5331f24
fix: 🐞 add checks for 'num_features' attribute and its type in ReIDMo…
onuralpszr May 19, 2025
9ba8857
fix: 🐞 update type annotations and fix image transformation handling …
onuralpszr May 19, 2025
b28d819
Merge branch 'main' into feat/core/bytetrack
onuralpszr May 19, 2025
110149c
Merge branch 'main' into feat/core/bytetrack
AlexBodner May 19, 2025
1d351b5
now reid model.extract_features sets 0 to the bbox coordinates that a…
AlexBodner May 19, 2025
df2a902
Merge branch 'feat/core/bytetrack' of https://github.com/roboflow/tra…
AlexBodner May 19, 2025
511e083
removed print
AlexBodner May 20, 2025
0d89ae1
update: bytetrack feature association
soumik12345 May 26, 2025
2284fe7
update: get_features
soumik12345 May 26, 2025
6d1ce84
Merge branch 'feat/core/bytetrack' into fix/bytetrack-feature-associa…
soumik12345 May 26, 2025
8b81e90
Updated docs with ReID merge
AlexBodner May 26, 2025
dfac192
Merge pull request #65 from roboflow/fix/bytetrack-feature-association
soumik12345 May 27, 2025
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
33 changes: 33 additions & 0 deletions .github/workflows/mypy-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: 🔧 MyPy Test Workflow

on:
pull_request:
branches: [main]

jobs:
run-tests:
name: MyPy Run Tests
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
python-version: ["3.11"]

runs-on: ${{ matrix.os }}
steps:
- name: 📥 Checkout the repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: 🐍 Install uv and set Python version ${{ matrix.python-version }}
uses: astral-sh/setup-uv@0c5e2b8115b80b4c7c5ddf6ffdd634974642d182 # v5.4.1
with:
python-version: ${{ matrix.python-version }}
# TODO(https://github.com/astral-sh/setup-uv/issues/226): Remove this.
prune-cache: ${{ matrix.os != 'windows-latest' }}

- name: 🚀 Install Packages
run: uv pip install -r pyproject.toml --group dev --group docs --extra cpu --extra deepsort

- name: 🧪 Run MyPy Test
run: uv run mypy --config-file mypy.ini --exclude "tests|docs" .
6 changes: 0 additions & 6 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,3 @@ repos:
args: [--fix, --exit-non-zero-on-fix]
- id: ruff-format
types_or: [ python, pyi, jupyter]

- repo: https://github.com/pre-commit/mirrors-mypy
rev: 'v1.15.0'
hooks:
- id: mypy
additional_dependencies: [numpy]
157 changes: 157 additions & 0 deletions docs/trackers/core/bytetrack/tracker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
---
comments: true
---

# ByteTrack

[![arXiv](https://img.shields.io/badge/arXiv-2110.06864-b31b1b.svg)](https://arxiv.org/pdf/2110.06864)
[![colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1C7XyJV8_V6HJwx20E838oQ03F5DLauuC?usp=sharing) <!-- Change the URL to custom Roboflow one before merging -->

## Overview

ByteTrack presents a simple and generic association method which associates almost every detection box instead of only the high probability ones. Low score boxes are typically occluded object, so leaving out this objects of the tracking will result in a fatal failure, but because they aren't clearly seen in the image we cannot trust on it's appearance.

That's why the proposed method consists in 2 key steps. The first step will associate the high score detections to the existing tracks using a chosen similarity metric that can be either IoU or based in appearance features. The second step will associate the low score detections to the trackers that didn't match in the previous step using IoU distance. In addition to this, we added parametrized thresholds for accepting the matches only if the similarity is higher to the corresponding threshold. Finally it starts new tracks with the high score detections that didn't match in step 1. Just like [SORT](../sort/tracker.md) and [DeepSORT](../deepsort/tracker.md) this method combines Kalman Filters for having a motion model in order to match low score boxes and the Hungarian algorithm for calculating the optimal associations.

While calculating the appearance features with a Convolutional Neural Network might be slower than only comparing IoU, it makes it possible to track unpredictable trajectories and objects that dissapear and reappear in the scene, while also being suitable for real time tracking.

BytTrack is independent on the object detector and feature extractor network so it can be used for any tracking task as long as the user provides the adequate model.


## Examples

=== "rf-detr"

```python hl_lines="2 5-8 15"
import supervision as sv
from rfdetr import RFDETRBase
from trackers import ByteTrackTracker
from trackers.core.deepsort.feature_extractor import DeepSORTFeatureExtractor

model = RFDETRBase(device="cuda") # Load the Object Detector
feature_extractor = DeepSORTFeatureExtractor.from_timm(
model_name="mobilenetv4_conv_small.e1200_r224_in1k",
)
tracker = ByteTrackTracker(feature_extractor=feature_extractor)

annotator = sv.LabelAnnotator(text_position=sv.Position.CENTER)

def callback(frame, _):
# Obtain bounding box predictions from RF-DETR
detections = model.predict(frame, threshold=0.5)

# Update tracker with new detections and retrieve updated IDs
detections = tracker.update(detections, frame)
return annotator.annotate(frame, detections, labels=detections.tracker_id)

sv.process_video(
source_path="input.mp4",
target_path="output.mp4",
callback=callback,
)
```
=== "inference"

```python hl_lines="2 5-8 15"
import supervision as sv
from trackers import DeepSORTFeatureExtractor
from trackers import ByteTrackTracker
from inference import get_model

feature_extractor = DeepSORTFeatureExtractor.from_timm(
model_name="mobilenetv4_conv_small.e1200_r224_in1k"
)
tracker = ByteTrackTracker(feature_extractor=feature_extractor)
model = get_model(model_id="yolov11m-640")
annotator = sv.LabelAnnotator(text_position=sv.Position.CENTER)

def callback(frame, _):
result = model.infer(frame)[0]
detections = sv.Detections.from_inference(result)
detections = tracker.update(detections, frame)
return annotator.annotate(frame, detections, labels=detections.tracker_id)

sv.process_video(
source_path="input.mp4",
target_path="output.mp4",
callback=callback,
)
```


=== "ultralytics"

```python hl_lines="2 5-8 15"
import supervision as sv
from trackers import DeepSORTFeatureExtractor
from trackers import ByteTrackTracker

from ultralytics import YOLO

feature_extractor = DeepSORTFeatureExtractor.from_timm(
model_name="mobilenetv4_conv_small.e1200_r224_in1k"
)
tracker = ByteTrackTracker(feature_extractor=feature_extractor)
model = YOLO("yolo11m.pt")
annotator = sv.LabelAnnotator(text_position=sv.Position.CENTER)

def callback(frame, _):
result = model(frame)[0]
detections = sv.Detections.from_ultralytics(result)
detections = tracker.update(detections, frame)
return annotator.annotate(frame, detections, labels=detections.tracker_id)

sv.process_video(
source_path="input.mp4",
target_path="output.mp4",
callback=callback,
)
```

=== "transformers"

```python hl_lines="3 6-9 31"
import torch
import supervision as sv
from trackers import DeepSORTFeatureExtractor
from trackers import ByteTrackTracker
from transformers import RTDetrV2ForObjectDetection, RTDetrImageProcessor

feature_extractor = DeepSORTFeatureExtractor.from_timm(
model_name="mobilenetv4_conv_small.e1200_r224_in1k"
)
tracker = ByteTrackTracker(feature_extractor=feature_extractor)
processor = RTDetrImageProcessor.from_pretrained("PekingU/rtdetr_v2_r18vd")
model = RTDetrV2ForObjectDetection.from_pretrained("PekingU/rtdetr_v2_r18vd")
annotator = sv.LabelAnnotator(text_position=sv.Position.CENTER)

def callback(frame, _):
inputs = processor(images=frame, return_tensors="pt")
with torch.no_grad():
outputs = model(**inputs)

h, w, _ = frame.shape
results = processor.post_process_object_detection(
outputs,
target_sizes=torch.tensor([(h, w)]),
threshold=0.5
)[0]

detections = sv.Detections.from_transformers(
transformers_results=results,
id2label=model.config.id2label
)

detections = tracker.update(detections, frame)
return annotator.annotate(frame, detections, labels=detections.tracker_id)

sv.process_video(
source_path="input.mp4",
target_path="output.mp4",
callback=callback,
)
```

## Usage

::: trackers.core.bytetrack.tracker.ByteTrackTracker
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,4 @@ nav:
- Trackers:
- SORT: trackers/core/sort/tracker.md
- DeepSORT: trackers/core/deepsort/tracker.md
- ByteTrack: trackers/core/bytetrack/tracker.md
7 changes: 7 additions & 0 deletions mypy.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
python_version = 3.9
plugins = numpy.typing.mypy_plugin


[mypy-requests]
ignore_missing_imports = True

Expand All @@ -16,3 +17,9 @@ ignore_missing_imports = True

[mypy-firerequests]
ignore_missing_imports = True

[mypy-scipy.optimize]
ignore_missing_imports = True

[mypy-scipy.spatial.distance]
ignore_missing_imports = True
9 changes: 9 additions & 0 deletions trackers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,12 @@
"Please run `pip install trackers[deepsort]` and try again."
)
pass
try:
from trackers.core.bytetrack.tracker import ByteTrackTracker

__all__.extend(["ByteTrackTracker"])
except ImportError:
logger.warning(
"ByteTrack dependencies not installed. ByteTrack features will not be available. " # noqa: E501
"Please run `pip install trackers` and try again."
)
Empty file.
Loading