Skip to content

Reference for ultralytics/trackers/bot_sort.py

Note

This file is available at https://github.com/ultralytics/ultralytics/blob/main/ultralytics/trackers/bot_sort.py. If you spot a problem please help fix it by contributing a Pull Request 🛠️. Thank you 🙏!


ultralytics.trackers.bot_sort.BOTrack

BOTrack(tlwh, score, cls, feat=None, feat_history=50)

Bases: STrack

An extended version of the STrack class for YOLOv8, adding object tracking features.

This class extends the STrack class to include additional functionalities for object tracking, such as feature smoothing, Kalman filter prediction, and reactivation of tracks.

Attributes:

NameTypeDescription
shared_kalmanKalmanFilterXYWH

A shared Kalman filter for all instances of BOTrack.

smooth_featndarray

Smoothed feature vector.

curr_featndarray

Current feature vector.

featuresdeque

A deque to store feature vectors with a maximum length defined by feat_history.

alphafloat

Smoothing factor for the exponential moving average of features.

meanndarray

The mean state of the Kalman filter.

covariancendarray

The covariance matrix of the Kalman filter.

Methods:

NameDescription
update_features

Update features vector and smooth it using exponential moving average.

predict

Predicts the mean and covariance using Kalman filter.

re_activate

Reactivates a track with updated features and optionally new ID.

update

Update the YOLOv8 instance with new track and frame ID.

tlwh

Property that gets the current position in tlwh format (top left x, top left y, width, height).

multi_predict

Predicts the mean and covariance of multiple object tracks using shared Kalman filter.

convert_coords

Converts tlwh bounding box coordinates to xywh format.

tlwh_to_xywh

Convert bounding box to xywh format (center x, center y, width, height).

Examples:

Create a BOTrack instance and update its features

>>> bo_track = BOTrack(tlwh=[100, 50, 80, 40], score=0.9, cls=1, feat=np.random.rand(128))
>>> bo_track.predict()
>>> new_track = BOTrack(tlwh=[110, 60, 80, 40], score=0.85, cls=1, feat=np.random.rand(128))
>>> bo_track.update(new_track, frame_id=2)

Parameters:

NameTypeDescriptionDefault
tlwhndarray

Bounding box coordinates in tlwh format (top left x, top left y, width, height).

required
scorefloat

Confidence score of the detection.

required
clsint

Class ID of the detected object.

required
featndarray | None

Feature vector associated with the detection.

None
feat_historyint

Maximum length of the feature history deque.

50

Examples:

Initialize a BOTrack object with bounding box, score, class ID, and feature vector

>>> tlwh = np.array([100, 50, 80, 120])
>>> score = 0.9
>>> cls = 1
>>> feat = np.random.rand(128)
>>> bo_track = BOTrack(tlwh, score, cls, feat)
Source code in ultralytics/trackers/bot_sort.py
def __init__(self, tlwh, score, cls, feat=None, feat_history=50):
    """
    Initialize a BOTrack object with temporal parameters, such as feature history, alpha, and current features.

    Args:
        tlwh (np.ndarray): Bounding box coordinates in tlwh format (top left x, top left y, width, height).
        score (float): Confidence score of the detection.
        cls (int): Class ID of the detected object.
        feat (np.ndarray | None): Feature vector associated with the detection.
        feat_history (int): Maximum length of the feature history deque.

    Examples:
        Initialize a BOTrack object with bounding box, score, class ID, and feature vector
        >>> tlwh = np.array([100, 50, 80, 120])
        >>> score = 0.9
        >>> cls = 1
        >>> feat = np.random.rand(128)
        >>> bo_track = BOTrack(tlwh, score, cls, feat)
    """
    super().__init__(tlwh, score, cls)

    self.smooth_feat = None
    self.curr_feat = None
    if feat is not None:
        self.update_features(feat)
    self.features = deque([], maxlen=feat_history)
    self.alpha = 0.9

tlwh property

tlwh

Returns the current bounding box position in (top left x, top left y, width, height) format.

convert_coords

convert_coords(tlwh)

Converts tlwh bounding box coordinates to xywh format.

Source code in ultralytics/trackers/bot_sort.py
def convert_coords(self, tlwh):
    """Converts tlwh bounding box coordinates to xywh format."""
    return self.tlwh_to_xywh(tlwh)

