Skip to content

Tracker

BoxMOT tracking utilities and unified tracker interface.

This module provides the Tracker class for BoxMOT tracking and post-processing utilities for infilling, clustering, and filtering tracks.

MOTModels

Bases: StrEnum

Supported tracker backends exposed by BoxMOT.

Attributes:

Name Type Description
BOTSORT str

BoT-SORT tracker name used by BoxMOT. Good default when you want motion + appearance matching.

BOOSTTRACK str

BoostTrack tracker name used by BoxMOT. Usually improves association under difficult motion/crowding.

BYTE_TRACK str

ByteTrack tracker name used by BoxMOT. Faster and simpler; does not require ReID weights.

OCSORT str

OCSORT tracker name used by BoxMOT. Motion-centric tracker; useful when appearance features are unreliable.

STRONGSORT str

StrongSORT tracker name used by BoxMOT. Appearance-heavy tracker; typically more robust to long occlusions.

DEEPOCSORT str

DeepOCSORT tracker name used by BoxMOT. OCSORT variant enhanced with appearance features.

HYBRIDSORT str

HybridSORT tracker name used by BoxMOT. Hybrid strategy between motion and appearance matching.

SFSORT str

SFSort tracker name used by BoxMOT. Lightweight motion-centric tracking for real-time pipelines.

ReIDWeights

Bases: StrEnum

Built-in BoxMOT ReID weight file names.

Use these enum values for reid_weights in tracker parameter dataclasses.

MOTBaseConfig dataclass

MOTBaseConfig(
    model: MOTModels = MOTModels.BOTSORT,
    per_class: bool = False,
    extra_kwargs: dict[str, Any] = dict(),
)

Common configuration fields for BoxMOT tracker creation.

Attributes:

Name Type Description
model MOTModels

BoxMOT tracker backend for this parameter bundle (default: MOTModels.BOTSORT).

per_class bool

Whether to run tracking independently per class (default: False). Options: True, False. Setting True reduces cross-class ID switches but can create more tracks.

extra_kwargs dict[str, Any]

Additional kwargs merged into tracker construction arguments (default: {}). Use this for BoxMOT arguments not explicitly represented in dataclasses.

to_kwargs

to_kwargs() -> dict[str, Any]

Convert dataclass fields to keyword arguments for BoxMOT tracker creation.

Source code in src/dnt/track/tracker.py
189
190
191
192
193
194
195
def to_kwargs(self) -> dict[str, Any]:
    """Convert dataclass fields to keyword arguments for BoxMOT tracker creation."""
    kwargs = asdict(self)
    kwargs.pop("model", None)
    kwargs.pop("extra_kwargs", None)
    kwargs.update(self.extra_kwargs)
    return kwargs

to_dict

to_dict() -> dict[str, Any]

Return dataclass values as a serializable dictionary.

Source code in src/dnt/track/tracker.py
197
198
199
def to_dict(self) -> dict[str, Any]:
    """Return dataclass values as a serializable dictionary."""
    return self._yaml_safe(asdict(self))

from_dict classmethod

from_dict(data: dict[str, Any]) -> MOTBaseConfig

Build a parameter object from a dictionary.

Unknown keys are stored in extra_kwargs.

Source code in src/dnt/track/tracker.py
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "MOTBaseConfig":
    """Build a parameter object from a dictionary.

    Unknown keys are stored in `extra_kwargs`.
    """
    valid_fields = {f.name for f in fields(cls)}
    known = {k: v for k, v in data.items() if k in valid_fields}
    unknown = {k: v for k, v in data.items() if k not in valid_fields}

    if "model" in known and not isinstance(known["model"], MOTModels):
        known["model"] = MOTModels(str(known["model"]))

    params = cls(**known)
    if unknown:
        params.extra_kwargs.update(unknown)
    return params

export_yaml

export_yaml(yaml_file: str) -> None

Export parameters to a YAML file.

Source code in src/dnt/track/tracker.py
232
233
234
235
236
237
def export_yaml(self, yaml_file: str) -> None:
    """Export parameters to a YAML file."""
    out_path = Path(yaml_file)
    out_path.parent.mkdir(parents=True, exist_ok=True)
    with out_path.open("w", encoding="utf-8") as f:
        yaml.safe_dump(self.to_dict(), f, sort_keys=False)

import_yaml classmethod

import_yaml(yaml_file: str) -> MOTBaseConfig

Import parameters from a YAML file.

Source code in src/dnt/track/tracker.py
239
240
241
242
243
244
245
246
247
@classmethod
def import_yaml(cls, yaml_file: str) -> "MOTBaseConfig":
    """Import parameters from a YAML file."""
    with Path(yaml_file).open("r", encoding="utf-8") as f:
        data = yaml.safe_load(f) or {}
    if not isinstance(data, dict):
        msg = f"Invalid YAML content in {yaml_file}: expected a mapping."
        raise ValueError(msg)
    return cls.from_dict(data)

BoTSORTConfig dataclass

BoTSORTConfig(
    model: MOTModels = MOTModels.BOTSORT,
    per_class: bool = False,
    extra_kwargs: dict[str, Any] = dict(),
    reid_weights: ReIDWeights
    | str
    | None = ReIDWeights.OSNET_X1_0_MSMT17,
    track_high_thresh: float = 0.5,
    track_low_thresh: float = 0.1,
    new_track_thresh: float = 0.6,
    match_thresh: float = 0.8,
    track_buffer: int = 30,
    with_reid: bool = True,
    proximity_thresh: float = 0.5,
    appearance_thresh: float = 0.25,
)

Bases: MOTBaseConfig

BoTSORT-specific parameters.

Attributes:

Name Type Description
reid_weights ReIDWeights | str | None

Optional ReID weights path (default: "osnet_x1_0_msmt17.pt"). Options: None, file name (auto-resolved), or absolute path. Built-in downloadable options: 'resnet50_market1501.pt', 'resnet50_dukemtmcreid.pt', 'resnet50_msmt17.pt', 'resnet50_fc512_market1501.pt', 'resnet50_fc512_dukemtmcreid.pt', 'resnet50_fc512_msmt17.pt', 'mlfn_market1501.pt', 'mlfn_dukemtmcreid.pt', 'mlfn_msmt17.pt', 'hacnn_market1501.pt', 'hacnn_dukemtmcreid.pt', 'hacnn_msmt17.pt', 'mobilenetv2_x1_0_market1501.pt', 'mobilenetv2_x1_0_dukemtmcreid.pt', 'mobilenetv2_x1_0_msmt17.pt', 'mobilenetv2_x1_4_market1501.pt', 'mobilenetv2_x1_4_dukemtmcreid.pt', 'mobilenetv2_x1_4_msmt17.pt', 'osnet_x1_0_market1501.pt', 'osnet_x1_0_dukemtmcreid.pt', 'osnet_x1_0_msmt17.pt', 'osnet_x0_75_market1501.pt', 'osnet_x0_75_dukemtmcreid.pt', 'osnet_x0_75_msmt17.pt', 'osnet_x0_5_market1501.pt', 'osnet_x0_5_dukemtmcreid.pt', 'osnet_x0_5_msmt17.pt', 'osnet_x0_25_market1501.pt', 'osnet_x0_25_dukemtmcreid.pt', 'osnet_x0_25_msmt17.pt', 'osnet_ibn_x1_0_msmt17.pt', 'osnet_ain_x1_0_msmt17.pt', 'lmbn_n_duke.pt', 'lmbn_n_market.pt', 'lmbn_n_cuhk03_d.pt', 'clip_market1501.pt', 'clip_duke.pt', 'clip_veri.pt', 'clip_vehicleid.pt'. Suggestions: use "osnet_x1_0_msmt17.pt" for pedestrians or "clip_vehicleid.pt" / "clip_veri.pt" for vehicles.

