o
    Wh ,                     @   s   d dl mZ d dlZd dlZd dlmZ d dlmZ ddl	m
Z
 ddlmZmZ ddlmZ dd	lmZ dd
lmZ G dd deZG dd deZG dd dZdS )    )dequeN)	xywh2xyxysave_one_box   )
TrackState)BYTETrackerSTrack)matching)GMCKalmanFilterXYWHc                       s~   e Zd ZdZe Zd fdd	Zdd Zdd	 Zd fdd	Z	 fddZ
edd Zedd Zdd Zedd Z  ZS )BOTracka  
    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:
        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: Update features vector and smooth it using exponential moving average.
        predict: Predict the mean and covariance using Kalman filter.
        re_activate: Reactivate a track with updated features and optionally new ID.
        update: Update the track with new detection and frame ID.
        tlwh: Property that gets the current position in tlwh format `(top left x, top left y, width, height)`.
        multi_predict: Predict the mean and covariance of multiple object tracks using shared Kalman filter.
        convert_coords: Convert 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)
    N2   c                    sF   t  ||| d| _d| _|dur| | tg |d| _d| _dS )aS  
        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)
        N)maxleng?)super__init__smooth_feat	curr_featupdate_featuresr   featuresalpha)selftlwhscoreclsfeatfeat_history	__class__ Q/var/www/vscode/kcb/lib/python3.10/site-packages/ultralytics/trackers/bot_sort.pyr   6   s   

zBOTrack.__init__c                 C   sl   |t j| }|| _| jdu r|| _n| j| j d| j |  | _| j| |  jt j| j  _dS )zIUpdate the feature vector and apply exponential moving average smoothing.Nr   )nplinalgnormr   r   r   r   append)r   r   r    r    r!   r   R   s   
zBOTrack.update_featuresc                 C   sB   | j  }| jtjkrd|d< d|d< | j|| j\| _ | _dS )z\Predict the object's future state using the Kalman filter to update its mean and covariance.r         N)meancopystater   Trackedkalman_filterpredict
covariance)r   
mean_stater    r    r!   r-   ]   s
   
zBOTrack.predictFc                    s*   |j dur| |j  t ||| dS )zHReactivate a track with updated features and optionally assign a new ID.N)r   r   r   re_activate)r   	new_trackframe_idnew_idr   r    r!   r0   f   s   
zBOTrack.re_activatec                    s(   |j dur| |j  t || dS )zIUpdate the track with new detection information and the current frame ID.N)r   r   r   update)r   r1   r2   r   r    r!   r4   l   s   
zBOTrack.updatec                 C   sJ   | j du r
| j S | j dd  }|dd  |dd d 8  < |S )z]Return the current bounding box position in `(top left x, top left y, width, height)` format.N      )r(   _tlwhr)   )r   retr    r    r!   r   r   s
   

 zBOTrack.tlwhc                 C   s   t | dkrdS tdd | D }tdd | D }t| D ]\}}|jtjkr6d|| d< d|| d< q tj	||\}}tt
||D ]\}\}}|| | _|| | _qGdS )zXPredict the mean and covariance for multiple object tracks using a shared Kalman filter.r   Nc                 S   s   g | ]}|j  qS r    )r(   r)   .0str    r    r!   
<listcomp>   s    z)BOTrack.multi_predict.<locals>.<listcomp>c                 S   s   g | ]}|j qS r    )r.   r9   r    r    r!   r<      s    r&   r'   )lenr"   asarray	enumerater*   r   r+   r   shared_kalmanmulti_predictzipr(   r.   )stracks
multi_meanmulti_covarianceir;   r(   covr    r    r!   rA   {   s   
zBOTrack.multi_predictc                 C   s
   |  |S )z5Convert tlwh bounding box coordinates to xywh format.)tlwh_to_xywh)r   r   r    r    r!   convert_coords   s   
zBOTrack.convert_coordsc                 C   s2   t |  }|dd  |dd d 7  < |S )zgConvert bounding box from tlwh (top-left-width-height) to xywh (center-x-center-y-width-height) format.Nr6   )r"   r>   r)   )r   r8   r    r    r!   rH      s    zBOTrack.tlwh_to_xywh)Nr   )F)__name__
__module____qualname____doc__r   r@   r   r   r-   r0   r4   propertyr   staticmethodrA   rI   rH   __classcell__r    r    r   r!   r      s    !	

