
    hh              	       T   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 	 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y# e
eef$ r d dlmZ  ed       d dlZY {w xY w)    N)cdist)batch_probioubbox_ioa)check_requirementszlap>=0.5.12cost_matrixthreshuse_lapc           	         | j                   dk(  r\t        j                  dt              t	        t        | j                  d               t	        t        | j                  d               fS |ryt        j                  | d|      \  }}}t        |      D cg c]  \  }}|dk\  s||g }}}t        j                  |dk        d   }	t        j                  |dk        d   }
nct        j                  j                  |       \  }}t        j                  t        t        |            D cg c]  }| ||   ||   f   |k  s||   ||   g c}      }t        |      dk(  rWt!        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 c c}}w c c}w )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 (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               a/var/www/html/dev/engine/venv/lib/python3.12/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1a*3A,BB"'B8BBhhq1uoa(hhq1uoa( ~~33K@1**E#a&Mgq[QRSTQUWXYZW[Q[E\`fEfqtQqTl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K,, C hs   I&I.IIatracksbtracksreturnc                    | rt        | d   t        j                        s|r"t        |d   t        j                        r| }|}nb| D cg c]&  }|j                  |j                  n|j
                  ( }}|D cg c]&  }|j                  |j                  n|j
                  ( }}t        j                  t        |      t        |      ft        j                        }t        |      rt        |      rt        |d         dk(  rvt        |d         dk(  ret        t        j                  |t        j                        t        j                  |t        j                              j                         }d|z
  S t        t        j                  |t        j                        t        j                  |t        j                        d      }d|z
  S c c}w c c}w )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   r      T)iour   )
isinstancer   ndarrayanglexywhaxyxyzerosr    float32r   ascontiguousarraynumpyr   )r/   r0   atlbrsbtlbrstrackiouss         r-   iou_distancerB   @   sn   " :gaj"**5ZPWXYPZ\^\f\fEgV]^U!8%++ejjH^^V]^U!8%++ejjH^^88S[#f+.bjjAD
6{s6{vay>Q3vay>Q#6 $$V2::>$$V2::> eg  t8O $$V2::>$$V2::>D
 t8O! _^s   +G9+Gtracks
detectionsmetricc                    t        j                  t        |       t        |      ft         j                        }|j                  dk(  r|S t        j
                  |D cg c]  }|j                   c}t         j                        }t        j
                  | D cg c]  }|j                   c}t         j                        }t        j                  dt        |||            }|S c c}w c c}w )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G5uGrzzZL ZZ Gu!2!2 GrzzZN**S%f"MNK H !Hs   C(C-c                    | j                   dk(  r| S d| z
  }t        j                  |D cg c]  }|j                   c}      }t        j                  |d      j                  | j                  d   d      }||z  }d|z
  S c c}w )a  
    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
;399;<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
 
B'&B'