track_high_thresh float

High score threshold for first association (default: 0.5). Increasing this is stricter and may reduce false matches but miss tracks.

track_low_thresh float

Lower score threshold for second association (default: 0.1). Increasing this keeps fewer low-confidence detections.

new_track_thresh float

Threshold to initialize new tracks (default: 0.6). Increasing this creates fewer new tracks and can reduce false positives.

match_thresh float

Matching threshold for association (default: 0.8). Increasing this makes association more permissive.

track_buffer int

Number of frames to keep lost tracks (default: 30). Increasing this preserves IDs longer through occlusion, but may cause stale tracks to survive longer.

with_reid bool

Whether to enable ReID-assisted association (default: True). Options: True, False. Disabling this speeds up tracking but may increase ID switches.

proximity_thresh float

Proximity threshold for ReID matching (default: 0.5). Increasing this requires stronger geometric overlap before ReID is used.

appearance_thresh float

Appearance similarity threshold for ReID matching (default: 0.25). Increasing this requires closer appearance match and is more conservative.

to_kwargs

to_kwargs() -> dict[str, Any]

Convert dataclass fields to keyword arguments for BoxMOT tracker creation.

Source code in src/dnt/track/tracker.py
189
190
191
192
193
194
195
def to_kwargs(self) -> dict[str, Any]:
    """Convert dataclass fields to keyword arguments for BoxMOT tracker creation."""
    kwargs = asdict(self)
    kwargs.pop("model", None)
    kwargs.pop("extra_kwargs", None)
    kwargs.update(self.extra_kwargs)
    return kwargs

to_dict

to_dict() -> dict[str, Any]

Return dataclass values as a serializable dictionary.

Source code in src/dnt/track/tracker.py
197
198
199
def to_dict(self) -> dict[str, Any]:
    """Return dataclass values as a serializable dictionary."""
    return self._yaml_safe(asdict(self))

from_dict classmethod

from_dict(data: dict[str, Any]) -> MOTBaseConfig

Build a parameter object from a dictionary.

Unknown keys are stored in extra_kwargs.

Source code in src/dnt/track/tracker.py
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "MOTBaseConfig":
    """Build a parameter object from a dictionary.

    Unknown keys are stored in `extra_kwargs`.
    """
    valid_fields = {f.name for f in fields(cls)}
    known = {k: v for k, v in data.items() if k in valid_fields}
    unknown = {k: v for k, v in data.items() if k not in valid_fields}

    if "model" in known and not isinstance(known["model"], MOTModels):
        known["model"] = MOTModels(str(known["model"]))

    params = cls(**known)
    if unknown:
        params.extra_kwargs.update(unknown)
    return params

export_yaml

export_yaml(yaml_file: str) -> None

Export parameters to a YAML file.

Source code in src/dnt/track/tracker.py
232
233
234
235
236
237
def export_yaml(self, yaml_file: str) -> None:
    """Export parameters to a YAML file."""
    out_path = Path(yaml_file)
    out_path.parent.mkdir(parents=True, exist_ok=True)
    with out_path.open("w", encoding="utf-8") as f:
        yaml.safe_dump(self.to_dict(), f, sort_keys=False)

import_yaml classmethod

import_yaml(yaml_file: str) -> MOTBaseConfig

Import parameters from a YAML file.

Source code in src/dnt/track/tracker.py
239
240
241
242
243
244
245
246
247
@classmethod
def import_yaml(cls, yaml_file: str) -> "MOTBaseConfig":
    """Import parameters from a YAML file."""
    with Path(yaml_file).open("r", encoding="utf-8") as f:
        data = yaml.safe_load(f) or {}
    if not isinstance(data, dict):
        msg = f"Invalid YAML content in {yaml_file}: expected a mapping."
        raise ValueError(msg)
    return cls.from_dict(data)

BoostTrackConfig dataclass

BoostTrackConfig(
    model: MOTModels = MOTModels.BOOSTTRACK,
    per_class: bool = False,
    extra_kwargs: dict[str, Any] = dict(),
    reid_weights: ReIDWeights
    | str
    | None = ReIDWeights.OSNET_X1_0_MSMT17,
    det_thresh: float = 0.3,
    max_age: int = 30,
    min_hits: int = 3,
    iou_threshold: float = 0.3,
    asso_func: str = "iou",
)

Bases: MOTBaseConfig

BoostTrack-specific parameters.

Attributes:

Name Type Description
reid_weights ReIDWeights | str | None

Optional ReID weights path (default: "osnet_x1_0_msmt17.pt"). Options: same built-in .pt names listed in BoTSORTParams.reid_weights.

det_thresh float

Detection confidence threshold (default: 0.3). Increasing this keeps only higher-confidence detections.

max_age int

Maximum age of unmatched tracks (default: 30). Increasing this keeps tracks alive longer when unmatched.

min_hits int

Minimum hits before track confirmation (default: 3). Increasing this delays confirmation and reduces short noisy tracks.

iou_threshold float

IoU threshold for association (default: 0.3). Increasing this demands tighter overlap to match detections.

asso_func str

Association function name (default: "iou"). Typical options: "iou", "giou", "diou", "ciou", "centroid".

to_kwargs

to_kwargs() -> dict[str, Any]

Convert dataclass fields to keyword arguments for BoxMOT tracker creation.

Source code in src/dnt/track/tracker.py
189
190
191
192
193
194
195
def to_kwargs(self) -> dict[str, Any]:
    """Convert dataclass fields to keyword arguments for BoxMOT tracker creation."""
    kwargs = asdict(self)
    kwargs.pop("model", None)
    kwargs.pop("extra_kwargs", None)
    kwargs.update(self.extra_kwargs)
    return kwargs

to_dict

to_dict() -> dict[str, Any]

Return dataclass values as a serializable dictionary.

Source code in src/dnt/track/tracker.py
197
198
199
def to_dict(self) -> dict[str, Any]:
    """Return dataclass values as a serializable dictionary."""
    return self._yaml_safe(asdict(self))