multi_predict staticmethod

multi_predict(stracks)

Predicts the mean and covariance for multiple object tracks using a shared Kalman filter.

Source code in ultralytics/trackers/bot_sort.py
@staticmethod
def multi_predict(stracks):
    """Predicts the mean and covariance for multiple object tracks using a shared Kalman filter."""
    if len(stracks) <= 0:
        return
    multi_mean = np.asarray([st.mean.copy() for st in stracks])
    multi_covariance = np.asarray([st.covariance for st in stracks])
    for i, st in enumerate(stracks):
        if st.state != TrackState.Tracked:
            multi_mean[i][6] = 0
            multi_mean[i][7] = 0
    multi_mean, multi_covariance = BOTrack.shared_kalman.multi_predict(multi_mean, multi_covariance)
    for i, (mean, cov) in enumerate(zip(multi_mean, multi_covariance)):
        stracks[i].mean = mean
        stracks[i].covariance = cov

predict

predict()

Predicts the object's future state using the Kalman filter to update its mean and covariance.

Source code in ultralytics/trackers/bot_sort.py
def predict(self):
    """Predicts the object's future state using the Kalman filter to update its mean and covariance."""
    mean_state = self.mean.copy()
    if self.state != TrackState.Tracked:
        mean_state[6] = 0
        mean_state[7] = 0

    self.mean, self.covariance = self.kalman_filter.predict(mean_state, self.covariance)

re_activate

re_activate(new_track, frame_id, new_id=False)

Reactivates a track with updated features and optionally assigns a new ID.

Source code in ultralytics/trackers/bot_sort.py
def re_activate(self, new_track, frame_id, new_id=False):
    """Reactivates a track with updated features and optionally assigns a new ID."""
    if new_track.curr_feat is not None:
        self.update_features(new_track.curr_feat)
    super().re_activate(new_track, frame_id, new_id)

tlwh_to_xywh staticmethod

tlwh_to_xywh(tlwh)

Convert bounding box from tlwh (top-left-width-height) to xywh (center-x-center-y-width-height) format.

Source code in ultralytics/trackers/bot_sort.py
@staticmethod
def tlwh_to_xywh(tlwh):
    """Convert bounding box from tlwh (top-left-width-height) to xywh (center-x-center-y-width-height) format."""
    ret = np.asarray(tlwh).copy()
    ret[:2] += ret[2:] / 2
    return ret

update

update(new_track, frame_id)

Updates the YOLOv8 instance with new track information and the current frame ID.

Source code in ultralytics/trackers/bot_sort.py
def update(self, new_track, frame_id):
    """Updates the YOLOv8 instance with new track information and the current frame ID."""
    if new_track.curr_feat is not None:
        self.update_features(new_track.curr_feat)
    super().update(new_track, frame_id)

update_features

update_features(feat)

Update the feature vector and apply exponential moving average smoothing.

Source code in ultralytics/trackers/bot_sort.py
def update_features(self, feat):
    """Update the feature vector and apply exponential moving average smoothing."""
    feat /= np.linalg.norm(feat)
    self.curr_feat = feat
    if self.smooth_feat is None:
        self.smooth_feat = feat
    else:
        self.smooth_feat = self.alpha * self.smooth_feat + (1 - self.alpha) * feat
    self.features.append(feat)
    self.smooth_feat /= np.linalg.norm(self.smooth_feat)





ultralytics.trackers.bot_sort.BOTSORT

BOTSORT(args, frame_rate=30)

Bases: BYTETracker

An extended version of the BYTETracker class for YOLOv8, designed for object tracking with ReID and GMC algorithm.

Attributes:

NameTypeDescription
proximity_threshfloat

Threshold for spatial proximity (IoU) between tracks and detections.

appearance_threshfloat

Threshold for appearance similarity (ReID embeddings) between tracks and detections.

encoderAny

Object to handle ReID embeddings, set to None if ReID is not enabled.

gmcGMC

An instance of the GMC algorithm for data association.

argsAny

Parsed command-line arguments containing tracking parameters.

Methods:

NameDescription
get_kalmanfilter

Returns an instance of KalmanFilterXYWH for object tracking.

init_track

Initialize track with detections, scores, and classes.

get_dists

