рд╕рд╛рдордЧреНрд░реА рдкрд░ рдЬрд╛рдПрдВ

рдХреЗ рд▓рд┐рдП рд╕рдВрджрд░реНрдн ultralytics/trackers/bot_sort.py

рдиреЛрдЯ

рдпрд╣ рдлрд╝рд╛рдЗрд▓ рдпрд╣рд╛рдБ рдЙрдкрд▓рдмреНрдз рд╣реИ https://github.com/ultralytics/ultralytics/рдмреВрдБрдж/рдореБрдЦреНрдп/ultralytics/рдЯреНрд░реИрдХрд░реНрд╕/bot_sort.py рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред рдпрджрд┐ рдЖрдк рдХреЛрдИ рд╕рдорд╕реНрдпрд╛ рджреЗрдЦрддреЗ рд╣реИрдВ рддреЛ рдХреГрдкрдпрд╛ рдкреБрд▓ рдЕрдиреБрд░реЛрдз рдХрд╛ рдпреЛрдЧрджрд╛рди рдХрд░рдХреЗ рдЗрд╕реЗ рдареАрдХ рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдВ ЁЯЫая╕Пред ЁЯЩП рдзрдиреНрдпрд╡рд╛рдж !



ultralytics.trackers.bot_sort.BOTrack

рдХрд╛ рд░реВрдк: STrack

рдХреЗ рд▓рд┐рдП STrack рд╡рд░реНрдЧ рдХрд╛ рдПрдХ рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рд╕рдВрд╕реНрдХрд░рдг YOLOv8, рдСрдмреНрдЬреЗрдХреНрдЯ рдЯреНрд░реИрдХрд┐рдВрдЧ рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреЛ рдЬреЛрдбрд╝рдирд╛ред

рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдБ:

рдирд╛рдо рдкреНрд░рдХрд╛рд░ рдпрд╛ рдХрд╝рд┐рд╕реНтАНрдо
shared_kalman KalmanFilterXYWH

BOTrack рдХреЗ рд╕рднреА рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рд╛рдЭрд╛ Kalman рдлрд╝рд┐рд▓реНрдЯрд░ред

smooth_feat ndarray

рдЪрд┐рдХрдирд╛ рдлреАрдЪрд░ рд╡реЗрдХреНрдЯрд░ред

curr_feat ndarray

рд╡рд░реНрддрдорд╛рди рд╕реБрд╡рд┐рдзрд╛ рд╡реЗрдХреНрдЯрд░ред

features deque

рджреНрд╡рд╛рд░рд╛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдЕрдзрд┐рдХрддрдо рд▓рдВрдмрд╛рдИ рдХреЗ рд╕рд╛рде рдлреАрдЪрд░ рд╡реИрдХреНрдЯрд░ рдХреЛ рд╕реНрдЯреЛрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ deque feat_history.

alpha float

рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреЗ рдШрд╛рддреАрдп рдЪрд▓рддреА рдФрд╕рдд рдХреЗ рд▓рд┐рдП рдЪреМрд░рд╕рд╛рдИ рдХрд╛рд░рдХред

mean ndarray

рдХрд▓рдореИрди рдлрд┐рд▓реНрдЯрд░ рдХреА рдФрд╕рдд рд╕реНрдерд┐рддрд┐ред

covariance ndarray

рдХрд▓рдореИрди рдлрд┐рд▓реНрдЯрд░ рдХрд╛ рд╕рд╣рдкреНрд░рд╕рд░рдг рдореИрдЯреНрд░рд┐рдХреНрд╕ред

рд╡рд┐рдзрд┐рдпрд╛рдБ:

рдирд╛рдо рдпрд╛ рдХрд╝рд┐рд╕реНтАНрдо
update_features

рд╕реБрд╡рд┐рдзрд╛рдУрдВ рд╡реЗрдХреНрдЯрд░ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВ рдФрд░ рдШрд╛рддреАрдп рдЪрд▓рддреА рдФрд╕рдд рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕реЗ рд╕реБрдЪрд╛рд░реВ рдХрд░реЗрдВред

predict

Kalman рдлрд┐рд▓реНрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рдорддрд▓рдм рдФрд░ рд╕рд╣рдкреНрд░рд╕рд░рдг рдХреА рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгреА рдХрд░рддрд╛ рд╣реИ.

re_activate