from_dict classmethod

from_dict(data: dict[str, Any]) -> MOTBaseConfig

Build a parameter object from a dictionary.

Unknown keys are stored in extra_kwargs.

Source code in src/dnt/track/tracker.py
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "MOTBaseConfig":
    """Build a parameter object from a dictionary.

    Unknown keys are stored in `extra_kwargs`.
    """
    valid_fields = {f.name for f in fields(cls)}
    known = {k: v for k, v in data.items() if k in valid_fields}
    unknown = {k: v for k, v in data.items() if k not in valid_fields}

    if "model" in known and not isinstance(known["model"], MOTModels):
        known["model"] = MOTModels(str(known["model"]))

    params = cls(**known)
    if unknown:
        params.extra_kwargs.update(unknown)
    return params

export_yaml

export_yaml(yaml_file: str) -> None

Export parameters to a YAML file.

Source code in src/dnt/track/tracker.py
232
233
234
235
236
237
def export_yaml(self, yaml_file: str) -> None:
    """Export parameters to a YAML file."""
    out_path = Path(yaml_file)
    out_path.parent.mkdir(parents=True, exist_ok=True)
    with out_path.open("w", encoding="utf-8") as f:
        yaml.safe_dump(self.to_dict(), f, sort_keys=False)

import_yaml classmethod

import_yaml(yaml_file: str) -> MOTBaseConfig

Import parameters from a YAML file.

Source code in src/dnt/track/tracker.py
239
240
241
242
243
244
245
246
247
@classmethod
def import_yaml(cls, yaml_file: str) -> "MOTBaseConfig":
    """Import parameters from a YAML file."""
    with Path(yaml_file).open("r", encoding="utf-8") as f:
        data = yaml.safe_load(f) or {}
    if not isinstance(data, dict):
        msg = f"Invalid YAML content in {yaml_file}: expected a mapping."
        raise ValueError(msg)
    return cls.from_dict(data)

ByteTrackConfig dataclass

ByteTrackConfig(
    model: MOTModels = MOTModels.BYTE_TRACK,
    per_class: bool = False,
    extra_kwargs: dict[str, Any] = dict(),
    track_thresh: float = 0.5,
    match_thresh: float = 0.8,
    track_buffer: int = 30,
    frame_rate: int = 30,
)

Bases: MOTBaseConfig

ByteTrack-specific parameters.

Attributes:

Name Type Description
track_thresh float

Detection confidence threshold (default: 0.5). Increasing this filters more weak detections.

match_thresh float

Threshold for matching detections to tracks (default: 0.8). Increasing this generally allows looser matching.

track_buffer int

Number of frames to keep lost tracks (default: 30). Increasing this keeps unmatched tracks longer.

frame_rate int

Source video frame rate used by the tracker (default: 30). Set this close to real FPS for best temporal behavior.

to_kwargs

to_kwargs() -> dict[str, Any]

Convert dataclass fields to keyword arguments for BoxMOT tracker creation.

Source code in src/dnt/track/tracker.py
189
190
191
192
193
194
195
def to_kwargs(self) -> dict[str, Any]:
    """Convert dataclass fields to keyword arguments for BoxMOT tracker creation."""
    kwargs = asdict(self)
    kwargs.pop("model", None)
    kwargs.pop("extra_kwargs", None)
    kwargs.update(self.extra_kwargs)
    return kwargs

to_dict

to_dict() -> dict[str, Any]

Return dataclass values as a serializable dictionary.

Source code in src/dnt/track/tracker.py
197
198
199
def to_dict(self) -> dict[str, Any]:
    """Return dataclass values as a serializable dictionary."""
    return self._yaml_safe(asdict(self))

from_dict classmethod

from_dict(data: dict[str, Any]) -> MOTBaseConfig

Build a parameter object from a dictionary.

Unknown keys are stored in extra_kwargs.

Source code in src/dnt/track/tracker.py
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "MOTBaseConfig":
    """Build a parameter object from a dictionary.

    Unknown keys are stored in `extra_kwargs`.
    """
    valid_fields = {f.name for f in fields(cls)}
    known = {k: v for k, v in data.items() if k in valid_fields}
    unknown = {k: v for k, v in data.items() if k not in valid_fields}

    if "model" in known and not isinstance(known["model"], MOTModels):
        known["model"] = MOTModels(str(known["model"]))

    params = cls(**known)
    if unknown:
        params.extra_kwargs.update(unknown)
    return params

export_yaml

export_yaml(yaml_file: str) -> None

Export parameters to a YAML file.

Source code in src/dnt/track/tracker.py
232
233
234
235
236
237
def export_yaml(self, yaml_file: str) -> None:
    """Export parameters to a YAML file."""
    out_path = Path(yaml_file)
    out_path.parent.mkdir(parents=True, exist_ok=True)
    with out_path.open("w", encoding="utf-8") as f:
        yaml.safe_dump(self.to_dict(), f, sort_keys=False)

import_yaml classmethod

import_yaml(yaml_file: str) -> MOTBaseConfig

Import parameters from a YAML file.

Source code in src/dnt/track/tracker.py
239
240
241
242
243
244
245
246
247
@classmethod
def import_yaml(cls, yaml_file: str) -> "MOTBaseConfig":
    """Import parameters from a YAML file."""
    with Path(yaml_file).open("r", encoding="utf-8") as f:
        data = yaml.safe_load(f) or {}
    if not isinstance(data, dict):
        msg = f"Invalid YAML content in {yaml_file}: expected a mapping."
        raise ValueError(msg)
    return cls.from_dict(data)

OCSORTConfig dataclass

OCSORTConfig(
    model: MOTModels = MOTModels.OCSORT,
    per_class: bool = False,
    extra_kwargs: dict[str, Any] = dict(),
    det_thresh: float = 0.3,
    max_age: int = 30,
    min_hits: int = 3,
    iou_threshold: float = 0.3,
    asso_func: str = "iou",
    delta_t: int = 3,
    inertia: float = 0.2,
)

Bases: MOTBaseConfig

OCSORT-specific parameters.

Attributes:

Name Type Description
det_thresh float

Detection confidence threshold (default: 0.3). Increasing this reduces low-confidence detections.

max_age int

Maximum age of unmatched tracks (default: 30). Increasing this keeps tracks alive through longer gaps.

min_hits int

Minimum hits before track confirmation (default: 3). Increasing this reduces short-lived false tracks.

iou_threshold float

IoU threshold for association (default: 0.3). Increasing this makes matching stricter.

asso_func str

Association function name (default: "iou"). Typical options: "iou", "giou", "diou", "ciou", "centroid".

delta_t int

Time gap used by motion compensation (default: 3). Increasing this smooths longer motion history, but may lag quick turns.

inertia float

Motion inertia weight (default: 0.2). Increasing this trusts previous velocity more.

to_kwargs

to_kwargs() -> dict[str, Any]

