a
    yf                  
   @   s   d dl Zd dlZd dlmZ d dlmZmZ zd dlZej	s@J W n4 e
eefyv   d dlmZ ed d dlZY n0 dejeeeddd	Zeeejd
ddZdeeeejdddZejeejdddZdS )    N)cdist)batch_probioubbox_ioa)check_requirementszlapx>=0.5.2T)cost_matrixthreshuse_lapreturnc                    sZ   j dkr:tjdtdtt jd tt jd fS |rtj dd\}dd t	D }t
dk d }t
dk d }ntj \t fd	dttD }t|dkrtt jd }tt jd }nXttt jd t|d
d
df  }ttt jd t|d
d
df  }|||fS )a  
    Perform linear assignment using either the scipy or lap.lapjv method.

    Args:
        cost_matrix (np.ndarray): The matrix containing cost values for assignments, with shape (N, M).
        thresh (float): Threshold for considering an assignment valid.
        use_lap (bool): Use lap.lapjv for the assignment. If False, scipy.optimize.linear_sum_assignment is used.

    Returns:
        (tuple): A tuple containing:
            - matched_indices (np.ndarray): Array of matched indices of shape (K, 2), where K is the number of matches.
            - unmatched_a (np.ndarray): Array of unmatched indices from the first set, with shape (L,).
            - unmatched_b (np.ndarray): Array of unmatched indices from the second set, with shape (M,).

    Examples:
        >>> cost_matrix = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
        >>> thresh = 5.0
        >>> matched_indices, unmatched_a, unmatched_b = linear_assignment(cost_matrix, thresh, use_lap=True)
    r   )r      Zdtype   T)Zextend_costZ
cost_limitc                 S   s    g | ]\}}|d kr||gqS )r    ).0ZixZmxr   r   _/var/www/html/django/DPS/env/lib/python3.9/site-packages/ultralytics/trackers/utils/matching.py
<listcomp>/       z%linear_assignment.<locals>.<listcomp>c                    s4   g | ],} | | f kr| | gqS r   r   )r   ir   r   xyr   r   r   6   r   N)sizenpemptyinttuplerangeshapelapZlapjv	enumeratewherescipyoptimizeZlinear_sum_assignmentasarraylenlistZarangeset)r   r   r   _matchesZunmatched_aZunmatched_br   r   r   linear_assignment   s    
0&,,r(   )atracksbtracksr	   c                 C   s   | rt | d tjs(|r2t |d tjr2| }|}ndd | D }dd |D }tjt|t|ftjd}t|rt|rt|d dkrt|d dkrttj|tjdtj|tjd }n&t	tj|tjdtj|tjddd}d	| S )
ak  
    Compute cost based on Intersection over Union (IoU) between tracks.

    Args:
        atracks (list[STrack] | list[np.ndarray]): List of tracks 'a' or bounding boxes.
        btracks (list[STrack] | list[np.ndarray]): List of tracks 'b' or bounding boxes.

    Returns:
        (np.ndarray): Cost matrix computed based on IoU.

    Examples:
        Compute IoU distance between two sets of tracks
        >>> atracks = [np.array([0, 0, 10, 10]), np.array([20, 20, 30, 30])]
        >>> btracks = [np.array([5, 5, 15, 15]), np.array([25, 25, 35, 35])]
        >>> cost_matrix = iou_distance(atracks, btracks)
    r   c                 S   s"   g | ]}|j d ur|jn|jqS NZangleZxywhaZxyxyr   trackr   r   r   r   V   r   z iou_distance.<locals>.<listcomp>c                 S   s"   g | ]}|j d ur|jn|jqS r+   r,   r-   r   r   r   r   W   r   r      T)Ziour   )

isinstancer   ndarrayzerosr#   float32r   Zascontiguousarraynumpyr   )r)   r*   ZatlbrsZbtlbrsZiousr   r   r   iou_distanceA   s$    ( 
r5   cosine)tracks
detectionsmetricr	   c                 C   sv   t jt| t|ft jd}|jdkr*|S t jdd |D t jd}t jdd | D t jd}t dt|||}|S )a  
    Compute distance between tracks and detections based on embeddings.

    Args:
        tracks (list[STrack]): List of tracks, where each track contains embedding features.
        detections (list[BaseTrack]): List of detections, where each detection contains embedding features.
        metric (str): Metric for distance computation. Supported metrics include 'cosine', 'euclidean', etc.

    Returns:
        (np.ndarray): Cost matrix computed based on embeddings with shape (N, M), where N is the number of tracks
            and M is the number of detections.

    Examples:
        Compute the embedding distance between tracks and detections using cosine metric
        >>> tracks = [STrack(...), STrack(...)]  # List of track objects with embedding features
        >>> detections = [BaseTrack(...), BaseTrack(...)]  # List of detection objects with embedding features
        >>> cost_matrix = embedding_distance(tracks, detections, metric="cosine")
    r   r   c                 S   s   g | ]
}|j qS r   )Z	curr_featr-   r   r   r   r      r   z&embedding_distance.<locals>.<listcomp>c                 S   s   g | ]
}|j qS r   )Zsmooth_featr-   r   r   r   r      r   g        )r   r2   r#   r3   r   r"   maximumr   )r7   r8   r9   r   Zdet_featuresZtrack_featuresr   r   r   embedding_distancei   s    
r;   )r   r8   r	   c                 C   sX   | j dkr| S d|  }tdd |D }tj|ddj| jd dd}|| }d| S )a  
    Fuses cost matrix with detection scores to produce a single similarity matrix.

    Args:
        cost_matrix (np.ndarray): The matrix containing cost values for assignments, with shape (N, M).
        detections (list[BaseTrack]): List of detections, each containing a score attribute.

    Returns:
        (np.ndarray): Fused similarity matrix with shape (N, M).

    Examples:
        Fuse a cost matrix with detection scores
        >>> cost_matrix = np.random.rand(5, 10)  # 5 tracks and 10 detections
        >>> detections = [BaseTrack(score=np.random.rand()) for _ in range(10)]
        >>> fused_matrix = fuse_score(cost_matrix, detections)
    r   r   c                 S   s   g | ]
}|j qS r   )Zscore)r   Zdetr   r   r   r      r   zfuse_score.<locals>.<listcomp>)Zaxis)r   r   arrayZexpand_dimsrepeatr   )r   r8   Ziou_simZ
det_scoresZfuse_simr   r   r   
fuse_score   s    
r>   )T)r6   )r4   r   r    Zscipy.spatial.distancer   Zultralytics.utils.metricsr   r   r   __version__ImportErrorAssertionErrorAttributeErrorZultralytics.utils.checksr   r1   floatboolr   r(   r$   r5   strr;   r>   r   r   r   r   <module>   s   -(