рдЕрдкрдбреЗрдЯ рдХреА рдЧрдИ рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдФрд░ рд╡реИрдХрд▓реНрдкрд┐рдХ рд░реВрдк рд╕реЗ рдирдИ рдЖрдИрдбреА рдХреЗ рд╕рд╛рде рдПрдХ рдЯреНрд░реИрдХ рдХреЛ рдлрд┐рд░ рд╕реЗ рд╕рдХреНрд░рд┐рдп рдХрд░рддрд╛ рд╣реИред

update

рдЕрджреНрдпрддрди рдХрд░реЗрдВ YOLOv8 рдирдП рдЯреНрд░реИрдХ рдФрд░ рдлреНрд░реЗрдо рдЖрдИрдбреА рдХреЗ рд╕рд╛рде рдЙрджрд╛рд╣рд░рдгред

tlwh

рдкреНрд░реЙрдкрд░реНрдЯреА рдЬрд┐рд╕реЗ tlwh рдлрд╝реЙрд░реНрдореИрдЯ рдореЗрдВ рд╡рд░реНрддрдорд╛рди рд╕реНрдерд╛рди рдорд┐рд▓рддрд╛ рд╣реИ (top left x, top left y, width, height).

multi_predict

рд╕рд╛рдЭрд╛ Kalman рдлрд┐рд▓реНрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рдХрдИ рд╡рд╕реНрддреБ рдкрдЯрд░рд┐рдпреЛрдВ рдХреЗ рдорддрд▓рдм рдФрд░ рд╕рд╣рдкреНрд░рд╕рд░рдг рдХреА рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгреА рдХрд░рддрд╛ рд╣реИ.

convert_coords

tlwh bounding рдмреЙрдХреНрд╕ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдХреЛ xywh рд╕реНрд╡рд░реВрдк рдореЗрдВ рдХрдирд╡рд░реНрдЯ рдХрд░рддрд╛ рд╣реИ.

tlwh_to_xywh

рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдХреЛ xywh рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдмрджрд▓реЗрдВ (center x, center y, width, height).

рдЙрдкрдпреЛрдЧ

bo_track = рдмреЙрдЯрд░реИрдХ (tlwh, рд╕реНрдХреЛрд░, cls, рдХрд░рддрдм) bo_track.predict() bo_track.update(new_track, frame_id)

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/trackers/bot_sort.py
 14 рдмрд╛рдВрдЧреНрд▓рд╛рджреЗрд╢ рдмрд╛рдВрдЧреНрд▓рд╛рджреЗрд╢ 14 рдмрд╛рдВрдЧреНрд▓рд╛рджреЗрд╢ рдмрд╛рдВрдЧреНрд▓рд╛рджреЗрд╢ 14 рдмрд╛рдВрдЧреНрд▓рд╛рджреЗрд╢ рдмрд╛рдВрдЧреНрд▓рд╛рджреЗрд╢ 14 рдмрд╛рдВрдЧреНрд▓рд╛рджреЗрд╢ рдмрд╛рдВрдЧреНрд▓рд╛рджреЗрд╢ 14 (рдорд▓реЗрд╢рд┐рдпрд╛) 14 рдмрд╛рдВрдЧреНрд▓рд╛рджреЗрд╢ рдмрд╛рдВрдЧреНрд▓рд╛рджреЗрд╢ (рд╡рд┐рдпрддрдирд╛рдо) 14 рдмрд╛рдВрдЧреНрд▓рд╛рджреЗрд╢ рдмрд╛рдВрдЧреНрд▓рд╛рджреЗрд╢ (рд╡рд┐рдпрддрдирд╛рдо) 14 рдмрд╛рдВрдЧреНрд▓рд╛рджреЗрд╢ рдмрд╛рдВрдЧреНрд▓рд╛рджреЗрд╢ (рдПрдордПрд╕) 14 рдмрд╛рдВрдЧреНрд▓рд╛рджреЗрд╢ (рдЖрд░рдмреАрдЖрдИ) 14 рдмрд╛рдВрдЧреНрд▓рд╛рджреЗрд╢ рдмрд╛рдВрдЧреНрд▓рд╛рджреЗрд╢ (рдЖрд░рдмреАрдЖрдИ) 14 рдмрд╛рдВрдЧреНрд▓рд╛рджреЗрд╢ рдмрд╛рдВрдЧреНрд▓рд╛рджреЗрд╢ (рдЖрд░рдмреАрдЖрдИ) 14 рдмрд╛рдВрдЧреНрд▓рд╛рджреЗрд╢ рдмрд╛рдВрдЧреНрд▓рд╛рджреЗрд╢ (рдЖрд░рдмреАрдЖрдИ) 14 (3) 32  16 17  18   19 20 21 22 23 24  25  26 27 28 29 30 31 32  33 34 35 36 37 38 39 40 41 42 43 44 45  46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99100101102103104105106107108109110111112113114115116117118119120121122