Convert dataclass fields to keyword arguments for BoxMOT tracker creation.

Source code in src/dnt/track/tracker.py
189
190
191
192
193
194
195
def to_kwargs(self) -> dict[str, Any]:
    """Convert dataclass fields to keyword arguments for BoxMOT tracker creation."""
    kwargs = asdict(self)
    kwargs.pop("model", None)
    kwargs.pop("extra_kwargs", None)
    kwargs.update(self.extra_kwargs)
    return kwargs

to_dict

to_dict() -> dict[str, Any]

Return dataclass values as a serializable dictionary.

Source code in src/dnt/track/tracker.py
197
198
199
def to_dict(self) -> dict[str, Any]:
    """Return dataclass values as a serializable dictionary."""
    return self._yaml_safe(asdict(self))

from_dict classmethod

from_dict(data: dict[str, Any]) -> MOTBaseConfig

Build a parameter object from a dictionary.

Unknown keys are stored in extra_kwargs.

Source code in src/dnt/track/tracker.py
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "MOTBaseConfig":
    """Build a parameter object from a dictionary.

    Unknown keys are stored in `extra_kwargs`.
    """
    valid_fields = {f.name for f in fields(cls)}
    known = {k: v for k, v in data.items() if k in valid_fields}
    unknown = {k: v for k, v in data.items() if k not in valid_fields}

    if "model" in known and not isinstance(known["model"], MOTModels):
        known["model"] = MOTModels(str(known["model"]))

    params = cls(**known)
    if unknown:
        params.extra_kwargs.update(unknown)
    return params

export_yaml

export_yaml(yaml_file: str) -> None

Export parameters to a YAML file.

Source code in src/dnt/track/tracker.py
232
233
234
235
236
237
def export_yaml(self, yaml_file: str) -> None:
    """Export parameters to a YAML file."""
    out_path = Path(yaml_file)
    out_path.parent.mkdir(parents=True, exist_ok=True)
    with out_path.open("w", encoding="utf-8") as f:
        yaml.safe_dump(self.to_dict(), f, sort_keys=False)

import_yaml classmethod

import_yaml(yaml_file: str) -> MOTBaseConfig

Import parameters from a YAML file.

Source code in src/dnt/track/tracker.py
239
240
241
242
243
244
245
246
247
@classmethod
def import_yaml(cls, yaml_file: str) -> "MOTBaseConfig":
    """Import parameters from a YAML file."""
    with Path(yaml_file).open("r", encoding="utf-8") as f:
        data = yaml.safe_load(f) or {}
    if not isinstance(data, dict):
        msg = f"Invalid YAML content in {yaml_file}: expected a mapping."
        raise ValueError(msg)
    return cls.from_dict(data)

StrongSORTConfig dataclass

StrongSORTConfig(
    model: MOTModels = MOTModels.STRONGSORT,
    per_class: bool = False,
    extra_kwargs: dict[str, Any] = dict(),
    reid_weights: ReIDWeights
    | str
    | None = ReIDWeights.OSNET_X1_0_MSMT17,
    max_dist: float = 0.2,
    max_iou_dist: float = 0.7,
    max_age: int = 70,
    n_init: int = 3,
    nn_budget: int = 100,
    ema_alpha: float = 0.9,
    mc_lambda: float = 0.995,
)

Bases: MOTBaseConfig

StrongSORT-specific parameters.

Attributes:

Name Type Description
reid_weights ReIDWeights | str | None

Optional ReID weights path (default: "osnet_x1_0_msmt17.pt"). Options: same built-in .pt names listed in BoTSORTParams.reid_weights.

max_dist float

Maximum cosine distance for appearance matching (default: 0.2). Increasing this allows less similar appearance matches.

max_iou_dist float

Maximum IoU distance for geometric matching (default: 0.7). Increasing this allows looser geometric matches.

max_age int

Maximum age of unmatched tracks (default: 70). Increasing this retains tracks through longer occlusions.

n_init int

Minimum hits before track confirmation (default: 3). Increasing this delays confirmation and reduces unstable IDs.

nn_budget int

Maximum size of appearance feature gallery (default: 100). Increasing this improves long-term matching memory at higher memory cost.

ema_alpha float

EMA factor for appearance embeddings (default: 0.9). Increasing this smooths features more and reduces noise.

mc_lambda float

Motion compensation blending factor (default: 0.995). Increasing this gives more weight to motion compensation.

to_kwargs

to_kwargs() -> dict[str, Any]

Convert dataclass fields to keyword arguments for BoxMOT tracker creation.

Source code in src/dnt/track/tracker.py
189
190
191
192
193
194
195
def to_kwargs(self) -> dict[str, Any]:
    """Convert dataclass fields to keyword arguments for BoxMOT tracker creation."""
    kwargs = asdict(self)
    kwargs.pop("model", None)
    kwargs.pop("extra_kwargs", None)
    kwargs.update(self.extra_kwargs)
    return kwargs

to_dict

to_dict() -> dict[str, Any]

Return dataclass values as a serializable dictionary.

Source code in src/dnt/track/tracker.py
197
198
199
def to_dict(self) -> dict[str, Any]:
    """Return dataclass values as a serializable dictionary."""
    return self._yaml_safe(asdict(self))

from_dict classmethod

from_dict(data: dict[str, Any]) -> MOTBaseConfig

Build a parameter object from a dictionary.

Unknown keys are stored in extra_kwargs.

Source code in src/dnt/track/tracker.py
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "MOTBaseConfig":
    """Build a parameter object from a dictionary.

    Unknown keys are stored in `extra_kwargs`.
    """
    valid_fields = {f.name for f in fields(cls)}
    known = {k: v for k, v in data.items() if k in valid_fields}
    unknown = {k: v for k, v in data.items() if k not in valid_fields}

    if "model" in known and not isinstance(known["model"], MOTModels):
        known["model"] = MOTModels(str(known["model"]))

    params = cls(**known)
    if unknown:
        params.extra_kwargs.update(unknown)
    return params

export_yaml

export_yaml(yaml_file: str) -> None

Export parameters to a YAML file.

Source code in src/dnt/track/tracker.py
232
233
234
235
236
237
def export_yaml(self, yaml_file: str) -> None:
    """Export parameters to a YAML file."""
    out_path = Path(yaml_file)
    out_path.parent.mkdir(parents=True, exist_ok=True)
    with out_path.open("w", encoding="utf-8") as f:
        yaml.safe_dump(self.to_dict(), f, sort_keys=False)

import_yaml classmethod

import_yaml(yaml_file: str) -> MOTBaseConfig

Import parameters from a YAML file.

Source code in src/dnt/track/tracker.py
239
240
241
242
243
244
245
246
247
@classmethod
def import_yaml(cls, yaml_file: str) -> "MOTBaseConfig":
    """Import parameters from a YAML file."""
    with Path(yaml_file).open("r", encoding="utf-8") as f:
        data = yaml.safe_load(f) or {}
    if not isinstance(data, dict):
        msg = f"Invalid YAML content in {yaml_file}: expected a mapping."
        raise ValueError(msg)
    return cls.from_dict(data)

