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.

Attributes:

Name Type Description
shared_kalman KalmanFilterXYWH

A shared Kalman filter for all instances of BOTrack.

smooth_feat ndarray

Smoothed feature vector.

curr_feat ndarray

Current feature vector.

features deque

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

alpha float

Smoothing factor for the exponential moving average of features.

mean ndarray

The mean state of the Kalman filter.

covariance ndarray

The covariance matrix of the Kalman filter.

Methods:

Name Description
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).

Usage

bo_track = BOTrack(tlwh, score, cls, feat) bo_track.predict() bo_track.update(new_track, frame_id)

Source code in ultralytics/trackers/bot_sort.py
def __init__(self, tlwh, score, cls, feat=None, feat_history=50):
    """Initialize YOLOv8 object with temporal parameters, such as feature history, alpha and current features."""
    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

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

convert_coords

convert_coords(tlwh)

Converts Top-Left-Width-Height bounding box coordinates to X-Y-Width-Height format.

Source code in ultralytics/trackers/bot_sort.py
def convert_coords(self, tlwh):
    """Converts Top-Left-Width-Height bounding box coordinates to X-Y-Width-Height format."""
    return self.tlwh_to_xywh(tlwh)

multi_predict staticmethod

multi_predict(stracks)

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

Source code in ultralytics/trackers/bot_sort.py
@staticmethod
def multi_predict(stracks):
    """Predicts the mean and covariance of multiple object tracks using 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 mean and covariance using Kalman filter.

Source code in ultralytics/trackers/bot_sort.py
def predict(self):
    """Predicts the mean and covariance using Kalman filter."""
    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 to format (center x, center y, width, height).

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

update

update(new_track, frame_id)

Update the YOLOv8 instance with new track and frame ID.

Source code in ultralytics/trackers/bot_sort.py
def update(self, new_track, frame_id):
    """Update the YOLOv8 instance with new track and 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 features vector and smooth it using exponential moving average.

Source code in ultralytics/trackers/bot_sort.py
def update_features(self, feat):
    """Update features vector and smooth it using exponential moving average."""
    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:

Name Type Description
proximity_thresh float

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

appearance_thresh float

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

encoder object

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

gmc GMC

An instance of the GMC algorithm for data association.

args object

Parsed command-line arguments containing tracking parameters.

Methods:

Name Description
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.

Usage

bot_sort = BOTSORT(args, frame_rate) 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.

Source code in ultralytics/trackers/bot_sort.py
def __init__(self, args, frame_rate=30):
    """Initialize YOLOv8 object with ReID module and GMC algorithm."""
    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)

Get 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):
    """Get distances between tracks and detections using IoU and (optionally) ReID embeddings."""
    dists = matching.iou_distance(tracks, detections)
    dists_mask = dists > self.proximity_thresh

    # TODO: mot20
    # if not self.args.mot20:
    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 object tracking.

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

init_track

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

Initialize track with detections, scores, and classes.

Source code in ultralytics/trackers/bot_sort.py
def init_track(self, dets, scores, cls, img=None):
    """Initialize track with detections, scores, and classes."""
    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)

Predict and track multiple objects with YOLOv8 model.

Source code in ultralytics/trackers/bot_sort.py
def multi_predict(self, tracks):
    """Predict and track multiple objects with YOLOv8 model."""
    BOTrack.multi_predict(tracks)

reset

reset()

Reset tracker.

Source code in ultralytics/trackers/bot_sort.py
def reset(self):
    """Reset tracker."""
    super().reset()
    self.gmc.reset_params()





Created 2023-11-12, Updated 2024-07-21
Authors: glenn-jocher (6), Burhan-Q (1), Laughing-q (1)