r   c                       sP   e Zd ZdZd fdd	Zdd Zddd	Zd
d Zdd Z fddZ	  Z
S )BOTSORTa\  
    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 (Any): 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 (Any): Parsed command-line arguments containing tracking parameters.

    Methods:
        get_kalmanfilter: Return 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.
        reset: Reset the BOTSORT tracker to its initial state.

    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.
       c                    sf   t  || t|jd| _|j| _|j| _| jjdkr#dd | _dS |j	r.t
|j| _dS d| _dS )a  
        Initialize BOTSORT 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)
        )methodautoc                 S   s   dd | D S )Nc                 S      g | ]}|   qS r    cpunumpyr:   fr    r    r!   r<          z6BOTSORT.__init__.<locals>.<lambda>.<locals>.<listcomp>r    )featssr    r    r!   <lambda>   s    z"BOTSORT.__init__.<locals>.<lambda>N)r   r   r   
gmc_methodgmcproximity_threshappearance_threshargsmodel	with_reidReIDencoder)r   rc   
frame_rater   r    r!   r      s   
zBOTSORT.__init__c                 C   s   t  S )ziReturn an instance of KalmanFilterXYWH for predicting and updating object states in the tracking process.r   r   r    r    r!   get_kalmanfilter   s   zBOTSORT.get_kalmanfilterNc                 C   s\   t |dkrg S | jjr#| jdur#| ||}dd t||||D S dd t|||D S )zjInitialize object tracks using detection bounding boxes, scores, class labels, and optional ReID features.r   Nc                 S   s"   g | ]\}}}}t ||||qS r    r   )r:   xyxyr]   crZ   r    r    r!   r<      s   " z&BOTSORT.init_track.<locals>.<listcomp>c                 S   s   g | ]\}}}t |||qS r    rk   )r:   rl   r]   rm   r    r    r!   r<      s    )r=   rc   re   rg   rB   )r   detsscoresr   imgfeatures_keepr    r    r!   
init_track   s   zBOTSORT.init_trackc                 C   sz   t ||}|d| j k}| jjrt ||}| jjr;| jdur;t ||d }d||d| j k< d||< t	
||}|S )z[Calculate distances between tracks and detections using IoU and optionally ReID embeddings.r   Ng       @g      ?)r
   iou_distancera   rc   
fuse_scorere   rg   embedding_distancerb   r"   minimum)r   tracks
detectionsdists
dists_mask	emb_distsr    r    r!   	get_dists   s   zBOTSORT.get_distsc                 C   s   t | dS )zWPredict the mean and covariance of multiple object tracks using a shared Kalman filter.N)r   rA   )r   rw   r    r    r!   rA      s   zBOTSORT.multi_predictc                    s   t    | j  dS )zaReset the BOTSORT tracker to its initial state, clearing all tracked objects and internal states.N)r   resetr`   reset_paramsri   r   r    r!   r}      s   
zBOTSORT.reset)rR   )N)rJ   rK   rL   rM   r   rj   rr   r|   rA   r}   rP   r    r    r   r!   rQ      s    

rQ   c                   @   s    e Zd ZdZdd Zdd ZdS )rf   z,YOLO model as encoder for re-identification.c                 C   sD   ddl m} ||| _| jd|v rt| jjjd ndgdd dS )	z)Initialize encoder for re-identification.r   )YOLOz.ptr6   F)embedverboseN)ultralyticsr   rd   r=   )r   rd   r   r    r    r!   r      s   
.zReID.__init__c              
      s@   |   fddtt|ddddf D }dd |D S )z(Extract embeddings for detected objects.c                    s   g | ]	}t | d dqS )F)saver   )r:   detrp   r    r!   r<     s    z!ReID.__call__.<locals>.<listcomp>Nr5   c                 S   rU   r    rV   rY   r    r    r!   r<     r[   )rd   r   torch
from_numpy)r   rp   rn   r\   r    r   r!   __call__   s   2zReID.__call__N)rJ   rK   rL   rM   r   r   r    r    r    r!   rf      s    rf   )collectionsr   rX   r"   r   ultralytics.utils.opsr   ultralytics.utils.plottingr   	basetrackr   byte_trackerr   r	   utilsr
   	utils.gmcr   utils.kalman_filterr   r   rQ   rf   r    r    r    r!   <module>   s    ^