DeepOCSORTConfig dataclass

DeepOCSORTConfig(
    model: MOTModels = MOTModels.DEEPOCSORT,
    per_class: bool = False,
    extra_kwargs: dict[str, Any] = dict(),
    reid_weights: ReIDWeights
    | str
    | None = ReIDWeights.OSNET_X1_0_MSMT17,
    det_thresh: float = 0.3,
    max_age: int = 30,
    min_hits: int = 3,
    iou_threshold: float = 0.3,
    asso_func: str = "iou",
    delta_t: int = 3,
    inertia: float = 0.2,
)

Bases: MOTBaseConfig

DeepOCSORT-specific parameters.

Attributes:

Name Type Description
reid_weights ReIDWeights | str | None

Optional ReID weights path (default: "osnet_x1_0_msmt17.pt"). Options: same built-in .pt names listed in BoTSORTParams.reid_weights.

det_thresh float

Detection confidence threshold (default: 0.3). Increasing this keeps fewer low-confidence detections.

max_age int

Maximum age of unmatched tracks (default: 30). Increasing this keeps unmatched tracks alive longer.

min_hits int

Minimum hits before track confirmation (default: 3). Increasing this delays track confirmation.

iou_threshold float

IoU threshold for association (default: 0.3). Increasing this requires tighter overlap.

asso_func str

Association function name (default: "iou"). Typical options: "iou", "giou", "diou", "ciou", "centroid".

delta_t int

Time gap used by motion compensation (default: 3). Increasing this smooths over longer temporal windows.

inertia float

Motion inertia weight (default: 0.2). Increasing this emphasizes velocity continuity.

to_kwargs

to_kwargs() -> dict[str, Any]

Convert dataclass fields to keyword arguments for BoxMOT tracker creation.

Source code in src/dnt/track/tracker.py
189
190
191
192
193
194
195
def to_kwargs(self) -> dict[str, Any]:
    """Convert dataclass fields to keyword arguments for BoxMOT tracker creation."""
    kwargs = asdict(self)
    kwargs.pop("model", None)
    kwargs.pop("extra_kwargs", None)
    kwargs.update(self.extra_kwargs)
    return kwargs

to_dict

to_dict() -> dict[str, Any]

Return dataclass values as a serializable dictionary.

Source code in src/dnt/track/tracker.py
197
198
199
def to_dict(self) -> dict[str, Any]:
    """Return dataclass values as a serializable dictionary."""
    return self._yaml_safe(asdict(self))

from_dict classmethod

from_dict(data: dict[str, Any]) -> MOTBaseConfig

Build a parameter object from a dictionary.

Unknown keys are stored in extra_kwargs.

Source code in src/dnt/track/tracker.py
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "MOTBaseConfig":
    """Build a parameter object from a dictionary.

    Unknown keys are stored in `extra_kwargs`.
    """
    valid_fields = {f.name for f in fields(cls)}
    known = {k: v for k, v in data.items() if k in valid_fields}
    unknown = {k: v for k, v in data.items() if k not in valid_fields}

    if "model" in known and not isinstance(known["model"], MOTModels):
        known["model"] = MOTModels(str(known["model"]))

    params = cls(**known)
    if unknown:
        params.extra_kwargs.update(unknown)
    return params

export_yaml

export_yaml(yaml_file: str) -> None

Export parameters to a YAML file.

Source code in src/dnt/track/tracker.py
232
233
234
235
236
237
def export_yaml(self, yaml_file: str) -> None:
    """Export parameters to a YAML file."""
    out_path = Path(yaml_file)
    out_path.parent.mkdir(parents=True, exist_ok=True)
    with out_path.open("w", encoding="utf-8") as f:
        yaml.safe_dump(self.to_dict(), f, sort_keys=False)

import_yaml classmethod

import_yaml(yaml_file: str) -> MOTBaseConfig

Import parameters from a YAML file.

Source code in src/dnt/track/tracker.py
239
240
241
242
243
244
245
246
247
@classmethod
def import_yaml(cls, yaml_file: str) -> "MOTBaseConfig":
    """Import parameters from a YAML file."""
    with Path(yaml_file).open("r", encoding="utf-8") as f:
        data = yaml.safe_load(f) or {}
    if not isinstance(data, dict):
        msg = f"Invalid YAML content in {yaml_file}: expected a mapping."
        raise ValueError(msg)
    return cls.from_dict(data)

HybridSORTConfig dataclass

HybridSORTConfig(
    model: MOTModels = MOTModels.HYBRIDSORT,
    per_class: bool = False,
    extra_kwargs: dict[str, Any] = dict(),
    reid_weights: ReIDWeights
    | str
    | None = ReIDWeights.OSNET_X1_0_MSMT17,
    det_thresh: float = 0.3,
    max_age: int = 30,
    min_hits: int = 3,
    iou_threshold: float = 0.3,
    asso_func: str = "iou",
)

Bases: MOTBaseConfig

HybridSORT-specific parameters.

Attributes:

Name Type Description
reid_weights ReIDWeights | str | None

Optional ReID weights path (default: "osnet_x1_0_msmt17.pt"). Options: same built-in .pt names listed in BoTSORTParams.reid_weights.

det_thresh float

Detection confidence threshold (default: 0.3). Increasing this reduces weak detections.

max_age int

Maximum age of unmatched tracks (default: 30). Increasing this keeps tracks longer during occlusion.

min_hits int

Minimum hits before track confirmation (default: 3). Increasing this reduces early noisy tracks.

iou_threshold float

IoU threshold for association (default: 0.3). Increasing this makes IoU matching stricter.

asso_func str

Association function name (default: "iou"). Typical options: "iou", "giou", "diou", "ciou", "centroid".

to_kwargs

to_kwargs() -> dict[str, Any]

Convert dataclass fields to keyword arguments for BoxMOT tracker creation.

Source code in src/dnt/track/tracker.py
189
190
191
192
193
194
195
def to_kwargs(self) -> dict[str, Any]:
    """Convert dataclass fields to keyword arguments for BoxMOT tracker creation."""
    kwargs = asdict(self)
    kwargs.pop("model", None)
    kwargs.pop("extra_kwargs", None)
    kwargs.update(self.extra_kwargs)
    return kwargs

to_dict

to_dict() -> dict[str, Any]

Return dataclass values as a serializable dictionary.

Source code in src/dnt/track/tracker.py
197
198
199
def to_dict(self) -> dict[str, Any]:
    """Return dataclass values as a serializable dictionary."""
    return self._yaml_safe(asdict(self))

from_dict classmethod

from_dict(data: dict[str, Any]) -> MOTBaseConfig

Build a parameter object from a dictionary.

