
    h              	       l   S SK rS SKrS SKJr  S SKJrJr   S SKr\R                  (       d   e SS\R                  S\S\4S	 jjrS
\S\S\R                  4S jrSS\S\S\S\R                  4S jjrS\R                  S\S\R                  4S jrg! \
\\4 a    S SKJr  \" S5        S SKr Nf = f)    N)cdist)batch_probioubbox_ioa)check_requirementszlap>=0.5.12cost_matrixthreshuse_lapc           	         U R                   S:X  aZ  [        R                  " S[        S9[	        [        U R                  S   5      5      [	        [        U R                  S   5      5      4$ U(       a{  [        R                  " U SUS9u  p4n[        U5       VVs/ s H  u  pgUS:  d  M  Xg/PM     nnn[        R                  " US:  5      S   n	[        R                  " US:  5      S   n
GOh[        R                  R                  U 5      u  pE[        R                  " [        [        U5      5       Vs/ s H  oXK   X[   4   U::  d  M  XK   X[   /PM     sn5      n[        U5      S:X  aY  [!        [        R"                  " U R                  S   5      5      n	[!        [        R"                  " U R                  S   5      5      n
O[!        [%        [        R"                  " U R                  S   5      5      [%        USS2S4   5      -
  5      n	[!        [%        [        R"                  " U R                  S   5      5      [%        USS2S4   5      -
  5      n
XU
4$ s  snnf s  snf )ac  
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 (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      dtype   T)extend_cost
cost_limitN)sizenpemptyinttuplerangeshapelaplapjv	enumeratewherescipyoptimizelinear_sum_assignmentasarraylenlistarange	frozenset)r   r   r	   _xyixmxmatchesunmatched_aunmatched_bis               ]/home/james-whalen/.local/lib/python3.13/site-packages/ultralytics/trackers/utils/matching.pylinear_assignmentr.      s   & 1xxc*E%8I8I!8L2M,NPUV[\g\m\mno\pVqPrrr ))KTfMa*3A,B,"'8B8,Bhhq1uoa(hhq1uoa( ~~33K@**E#a&MgMqQRQUWXW[Q[E\`fEflqtQTlMghw<1ryy):):1)=>?Kryy):):1)=>?Ky;3D3DQ3G)HIIV]^_ab^bVcLddeKy;3D3DQ3G)HIIV]^_ab^bVcLddeK,, C hs   I)I4I
Iatracksbtracksreturnc                    U (       a"  [        U S   [        R                  5      (       d)  U(       a'  [        US   [        R                  5      (       a  U nUnOhU  Vs/ s H'  oDR                  b  UR                  OUR
                  PM)     nnU Vs/ s H'  oDR                  b  UR                  OUR
                  PM)     nn[        R                  " [        U5      [        U5      4[        R                  S9n[        U5      (       a  [        U5      (       a  [        US   5      S:X  as  [        US   5      S:X  aa  [        [        R                  " U[        R                  S9[        R                  " U[        R                  S95      R                  5       nSU-
  $ [        [        R                  " U[        R                  S9[        R                  " U[        R                  S9SS9nSU-
  $ s  snf s  snf )ac  
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   r      T)iour   )
isinstancer   ndarrayanglexywhaxyxyzerosr    float32r   ascontiguousarraynumpyr   )r/   r0   atlbrsbtlbrstrackiouss         r-   iou_distancerB   @   sz   " :gaj"**55ZPWXYPZ\^\f\fEgEgV]^V]U!8%++ejjHV]^V]^V]U!8%++ejjHV]^88S[#f+.bjjAD
6{{s6{{vay>Q3vay>Q#6 $$V2::>$$V2::> eg  t8O $$V2::>$$V2::>D
 t8O! _^s   .G..G3tracks
detectionsmetricc                    [         R                  " [        U 5      [        U5      4[         R                  S9nUR                  S:X  a  U$ [         R
                  " U Vs/ s H  oDR                  PM     sn[         R                  S9n[         R
                  " U  Vs/ s H  oDR                  PM     sn[         R                  S9n[         R                  " S[        XeU5      5      nU$ s  snf s  snf )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   g        )
r   r:   r    r;   r   r   	curr_featsmooth_featmaximumr   )rC   rD   rE   r   r@   det_featurestrack_featuress          r-   embedding_distancerL   h   s    & ((CKZ9LK1::JGJ5JGrzzZL ZZ Gu!2!2 GrzzZN**S%f"MNK H !Hs   C'C,c                    U R                   S:X  a  U $ SU -
  n[        R                  " U Vs/ s H  o3R                  PM     sn5      n[        R                  " USS9R                  U R                  S   SS9nX$-  nSU-
  $ s  snf )ac  
Fuse 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   )axis)r   r   arrayscoreexpand_dimsrepeatr   )r   rD   iou_simdet
det_scoresfuse_sims         r-   
fuse_scorerW      s    " 1+oG
;
99
;<J
3::;;L;LQ;OVW:XJ#Hx< <s   B)T)cosine)r=   r   r   scipy.spatial.distancer   ultralytics.utils.metricsr   r   r   __version__ImportErrorAssertionErrorAttributeErrorultralytics.utils.checksr   r6   floatboolr.   r!   rB   strrL   rW        r-   <module>re      s      ( =???)-2:: )-u )-t )-X%$ % %"** %Pt  s RTR\R\ <BJJ D RZZ s 	^^4 ;}%	s   B B32B3