class BOTrack(STrack):
    """
    An extended version of the STrack class for YOLOv8, adding object tracking features.

    Attributes:
        shared_kalman (KalmanFilterXYWH): A shared Kalman filter for all instances of BOTrack.
        smooth_feat (np.ndarray): Smoothed feature vector.
        curr_feat (np.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 (np.ndarray): The mean state of the Kalman filter.
        covariance (np.ndarray): The covariance matrix of the Kalman filter.

    Methods:
        update_features(feat): Update features vector and smooth it using exponential moving average.
        predict(): Predicts the mean and covariance using Kalman filter.
        re_activate(new_track, frame_id, new_id): Reactivates a track with updated features and optionally new ID.
        update(new_track, frame_id): 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(stracks): Predicts the mean and covariance of multiple object tracks using shared Kalman filter.
        convert_coords(tlwh): Converts tlwh bounding box coordinates to xywh format.
        tlwh_to_xywh(tlwh): 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)
    """

    shared_kalman = KalmanFilterXYWH()

    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

    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)

    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)

    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)

    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)

    @property
    def tlwh(self):
        """Get current position in bounding box format `(top left x, top left y, width, height)`."""
        if self.mean is None:
            return self._tlwh.copy()
        ret = self.mean[:4].copy()
        ret[:2] -= ret[2:] / 2
        return ret

    @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

    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)

    @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

tlwh property

рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рд╡рд░реНрддрдорд╛рди рд╕реНрдерд┐рддрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ (top left x, top left y, width, height).

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

рдкреНрд░рд╛рд░рдВрдн YOLOv8 рдЕрд╕реНрдерд╛рдпреА рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рдСрдмреНрдЬреЗрдХреНрдЯ, рдЬреИрд╕реЗ рдлреАрдЪрд░ рдЗрддрд┐рд╣рд╛рд╕, рдЕрд▓реНрдлрд╛ рдФрд░ рд╡рд░реНрддрдорд╛рди рд╕реБрд╡рд┐рдзрд╛рдПрдБред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб 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

convert_coords(tlwh)

рд╢реАрд░реНрд╖-рдмрд╛рдПрдБ-рдЪреМрдбрд╝рд╛рдИ-рдКрдБрдЪрд╛рдИ рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдХреЛ X-Y-рдЪреМрдбрд╝рд╛рдИ-рдКрдБрдЪрд╛рдИ рд╕реНрд╡рд░реВрдк рдореЗрдВ рдХрдирд╡рд░реНрдЯ рдХрд░рддрд╛ рд╣реИ.

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб 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(stracks) staticmethod

рд╕рд╛рдЭрд╛ Kalman рдлрд┐рд▓реНрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рдХрдИ рд╡рд╕реНрддреБ рдкрдЯрд░рд┐рдпреЛрдВ рдХреЗ рдорддрд▓рдм рдФрд░ рд╕рд╣рдкреНрд░рд╕рд░рдг рдХреА рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгреА рдХрд░рддрд╛ рд╣реИ.

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб 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()

Kalman рдлрд┐рд▓реНрдЯрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рдорддрд▓рдм рдФрд░ рд╕рд╣рдкреНрд░рд╕рд░рдг рдХреА рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгреА рдХрд░рддрд╛ рд╣реИ.

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб 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(new_track, frame_id, new_id=False)

рдЕрдкрдбреЗрдЯ рдХреА рдЧрдИ рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдЯреНрд░реИрдХ рдХреЛ рдкреБрдирдГ рд╕рдХреНрд░рд┐рдп рдХрд░рддрд╛ рд╣реИ рдФрд░ рд╡реИрдХрд▓реНрдкрд┐рдХ рд░реВрдк рд╕реЗ рдПрдХ рдирдИ рдЖрдИрдбреА рдЕрд╕рд╛рдЗрди рдХрд░рддрд╛ рд╣реИред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб 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(tlwh) staticmethod

рдмрд╛рдЙрдВрдбрд┐рдВрдЧ рдмреЙрдХреНрд╕ рдХреЛ рдлреЙрд░реНрдореЗрдЯ рдореЗрдВ рдмрджрд▓реЗрдВ (center x, center y, width, height).

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб 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(new_track, frame_id)