Unknown keys are stored in extra_kwargs.

Source code in src/dnt/track/tracker.py
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "MOTBaseConfig":
    """Build a parameter object from a dictionary.

    Unknown keys are stored in `extra_kwargs`.
    """
    valid_fields = {f.name for f in fields(cls)}
    known = {k: v for k, v in data.items() if k in valid_fields}
    unknown = {k: v for k, v in data.items() if k not in valid_fields}

    if "model" in known and not isinstance(known["model"], MOTModels):
        known["model"] = MOTModels(str(known["model"]))

    params = cls(**known)
    if unknown:
        params.extra_kwargs.update(unknown)
    return params

export_yaml

export_yaml(yaml_file: str) -> None

Export parameters to a YAML file.

Source code in src/dnt/track/tracker.py
232
233
234
235
236
237
def export_yaml(self, yaml_file: str) -> None:
    """Export parameters to a YAML file."""
    out_path = Path(yaml_file)
    out_path.parent.mkdir(parents=True, exist_ok=True)
    with out_path.open("w", encoding="utf-8") as f:
        yaml.safe_dump(self.to_dict(), f, sort_keys=False)

import_yaml classmethod

import_yaml(yaml_file: str) -> MOTBaseConfig

Import parameters from a YAML file.

Source code in src/dnt/track/tracker.py
239
240
241
242
243
244
245
246
247
@classmethod
def import_yaml(cls, yaml_file: str) -> "MOTBaseConfig":
    """Import parameters from a YAML file."""
    with Path(yaml_file).open("r", encoding="utf-8") as f:
        data = yaml.safe_load(f) or {}
    if not isinstance(data, dict):
        msg = f"Invalid YAML content in {yaml_file}: expected a mapping."
        raise ValueError(msg)
    return cls.from_dict(data)

SFSORTConfig dataclass

SFSORTConfig(
    model: MOTModels = MOTModels.SFSORT,
    per_class: bool = False,
    extra_kwargs: dict[str, Any] = dict(),
    det_thresh: float = 0.3,
    max_age: int = 30,
    min_hits: int = 3,
    iou_threshold: float = 0.3,
    asso_func: str = "iou",
)

Bases: MOTBaseConfig

SFSORT-specific parameters.

Attributes:

Name Type Description
det_thresh float

Detection confidence threshold (default: 0.3). Increasing this reduces weak detections.

max_age int

Maximum age of unmatched tracks (default: 30). Increasing this keeps tracks longer through brief misses.

min_hits int

Minimum hits before track confirmation (default: 3). Increasing this reduces short-lived noisy tracks.

iou_threshold float

IoU threshold for association (default: 0.3). Increasing this requires tighter overlap for matching.

asso_func str

Association function name (default: "iou"). Typical options: "iou", "giou", "diou", "ciou", "centroid".

to_kwargs

to_kwargs() -> dict[str, Any]

Convert dataclass fields to keyword arguments for BoxMOT tracker creation.

Source code in src/dnt/track/tracker.py
189
190
191
192
193
194
195
def to_kwargs(self) -> dict[str, Any]:
    """Convert dataclass fields to keyword arguments for BoxMOT tracker creation."""
    kwargs = asdict(self)
    kwargs.pop("model", None)
    kwargs.pop("extra_kwargs", None)
    kwargs.update(self.extra_kwargs)
    return kwargs

to_dict

to_dict() -> dict[str, Any]

Return dataclass values as a serializable dictionary.

Source code in src/dnt/track/tracker.py
197
198
199
def to_dict(self) -> dict[str, Any]:
    """Return dataclass values as a serializable dictionary."""
    return self._yaml_safe(asdict(self))

from_dict classmethod

from_dict(data: dict[str, Any]) -> MOTBaseConfig

Build a parameter object from a dictionary.

Unknown keys are stored in extra_kwargs.

Source code in src/dnt/track/tracker.py
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
@classmethod
def from_dict(cls, data: dict[str, Any]) -> "MOTBaseConfig":
    """Build a parameter object from a dictionary.

    Unknown keys are stored in `extra_kwargs`.
    """
    valid_fields = {f.name for f in fields(cls)}
    known = {k: v for k, v in data.items() if k in valid_fields}
    unknown = {k: v for k, v in data.items() if k not in valid_fields}

    if "model" in known and not isinstance(known["model"], MOTModels):
        known["model"] = MOTModels(str(known["model"]))

    params = cls(**known)
    if unknown:
        params.extra_kwargs.update(unknown)
    return params

export_yaml

export_yaml(yaml_file: str) -> None

Export parameters to a YAML file.

Source code in src/dnt/track/tracker.py
232
233
234
235
236
237
def export_yaml(self, yaml_file: str) -> None:
    """Export parameters to a YAML file."""
    out_path = Path(yaml_file)
    out_path.parent.mkdir(parents=True, exist_ok=True)
    with out_path.open("w", encoding="utf-8") as f:
        yaml.safe_dump(self.to_dict(), f, sort_keys=False)

import_yaml classmethod

import_yaml(yaml_file: str) -> MOTBaseConfig

Import parameters from a YAML file.

Source code in src/dnt/track/tracker.py
239
240
241
242
243
244
245
246
247
@classmethod
def import_yaml(cls, yaml_file: str) -> "MOTBaseConfig":
    """Import parameters from a YAML file."""
    with Path(yaml_file).open("r", encoding="utf-8") as f:
        data = yaml.safe_load(f) or {}
    if not isinstance(data, dict):
        msg = f"Invalid YAML content in {yaml_file}: expected a mapping."
        raise ValueError(msg)
    return cls.from_dict(data)

Tracker

Tracker(
    config: BoxMOTModelParams | None = None,
    config_yaml: str | None = None,
    device: str = "auto",
    half: bool = False,
    output_score_cls: bool = True,
    boxmot_verbose: bool = False,
)

Unified interface for BoxMOT tracking and track post-processing.

This class runs BoxMOT tracking given a detection file and source video. It also provides post-processing utilities to infill missing frames, split tracks by large gaps, and drop short tracks.

Attributes:

Name Type Description
TRACK_FIELDS list[str]

Standard output columns for tracking and post-processing utilities (default: class constant).

device str

Device string used by deep trackers (default: "auto"). Options: "auto", "cpu", "cuda", "mps".

half bool

Whether half precision is enabled for deep trackers (default: False). Options: True, False. Enabling can improve speed on supported GPUs.

boxmot_model MOTModels

Selected BoxMOT tracker backend (default: MOTModels.BOTSORT). Options: MOTModels.BOTSORT, MOTModels.BOOSTTRACK, MOTModels.BYTE_TRACK, MOTModels.OCSORT, MOTModels.STRONGSORT, MOTModels.DEEPOCSORT, MOTModels.HYBRIDSORT, MOTModels.SFSORT.

boxmot_config BoxMOTModelConfig

