
    j              	           d dl Zd dlZd dlmZ d dlmZmZ 	 d dlZej	        sJ n## e
eef$ r d dlmZ  ed           d dlZY nw xY wddej        ded	efd
Zdededej        fdZddedededej        fdZdej        dedej        fdZdS )    N)cdist)batch_probioubbox_ioa)check_requirementszlap>=0.5.12Tcost_matrixthreshuse_lapc                      j         dk    rht          j        dt                    t	          t           j        d                             t	          t           j        d                             fS |rrt          j         d          \  }d t                    D             }t          j
        dk               d         }t          j
        dk               d         }nqt          j                                       \  t          j         fdt          t                              D                       }t          |          dk    rYt!          t          j         j        d                             }t!          t          j         j        d                             }nt!          t%          t          j         j        d                             t%          |d	d	df                   z
            }t!          t%          t          j         j        d                             t%          |d	d	df                   z
            }|||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:
        matched_indices (list[list[int]] | np.ndarray): Matched indices of shape (K, 2), where K is the number of
            matches.
        unmatched_a (tuple | list | np.ndarray): Unmatched indices from the first set.
        unmatched_b (tuple | list | np.ndarray): Unmatched indices from the second set.

    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      dtype   T)extend_cost
cost_limitc                 (    g | ]\  }}|d k    ||gS )r    ).0ixmxs      h/home/longshao/multi-rider-rag/.venv/lib/python3.11/site-packages/ultralytics/trackers/utils/matching.py
<listcomp>z%linear_assignment.<locals>.<listcomp>.   s%    BBBB"''B8'''    c                 d    g | ],}|         |         f         k    |         |         g-S r   r   )r   ir   r   xys     r   r   z%linear_assignment.<locals>.<listcomp>5   sH    gggq[QRSTQUWXYZW[Q[E\`fEfEfqtQqTlEfEfEfr   N)sizenpemptyinttuplerangeshapelaplapjv	enumeratewherescipyoptimizelinear_sum_assignmentasarraylenlistarange	frozenset)	r   r   r	   _matchesunmatched_aunmatched_br   r   s	   ``     @@r   linear_assignmentr4      s   & 1xc***E%8I!8L2M2M,N,NPUV[\g\mno\pVqVqPrPrrr f )KTfMMM1aBB)A,,BBBhq1uooa(hq1uooa( ~33K@@1*gggggggE#a&&MMggghhw<<1ry):1)=>>??Kry):1)=>>??KKy;3DQ3G)H)HIIIV]^_^_^_ab^bVcLdLddeeKy;3DQ3G)H)HIIIV]^_^_^_ab^bVcLdLddeeKK,,r   atracksbtracksreturnc                 @   | r t          | d         t          j                  s"|r%t          |d         t          j                  r| }|}nd | D             }d |D             }t          j        t	          |          t	          |          ft          j                  }t	          |          rt	          |          rt	          |d                   dk    rxt	          |d                   dk    r_t          t          j        |t          j                  t          j        |t          j                                                            }nNt          t          j        |t          j                  t          j        |t          j                  d          }d|z
  S )	a  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 with shape (len(atracks), len(btracks)).

    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                 8    g | ]}|j         |j        n|j        S Nanglexywhaxyxyr   tracks     r   r   z iou_distance.<locals>.<listcomp>T   '    ^^^U!8%++ej^^^r   c                 8    g | ]}|j         |j        n|j        S r:   r;   r?   s     r   r   z iou_distance.<locals>.<listcomp>U   rA   r   r      T)iour   )

isinstancer   ndarrayzerosr,   float32r   ascontiguousarraynumpyr   )r5   r6   atlbrsbtlbrsiouss        r   iou_distancerN   @   s     	 _Jwqz2:66 _G _
SZ[\S]_a_iHjHj _^^V]^^^^^V]^^^8S[[#f++.bjAAAD
6{{ s6{{ vay>>Q3vay>>Q#6#6 $V2:>>>$V2:>>>  egg D
 $V2:>>>$V2:>>>  D
 t8Or   cosinetracks
detectionsmetricc                    t          j        t          |           t          |          ft           j                  }|j        dk    r|S t          j        d |D             t           j                  }t          j        d | D             t           j                  }t          j        dt          |||                    }|S )a  Compute distance between tracks and detections based on embeddings.

    Args:
        tracks (list[BOTrack]): List of tracks, where each track contains embedding features.
        detections (list[BOTrack]): 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 = [BOTrack(...), BOTrack(...)]  # List of track objects with embedding features
        >>> detections = [BOTrack(...), BOTrack(...)]  # List of detection objects with embedding features
        >>> cost_matrix = embedding_distance(tracks, detections, metric="cosine")
    r   r   c                     g | ]	}|j         
S r   )	curr_featr?   s     r   r   z&embedding_distance.<locals>.<listcomp>|   s    GGG5uGGGr   c                     g | ]	}|j         
S r   )smooth_featr?   s     r   r   z&embedding_distance.<locals>.<listcomp>   s     G G Gu!2 G G Gr   g        )r   rG   r,   rH   r   r+   maximumr   )rP   rQ   rR   r   det_featurestrack_featuress         r   embedding_distancer[   g   s    $ (CKKZ9LLLK1:GGJGGGrzZZZL Z G G G G GrzZZZN*S%f"M"MNNKr   c                     | j         dk    r| S d| z
  }t          j        d |D                       }|d                             | j        d         d          }||z  }d|z
  S )a  Fuse cost matrix with detection scores to produce a single cost 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 cost 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                     g | ]	}|j         
S r   )score)r   dets     r   r   zfuse_score.<locals>.<listcomp>   s    ;;;39;;;r   N)axis)r   r   arrayrepeatr#   )r   rQ   iou_sim
det_scoresfuse_sims        r   
fuse_scorerf      sx      1+oG;;
;;;<<JD!(():1)=A(FFJ#Hx<r   )T)rO   )rJ   r   r(   scipy.spatial.distancer   ultralytics.utils.metricsr   r   r$   __version__ImportErrorAssertionErrorAttributeErrorultralytics.utils.checksr   rF   floatboolr4   r-   rN   strr[   rf   r   r   r   <module>rq      s        ( ( ( ( ( ( = = = = = = = =JJJ??^^4   ;;;;;;}%%%JJJJJ	)- )-2: )-u )-t )- )- )- )-X$$ $ $"* $ $ $ $N t  s RTR\    :BJ D RZ      s   & AA