Get distances between tracks and detections using IoU and (optionally) ReID.

multi_predict

Predict and track multiple objects with YOLOv8 model.

Examples:

Initialize BOTSORT and process detections

>>> bot_sort = BOTSORT(args, frame_rate=30)
>>> bot_sort.init_track(dets, scores, cls, img)
>>> bot_sort.multi_predict(tracks)
Note

The class is designed to work with the YOLOv8 object detection model and supports ReID only if enabled via args.

Parameters:

NameTypeDescriptionDefault
argsobject

Parsed command-line arguments containing tracking parameters.

required
frame_rateint

Frame rate of the video being processed.

30

Examples:

Initialize BOTSORT with command-line arguments and a specified frame rate:

>>> args = parse_args()
>>> bot_sort = BOTSORT(args, frame_rate=30)
Source code in ultralytics/trackers/bot_sort.py
def __init__(self, args, frame_rate=30):
    """
    Initialize YOLOv8 object with ReID module and GMC algorithm.

    Args:
        args (object): Parsed command-line arguments containing tracking parameters.
        frame_rate (int): Frame rate of the video being processed.

    Examples:
        Initialize BOTSORT with command-line arguments and a specified frame rate:
        >>> args = parse_args()
        >>> bot_sort = BOTSORT(args, frame_rate=30)
    """
    super().__init__(args, frame_rate)
    # ReID module
    self.proximity_thresh = args.proximity_thresh
    self.appearance_thresh = args.appearance_thresh

    if args.with_reid:
        # Haven't supported BoT-SORT(reid) yet
        self.encoder = None
    self.gmc = GMC(method=args.gmc_method)

get_dists

get_dists(tracks, detections)

Calculates distances between tracks and detections using IoU and optionally ReID embeddings.

Source code in ultralytics/trackers/bot_sort.py
def get_dists(self, tracks, detections):
    """Calculates distances between tracks and detections using IoU and optionally ReID embeddings."""
    dists = matching.iou_distance(tracks, detections)
    dists_mask = dists > self.proximity_thresh

    if self.args.fuse_score:
        dists = matching.fuse_score(dists, detections)

    if self.args.with_reid and self.encoder is not None:
        emb_dists = matching.embedding_distance(tracks, detections) / 2.0
        emb_dists[emb_dists > self.appearance_thresh] = 1.0
        emb_dists[dists_mask] = 1.0
        dists = np.minimum(dists, emb_dists)
    return dists

get_kalmanfilter

get_kalmanfilter()

Returns an instance of KalmanFilterXYWH for predicting and updating object states in the tracking process.

Source code in ultralytics/trackers/bot_sort.py
def get_kalmanfilter(self):
    """Returns an instance of KalmanFilterXYWH for predicting and updating object states in the tracking process."""
    return KalmanFilterXYWH()

init_track

init_track(dets, scores, cls, img=None)

Initialize object tracks using detection bounding boxes, scores, class labels, and optional ReID features.

Source code in ultralytics/trackers/bot_sort.py
def init_track(self, dets, scores, cls, img=None):
    """Initialize object tracks using detection bounding boxes, scores, class labels, and optional ReID features."""
    if len(dets) == 0:
        return []
    if self.args.with_reid and self.encoder is not None:
        features_keep = self.encoder.inference(img, dets)
        return [BOTrack(xyxy, s, c, f) for (xyxy, s, c, f) in zip(dets, scores, cls, features_keep)]  # detections
    else:
        return [BOTrack(xyxy, s, c) for (xyxy, s, c) in zip(dets, scores, cls)]  # detections

multi_predict

multi_predict(tracks)

Predicts the mean and covariance of multiple object tracks using a shared Kalman filter.

Source code in ultralytics/trackers/bot_sort.py
def multi_predict(self, tracks):
    """Predicts the mean and covariance of multiple object tracks using a shared Kalman filter."""
    BOTrack.multi_predict(tracks)

reset

reset()

Resets the BOTSORT tracker to its initial state, clearing all tracked objects and internal states.

Source code in ultralytics/trackers/bot_sort.py
def reset(self):
    """Resets the BOTSORT tracker to its initial state, clearing all tracked objects and internal states."""
    super().reset()
    self.gmc.reset_params()



📅 Created 11 months ago ✏️ Updated 1 month ago