Configuration dataclass instance for BoxMOT tracker creation (default: model-specific defaults).

boxmot_verbose bool

If False, suppress BoxMOT INFO/SUCCESS logging output.

output_score_cls bool

Whether to include tracker score and cls values in outputs. If False, both fields are exported as -1 to keep file schema stable.

REID_WEIGHTS_DIR Path

Directory where relative ReID weights are resolved and stored.

DEFAULT_REID_WEIGHT str

Fallback ReID weight file name used when a model expects ReID and no weight is explicitly set.

Initialize the tracker.

Parameters:

Name Type Description Default
config BoxMOTModelConfig

Configuration bundle for BoxMOT tracker creation. Tracker backend is selected from config.model.

None
config_yaml str

YAML file containing model-aware config. When provided, values loaded from YAML override config input.

None
device str

Device string used by deep trackers (default: "auto", "cpu", "cuda", "mps").

'auto'
half bool

Whether half precision is enabled for deep trackers (default: False).

False
output_score_cls bool

If True, output tracker confidence and class values in score and cls columns. If False, export -1 for both fields.

True
boxmot_verbose bool

If False, suppress BoxMOT INFO/SUCCESS logging output.

False
Source code in src/dnt/track/tracker.py
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
def __init__(
    self,
    config: BoxMOTModelParams | None = None,
    config_yaml: str | None = None,
    device: str = "auto",
    half: bool = False,
    output_score_cls: bool = True,
    boxmot_verbose: bool = False,
) -> None:
    """Initialize the tracker.

    Parameters
    ----------
    config : BoxMOTModelConfig, optional
        Configuration bundle for BoxMOT tracker creation. Tracker backend
        is selected from `config.model`.
    config_yaml : str, optional
        YAML file containing model-aware config. When provided,
        values loaded from YAML override `config` input.
    device : str, optional
        Device string used by deep trackers (default: `"auto"`, "cpu", "cuda", "mps").
    half : bool, optional
        Whether half precision is enabled for deep trackers (default: `False`).
    output_score_cls : bool, optional
        If True, output tracker confidence and class values in `score` and
        `cls` columns. If False, export `-1` for both fields.
    boxmot_verbose : bool, optional
        If False, suppress BoxMOT INFO/SUCCESS logging output.

    """
    self.device = device
    self.half = half
    self.boxmot_verbose = boxmot_verbose
    self.output_score_cls = output_score_cls
    yaml_path = config_yaml
    resolved_config = config or config
    self.model_config_yaml = yaml_path

    if yaml_path:
        resolved_config = self.import_config_from_yaml(yaml_path)

    if resolved_config is None:
        resolved_config = self._default_boxmot_config()

    self.boxmot_model = resolved_config.model
    self.boxmot_config = resolved_config

track

track(
    det_file: str,
    out_file: str,
    video_file: str | None = None,
    show: bool = False,
    video_index: int | None = None,
    video_tot: int | None = None,
    message: str | None = None,
) -> pd.DataFrame

Run tracking on a single detection file using BoxMOT.

Parameters:

Name Type Description Default
det_file str

Path to detection file in DNT detection format (frame, -, x, y, width, height, confidence, class_id).

required
out_file str

Path to write tracking results. If empty string, results are not saved.

required
video_file str

Path to source video file. Required for BoxMOT tracker.

None
show bool

If True (default: False), display live tracking preview with bounding boxes and track IDs. Press 's' to toggle preview, 'ESC' to hide, 'q' to stop tracking early.

False
video_index int

Index of current video in batch (for progress bar display).

None
video_tot int

Total number of videos in batch (for complete progress context).

None
message str | None

Optional progress text shown in the progress bar. If None, the video stem is used (default: None).

None

Returns:

Type Description
DataFrame

Tracking results with columns: frame, track, x, y, w, h, score, cls, r3, r4 Each row represents one detected object per frame.

Raises:

Type Description
FileNotFoundError

If det_file or video_file does not exist.

ValueError

If video_file is None.

Notes

The tracker processes detections frame-by-frame, maintaining track IDs across frames. Detection coordinates are converted from (x1, y1, x2, y2) to (x, y, width, height) format for BoxMOT.

Track IDs are persistent across frame sequences and reused if tracks are lost and then re-acquired within track_buffer frames.

Source code in src/dnt/track/tracker.py
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
def track(
    self,
    det_file: str,
    out_file: str,
    video_file: str | None = None,
    show: bool = False,
    video_index: int | None = None,
    video_tot: int | None = None,
    message: str | None = None,
) -> pd.DataFrame:
    """Run tracking on a single detection file using BoxMOT.

    Parameters
    ----------
    det_file : str
        Path to detection file in DNT detection format
        (frame, -, x, y, width, height, confidence, class_id).
    out_file : str
        Path to write tracking results. If empty string, results are not saved.
    video_file : str, optional
        Path to source video file. Required for BoxMOT tracker.
    show : bool, optional
        If True (default: False), display live tracking preview with bounding
        boxes and track IDs. Press 's' to toggle preview, 'ESC' to hide,
        'q' to stop tracking early.
    video_index : int, optional
        Index of current video in batch (for progress bar display).
    video_tot : int, optional
        Total number of videos in batch (for complete progress context).
    message : str | None, optional
        Optional progress text shown in the progress bar. If None, the
        video stem is used (default: None).

    Returns
    -------
    pd.DataFrame
        Tracking results with columns: frame, track, x, y, w, h, score, cls, r3, r4
        Each row represents one detected object per frame.

    Raises
    ------
    FileNotFoundError
        If det_file or video_file does not exist.
    ValueError
        If video_file is None.

    Notes
    -----
    The tracker processes detections frame-by-frame, maintaining track IDs
    across frames. Detection coordinates are converted from (x1, y1, x2, y2)
    to (x, y, width, height) format for BoxMOT.

    Track IDs are persistent across frame sequences and reused if tracks
    are lost and then re-acquired within track_buffer frames.

    """
    if not Path(det_file).exists():
        msg = f"Detection file not found: {det_file}"
        raise FileNotFoundError(msg)

    if video_file is None:
        msg = "Video file required for BoxMOT tracking but not provided."
        raise ValueError(msg)
    if not Path(video_file).exists():
        msg = f"Video file not found: {video_file}"
        raise FileNotFoundError(msg)

    return self._track_boxmot(
        video_file=video_file,
        det_file=det_file,
        out_file=out_file,
        show=show,
        video_index=video_index,
        video_tot=video_tot,
        message=message,
    )

track_batch

track_batch(
    det_files: list[str] | None = None,
    video_files: list[str] | None = None,
    output_path: str | None = None,
    is_overwrite: bool = False,
    is_report: bool = True,
    message: str | None = None,
) -> list[str]

Run tracking on multiple detection files sequentially.

Parameters:

Name Type Description Default
det_files list[str] | None

List of detection file paths. Each file should contain frame-level detections in CSV format. If None (default), returns empty list.

