Object tracking
Tracking assigns a stable identity to each detection across video frames. LibreYOLO does not model it as a task with its own weights: it is a predict mode, model.track(), that runs a chosen tracker over the per-frame output of a detection, segmentation or pose model.
Definition
Tracking is not one of LibreYOLO's task keys, and there is no tracking
checkpoint to download. It is a method on the model, model.track(source),
which runs detection on each frame and associates the results across time. The
method is a generator: it yields one Results per processed frame, with
result.track_id set to an (N,) integer tensor aligned with result.boxes.
The same IDs are also on result.boxes.id.
Only confirmed, currently tracked objects are yielded. A track the association
loses stays alive for a configured number of frames before it is dropped,
track_buffer for ByteTrack and BoT-SORT and max_age for the two OC-SORT
variants, so an object recovered inside that window keeps its original ID.
Because association happens after detection, the frame's other payloads survive
it: the tracked Results is the detection Results sliced to the matched rows,
so masks and keypoints come through with the boxes.
Models
Two independent choices go into a tracking run: the model that produces boxes each frame, and the tracker that links them.
Any native LibreYOLO model whose task is detection, segmentation or pose exposes
track(), so the choice of detector is the ordinary one. See
the model index for the full list, or start from
YOLO9, RF-DETR,
D-FINE or RTMDet. Tasks whose
results have no box to associate refuse the call rather than returning
meaningless IDs: classification, oriented boxes, points, depth, surface normals,
edges, semantic and panoptic segmentation, restoration, OCR and body mesh all
raise from track().
Two of LibreYOLO's model tiers also decline it. Models loaded through
LibreSAM are image segmenters, and models loaded through LibreOpenVocab
are per-frame detectors; both raise from track() and are used with predict()
per frame instead.
Tracking runs on native PyTorch models. An exported artifact loaded through
LibreYOLO("model.onnx") returns a runtime backend object, which carries
predict() but not track().
Four trackers ship with the library, selected by the tracker argument:
"bytetrack" is the default. It is motion only, with a Kalman filter and a
three-stage association: high-confidence detections first, then a second pass
that gives low-confidence detections a chance to match an existing track before
they are discarded, then unconfirmed tracks. Configured with TrackConfig.
"botsort" keeps ByteTrack's three-stage lifecycle but uses a
center-width-height Kalman state and compensates predicted tracks for camera
motion before matching. This is the motion-only variant of BoT-SORT; it runs no
appearance model. Configured with BoTSortConfig, which adds enable_cmc,
cmc_method and cmc_downscale.
"ocsort" is also motion only, and adds a velocity-direction term to the
association cost, a second association pass against each track's last real
observation, and a smoothing of the Kalman state along a virtual trajectory when
a track is re-found. Configured with OCSortConfig.
"deepocsort" extends OC-SORT with appearance. Each track keeps a
confidence-weighted moving average of re-identification embeddings, and a cosine
similarity term joins the association cost, so identities survive long
occlusions and crossing targets. It costs one small embedding network forward
per frame, and its OSNet weights download on first use. Configured with
DeepOCSortConfig.
Predict
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt") # track() is a generator: one Results per processed frame.for result in model.track("video.mp4"): print(result.track_id) # (N,) int tensor, aligned with boxes print(result.boxes.xyxy)from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt") # "bytetrack" (default), "botsort", "ocsort" or "deepocsort".for result in model.track("video.mp4", tracker="botsort"): print(result.track_id)from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt") # Without output_path, the file lands in runs/track/<video_stem>.mp4.for result in model.track("video.mp4", save=True, vid_stride=2): passfrom libreyolo import BoTSortConfig, LibreYOLO model = LibreYOLO("LibreYOLO9s.pt") # The config type selects the tracker, so tracker= is redundant here.config = BoTSortConfig(track_buffer=60, frame_rate=25, enable_cmc=False)for result in model.track("video.mp4", tracker_config=config): print(result.track_id) # Or pass the same fields as keyword arguments and let track() build it.for result in model.track("video.mp4", tracker="botsort", track_buffer=60): print(result.track_id)track_conf sets the threshold for the first association stage:
track_high_thresh for ByteTrack and BoT-SORT, det_thresh for OC-SORT and
Deep OC-SORT. It is not predict()'s conf, and for ByteTrack, BoT-SORT and
OC-SORT the detector runs at a lower threshold internally so weak detections
stay available for the recovery pass. Deep OC-SORT runs the detector at
det_thresh itself. For ByteTrack and BoT-SORT, track_conf must be at or
above track_low_thresh, which defaults to 0.1.
Tracker settings arrive in one of two ways. Pass a config instance to
tracker_config=, and its type selects the tracker, making tracker= redundant.
Or pass the fields as keyword arguments and let track() build the config for
the tracker you named; unknown keys warn rather than being applied silently.
Either way, track_conf is ignored once the matching key is set explicitly.
The remaining arguments mirror prediction: iou, imgsz, classes, max_det,
vid_stride, show, and save with output_path. The source is a video file
path. See prediction for result handling.
Train
Trackers are not trained. Three of the four are pure motion models with no learned parameters at all, and Deep OC-SORT's appearance network is a published re-identification checkpoint that downloads on first use. Improving tracking quality means improving the detector, or tuning the association thresholds above.