рдЕрджреНрдпрддрди рдХрд░реЗрдВ YOLOv8 рдирдП рдЯреНрд░реИрдХ рдФрд░ рдлреНрд░реЗрдо рдЖрдИрдбреА рдХреЗ рд╕рд╛рде рдЙрджрд╛рд╣рд░рдгред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб 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(feat)

рд╕реБрд╡рд┐рдзрд╛рдУрдВ рд╡реЗрдХреНрдЯрд░ рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВ рдФрд░ рдШрд╛рддреАрдп рдЪрд▓рддреА рдФрд╕рдд рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕реЗ рд╕реБрдЪрд╛рд░реВ рдХрд░реЗрдВред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб 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

рдХрд╛ рд░реВрдк: BYTETracker

рдХреЗ рд▓рд┐рдП BYTETracker рд╡рд░реНрдЧ рдХрд╛ рдПрдХ рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рд╕рдВрд╕реНрдХрд░рдг YOLOv8, ReID рдФрд░ GMC рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЗ рд╕рд╛рде рдСрдмреНрдЬреЗрдХреНрдЯ рдЯреНрд░реИрдХрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ред

рд╡рд┐рд╢реЗрд╖рддрд╛рдПрдБ:

рдирд╛рдо рдкреНрд░рдХрд╛рд░ рдпрд╛ рдХрд╝рд┐рд╕реНтАНрдо
proximity_thresh float

рдкрдЯрд░рд┐рдпреЛрдВ рдФрд░ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рдмреАрдЪ рд╕реНрдерд╛рдирд┐рдХ рдирд┐рдХрдЯрддрд╛ (IoU) рдХреЗ рд▓рд┐рдП рджрд╣рд▓реАрдЬред

appearance_thresh float

рдкрдЯрд░рд┐рдпреЛрдВ рдФрд░ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рдмреАрдЪ рдЙрдкрд╕реНрдерд┐рддрд┐ рд╕рдорд╛рдирддрд╛ (ReID рдПрдореНрдмреЗрдбрд┐рдВрдЧ) рдХреЗ рд▓рд┐рдП рджрд╣рд▓реАрдЬред

encoder object

ReID рдПрдореНрдмреЗрдбрд┐рдВрдЧ рдХреЛ рд╣реИрдВрдбрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдСрдмреНрдЬреЗрдХреНрдЯ, ReID рд╕рдХреНрд╖рдо рдирд╣реАрдВ рд╣реЛрдиреЗ рдкрд░ рдХреЛрдИ рдирд╣реАрдВ рдкрд░ рд╕реЗрдЯ рдХрд░реЗрдВред

gmc GMC

рдбреЗрдЯрд╛ рдПрд╕реЛрд╕рд┐рдПрд╢рди рдХреЗ рд▓рд┐рдП рдЬреАрдПрдорд╕реА рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдгред

args object

рдЯреНрд░реИрдХрд┐рдВрдЧ рдкреИрд░рд╛рдореАрдЯрд░ рд╡рд╛рд▓реЗ рдХрдорд╛рдВрдб-рд▓рд╛рдЗрди рддрд░реНрдХреЛрдВ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд┐рдпрд╛ рдЧрдпрд╛ред

рд╡рд┐рдзрд┐рдпрд╛рдБ:

рдирд╛рдо рдпрд╛ рдХрд╝рд┐рд╕реНтАНрдо
get_kalmanfilter

рдСрдмреНрдЬреЗрдХреНрдЯ рдЯреНрд░реИрдХрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП KalmanFilterXYWH рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджреЗрддрд╛ рд╣реИред

init_track

рдбрд┐рдЯреЗрдХреНрд╢рди, рд╕реНрдХреЛрд░ рдФрд░ рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ рд╕рд╛рде рдЯреНрд░реИрдХ рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░реЗрдВред

get_dists

IoU рдФрд░ (рд╡реИрдХрд▓реНрдкрд┐рдХ рд░реВрдк рд╕реЗ) ReID рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкрдЯрд░рд┐рдпреЛрдВ рдФрд░ рдбрд┐рдЯреЗрдХреНрд╢рди рдХреЗ рдмреАрдЪ рджреВрд░рд┐рдпрд╛рдВ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред

multi_predict

рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгреА рдХрд░реЗрдВ рдФрд░ рдХрдИ рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдЯреНрд░реИрдХ рдХрд░реЗрдВ YOLOv8 рдХреЛ рдЧрдврд╝рдирд╛ред

рдЙрдкрдпреЛрдЧ