None
video_files list[str] | None

List of corresponding source video file paths for each detection file. Length should match det_files. Required for BoxMOT tracking.

None
output_path str | None

Directory to save tracking results. Track files are named based on input filename with '_track.txt' suffix. If None (default), tracking still runs but results are not persisted.

None
is_overwrite bool

If False (default), skip tracking for videos with existing output files.

False
is_report bool

If True (default), include skipped files in returned list.

True
message str | None

Optional progress text shown in each tracking progress bar. If None (default), each video's stem is used.

None

Returns:

Type Description
list[str]

List of output track file paths. Includes both newly created and existing files (if is_report=True). Empty list if det_files is None.

Notes

Processing is sequential (not parallel). Each detection file is tracked in order with progress display showing "Tracking X of Y".

Files matching between det_files and video_files by index position. If video_files is shorter than det_files, missing videos are left None and those detections are skipped.

Source code in src/dnt/track/tracker.py
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
def track_batch(
    self,
    det_files: list[str] | None = None,
    video_files: list[str] | None = None,
    output_path: str | None = None,
    is_overwrite: bool = False,
    is_report: bool = True,
    message: str | None = None,
) -> list[str]:
    """Run tracking on multiple detection files sequentially.

    Parameters
    ----------
    det_files : list[str] | None, optional
        List of detection file paths. Each file should contain frame-level
        detections in CSV format. If None (default), returns empty list.
    video_files : list[str] | None, optional
        List of corresponding source video file paths for each detection file.
        Length should match det_files. Required for BoxMOT tracking.
    output_path : str | None, optional
        Directory to save tracking results. Track files are named based on
        input filename with '_track.txt' suffix. If None (default),
        tracking still runs but results are not persisted.
    is_overwrite : bool, optional
        If False (default), skip tracking for videos with existing output files.
    is_report : bool, optional
        If True (default), include skipped files in returned list.
    message : str | None, optional
        Optional progress text shown in each tracking progress bar.
        If None (default), each video's stem is used.

    Returns
    -------
    list[str]
        List of output track file paths. Includes both newly created and
        existing files (if is_report=True). Empty list if det_files is None.

    Notes
    -----
    Processing is sequential (not parallel). Each detection file is tracked
    in order with progress display showing "Tracking X of Y".

    Files matching between det_files and video_files by index position.
    If video_files is shorter than det_files, missing videos are left None
    and those detections are skipped.

    """
    if det_files is None:
        return []

    results: list[str] = []
    total_videos = len(det_files)

    for idx, det_file in enumerate(det_files, start=1):
        base_filename = os.path.splitext(os.path.basename(det_file))[0].replace("_iou", "")

        track_file = None
        if output_path:
            os.makedirs(output_path, exist_ok=True)
            track_file = os.path.join(output_path, base_filename + "_track.txt")

        if track_file and not is_overwrite and os.path.exists(track_file):
            if is_report:
                results.append(track_file)
            continue

        # BoxMOT requires a matching source video.
        video_file = None
        if video_files is not None:  # noqa: SIM102
            if idx - 1 < len(video_files):
                video_file = video_files[idx - 1]

        # run tracking
        self.track(
            det_file=det_file,
            out_file=track_file if track_file else "",  # track() expects a path
            video_file=video_file,
            video_index=idx,
            video_tot=total_videos,
            message=message,
        )

        if track_file:
            results.append(track_file)

    return results

export_config_to_yaml staticmethod

export_config_to_yaml(
    yaml_file: str, config: BoxMOTModelParams
) -> None

Export model-aware BoxMOT config to a YAML file.

Source code in src/dnt/track/tracker.py
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
@staticmethod
def export_config_to_yaml(
    yaml_file: str,
    config: BoxMOTModelParams,
) -> None:
    """Export model-aware BoxMOT config to a YAML file."""
    out_path = Path(yaml_file)
    out_path.parent.mkdir(parents=True, exist_ok=True)
    with out_path.open("w", encoding="utf-8") as f:
        yaml.safe_dump(config.to_dict(), f, sort_keys=False)

import_config_from_yaml staticmethod

import_config_from_yaml(
    yaml_file: str,
) -> BoxMOTModelParams

Import model-aware BoxMOT config from a YAML file.

Source code in src/dnt/track/tracker.py
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
@staticmethod
def import_config_from_yaml(yaml_file: str) -> BoxMOTModelParams:
    """Import model-aware BoxMOT config from a YAML file."""
    with Path(yaml_file).open("r", encoding="utf-8") as f:
        data = yaml.safe_load(f) or {}
    if not isinstance(data, dict):
        msg = f"Invalid YAML content in {yaml_file}: expected a mapping."
        raise ValueError(msg)

    model = MOTModels(str(data.get("model", MOTModels.BOTSORT.value)))
    param_cls = Tracker._params_class_for_model(model)
    return param_cls.from_dict(data)

export_params_to_yaml staticmethod

export_params_to_yaml(
    yaml_file: str, params: BoxMOTModelParams
) -> None

Export model-aware BoxMOT params to a YAML file (backward-compatible wrapper).

Source code in src/dnt/track/tracker.py
1019
1020
1021
1022
1023
1024
1025
@staticmethod
def export_params_to_yaml(
    yaml_file: str,
    params: BoxMOTModelParams,
) -> None:
    """Export model-aware BoxMOT params to a YAML file (backward-compatible wrapper)."""
    Tracker.export_config_to_yaml(yaml_file=yaml_file, config=params)

import_params_from_yaml staticmethod

import_params_from_yaml(
    yaml_file: str,
) -> BoxMOTModelParams

Import model-aware BoxMOT params from a YAML file (backward-compatible wrapper).

Source code in src/dnt/track/tracker.py
1027
1028
1029
1030
@staticmethod
def import_params_from_yaml(yaml_file: str) -> BoxMOTModelParams:
    """Import model-aware BoxMOT params from a YAML file (backward-compatible wrapper)."""
    return Tracker.import_config_from_yaml(yaml_file=yaml_file)

export_current_config_to_yaml

export_current_config_to_yaml(yaml_file: str) -> None

Export this tracker's active model and config to YAML.

Source code in src/dnt/track/tracker.py
1032
1033
1034
1035
1036
1037
def export_current_config_to_yaml(self, yaml_file: str) -> None:
    """Export this tracker's active model and config to YAML."""
    self.export_config_to_yaml(
        yaml_file=yaml_file,
        config=self.boxmot_config,
    )

export_current_params_to_yaml

export_current_params_to_yaml(yaml_file: str) -> None

Export this tracker's active model and config to YAML (backward-compatible wrapper).

Source code in src/dnt/track/tracker.py
1039
1040
1041
def export_current_params_to_yaml(self, yaml_file: str) -> None:
    """Export this tracker's active model and config to YAML (backward-compatible wrapper)."""
    self.export_current_config_to_yaml(yaml_file)