bot_sort = рдмреЙрдЯрд╕реЙрд░реНрдЯ (рдЖрд░реНрдЧ, frame_rate) bot_sort.init_track(рдбреЗрдЯреНрд╕, рд╕реНрдХреЛрд░, CLS, img) bot_sort.multi_predict (рдЯреНрд░реИрдХ)

рдиреЛрдЯ

рдХрдХреНрд╖рд╛ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдбрд┐рдЬрд╝рд╛рдЗрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ YOLOv8 рдСрдмреНрдЬреЗрдХреНрдЯ рдбрд┐рдЯреЗрдХреНрд╢рди рдореЙрдбрд▓ рдФрд░ рдХреЗрд╡рд▓ рддрднреА ReID рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ рдЬрдм args рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕рдХреНрд╖рдо рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реЛред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/trackers/bot_sort.py
class BOTSORT(BYTETracker):
    """
    An extended version of the BYTETracker class for YOLOv8, designed for object tracking with ReID and GMC algorithm.

    Attributes:
        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:
        get_kalmanfilter(): Returns an instance of KalmanFilterXYWH for object tracking.
        init_track(dets, scores, cls, img): Initialize track with detections, scores, and classes.
        get_dists(tracks, detections): Get distances between tracks and detections using IoU and (optionally) ReID.
        multi_predict(tracks): 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.
    """

    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)

    def get_kalmanfilter(self):
        """Returns an instance of KalmanFilterXYWH for object tracking."""
        return KalmanFilterXYWH()

    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

    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

    def multi_predict(self, tracks):
        """Predict and track multiple objects with YOLOv8 model."""
        BOTrack.multi_predict(tracks)

    def reset(self):
        """Reset tracker."""
        super().reset()
        self.gmc.reset_params()

__init__(args, frame_rate=30)

рдкреНрд░рд╛рд░рдВрдн YOLOv8 ReID рдореЙрдбреНрдпреВрд▓ рдФрд░ GMC рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЗ рд╕рд╛рде рдСрдмреНрдЬреЗрдХреНрдЯред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб 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(tracks, detections)

IoU рдФрд░ (рд╡реИрдХрд▓реНрдкрд┐рдХ рд░реВрдк рд╕реЗ) ReID рдПрдореНрдмреЗрдбрд┐рдВрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдкрдЯрд░рд┐рдпреЛрдВ рдФрд░ рдбрд┐рдЯреЗрдХреНрд╢рди рдХреЗ рдмреАрдЪ рджреВрд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб 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()

рдСрдмреНрдЬреЗрдХреНрдЯ рдЯреНрд░реИрдХрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП KalmanFilterXYWH рдХрд╛ рдПрдХ рдЙрджрд╛рд╣рд░рдг рджреЗрддрд╛ рд╣реИред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/trackers/bot_sort.py
def get_kalmanfilter(self):
    """Returns an instance of KalmanFilterXYWH for object tracking."""
    return KalmanFilterXYWH()

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

рдбрд┐рдЯреЗрдХреНрд╢рди, рд╕реНрдХреЛрд░ рдФрд░ рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ рд╕рд╛рде рдЯреНрд░реИрдХ рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░реЗрдВред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб 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(tracks)

рднрд╡рд┐рд╖реНрдпрд╡рд╛рдгреА рдХрд░реЗрдВ рдФрд░ рдХрдИ рд╡рд╕реНрддреБрдУрдВ рдХреЛ рдЯреНрд░реИрдХ рдХрд░реЗрдВ YOLOv8 рдХреЛ рдЧрдврд╝рдирд╛ред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/trackers/bot_sort.py
def multi_predict(self, tracks):
    """Predict and track multiple objects with YOLOv8 model."""
    BOTrack.multi_predict(tracks)

reset()

рдЯреНрд░реИрдХрд░ рд░реАрд╕реЗрдЯ рдХрд░реЗрдВред

рдореЗрдВ рд╕реНрд░реЛрдд рдХреЛрдб ultralytics/trackers/bot_sort.py
def reset(self):
    """Reset tracker."""
    super().reset()
    self.gmc.reset_params()





2023-11-12 рдмрдирд╛рдпрд╛ рдЧрдпрд╛, рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ 2024-05-08
рд▓реЗрдЦрдХ: рдмреБрд░рд╣рд╛рди-рдХреНрдпреВ (1), рдЧреНрд▓реЗрди-рдЬреЛрдЪрд░ (3), рд▓рд╛рдлрд┐рдВрдЧ-рдХреНрдпреВ (1)