Ë
    ¼Ó^j=  ã                  óÜ  — 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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mZ d d	lmZ ej0                  Zd
Z G d„ de«      Zej8                  f	 	 	 	 	 	 	 d d„Z	 	 	 	 	 	 	 	 d!d„Zd"d„Zej8                  f	 	 	 	 	 	 	 	 	 d#d„Z d$d%d„Z!d&d„Z" ee"dd¬«      d&d„«       Z#	 	 	 	 	 	 d'd„Z$	 	 	 	 	 	 d(d„Z% G d„ d«      Z&d)d„Z'd*d„Z(d+d„Z)d,d„Z*d,d„Z+y)-é    )ÚannotationsN)ÚEnum)ÚAny)Ú
deprecatedÚvoid)ÚCLASS_NAME_DATA_FIELD)Ú
Detections)ÚColorÚColorPalette)ÚPositionéÿÿÿÿc                  ó.   — e Zd ZdZdZdZdZedd„«       Zy)ÚColorLookupaŽ  
    Enumeration class to define strategies for mapping colors to annotations.

    This enum supports three different lookup strategies:
        - `INDEX`: Colors are determined by the index of the detection within the scene.
        - `CLASS`: Colors are determined by the class label of the detected object.
        - `TRACK`: Colors are determined by the tracking identifier of the object.
    ÚindexÚclassÚtrackc                ó.   — t        t        d„ | «      «      S )Nc                ó   — | j                   S ©N)Úvalue)Úcs    úg/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/supervision/annotators/utils.pyú<lambda>z"ColorLookup.list.<locals>.<lambda>%   s
   €  !§'¡'€ ó    )ÚlistÚmap)Úclss    r   r   zColorLookup.list#   s   € ä”CÑ)¨3Ó/Ó0Ð0r   N)Úreturnú	list[str])	Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚINDEXÚCLASSÚTRACKÚclassmethodr   © r   r   r   r      s*   „ ñð €EØ€EØ€Eàò1ó ñ1r   r   c                ód  — |t        | «      k\  rt        d|› dt        | «      › �«      ‚t        |t        j                  «      rHt        |«      t        | «      k7  r#t        dt        |«      › dt        | «      › �«      ‚t        ||   «      S |t        j                  k(  r|S |t        j                  k(  r/| j                  €t        d«      ‚t        | j                  |   «      S |t        j                  k(  r/| j                  €t        d«      ‚t        | j                  |   «      S t        d|› �«      ‚)NzDetection index z+ is out of bounds for detections of length zLength of color lookup z% does not match length of detections zªCould not resolve color by class because Detections do not have class_id. If using an annotator, try setting color_lookup to sv.ColorLookup.INDEX or sv.ColorLookup.TRACK.z�Could not resolve color by track because Detections do not have tracker_id. Did you call tracker.update_with_detections(...) before annotating?z#Unsupported color lookup strategy: )ÚlenÚ
ValueErrorÚ
isinstanceÚnpÚndarrayÚintr   r$   r%   Úclass_idr&   Ú
tracker_id©Ú
detectionsÚdetection_idxÚcolor_lookups      r   Úresolve_color_idxr6   (   sK  € ð
 œ˜J›Ò'ÜØ˜}˜oð .9Ü9<¸Z»Ð8IðKó
ð 	
ô
 �,¤§
¡
Ô+Üˆ|Ó¤ J£Ò/ÜØ)¬#¨lÓ*;Ð)<ð =7Ü7:¸:³Ð6GðIóð ô �< Ñ.Ó/Ð/Ø	œ×*Ñ*Ò	*ØÐØ	œ×*Ñ*Ò	*Ø×ÑÐ&Üð(óð ô �:×&Ñ& }Ñ5Ó6Ð6Ø	œ×*Ñ*Ò	*Ø× Ñ Ð(ÜðIóð ô
 �:×(Ñ(¨Ñ7Ó8Ð8Ü
Ð:¸<¸.ÐIÓ
JÐJr   c                óØ  — | \  }}|\  }}|t         j                  k(  r|||z
  ||z   |fS |t         j                  k(  r||z
  ||z
  ||fS |t         j                  k(  r||dz  z
  ||z
  ||dz  z   |fS |t         j                  k(  s|t         j
                  k(  r||dz  z
  ||dz  z
  ||dz  z   ||dz  z   fS |t         j                  k(  r||||z   ||z   fS |t         j                  k(  r||z
  ||||z   fS |t         j                  k(  r||dz  z
  |||dz  z   ||z   fS |t         j                  k(  r||z
  ||dz  z
  |||dz  z   fS |t         j                  k(  r|||dz  z
  ||z   ||dz  z   fS y )Né   )r   ÚTOP_LEFTÚ	TOP_RIGHTÚ
TOP_CENTERÚCENTERÚCENTER_OF_MASSÚBOTTOM_LEFTÚBOTTOM_RIGHTÚBOTTOM_CENTERÚCENTER_LEFTÚCENTER_RIGHT)Úcenter_coordinatesÚtext_whÚpositionÚcenter_xÚcenter_yÚtext_wÚtext_hs          r   Úresolve_text_background_xyxyrJ   P   sÿ  € ð
 ,Ñ€HˆhØ�N€FˆFà”8×$Ñ$Ò$Ø˜ FÑ*¨H°vÑ,=¸xÐGÐGØ	”X×'Ñ'Ò	'Ø˜&Ñ  (¨VÑ"3°X¸xÐGÐGØ	”X×(Ñ(Ò	(à�v ‘{Ñ"Ø�vÑØ�v ‘{Ñ"Øð	
ð 	
ð 
”X—_‘_Ò	$¨´H×4KÑ4KÒ(Kà�v ‘{Ñ"Ø�v ‘{Ñ"Ø�v ‘{Ñ"Ø�v ‘{Ñ"ð	
ð 	
ð 
”X×)Ñ)Ò	)Ø˜ 8¨fÑ#4°hÀÑ6GÐGÐGØ	”X×*Ñ*Ò	*Ø˜&Ñ  (¨H°hÀÑ6GÐGÐGØ	”X×+Ñ+Ò	+à�v ‘{Ñ"ØØ�v ‘{Ñ"Ø�vÑð	
ð 	
ð 
”X×)Ñ)Ò	)à�vÑØ�v ‘{Ñ"ØØ�v ‘{Ñ"ð	
ð 	
ð 
”X×*Ñ*Ò	*àØ�v ‘{Ñ"Ø�vÑØ�v ‘{Ñ"ð	
ð 	
ð 
+r   c                óH   — t        | t        «      r| j                  |«      S | S r   )r,   r   Úby_idx©ÚcolorÚidxs     r   Úget_color_by_indexrP   …   s    € Ü�%œÔ&Ø�|‰|˜CÓ Ð Ø€Lr   c                óœ   — t        |||¬«      }t        |t        «      r"|t        j                  k(  r|t        k(  rt
        S t        | |¬«      S )Nr2   rM   )r6   r,   r   r&   ÚPENDING_TRACK_IDÚPENDING_TRACK_COLORrP   )rN   r3   r4   r5   rO   s        r   Úresolve_colorrT   ‹   sM   € ô ØØ#Ø!ô€Cô 	�<¤Ô-ØœK×-Ñ-Ò-ØÔ#Ò#ä"Ð"Ü E¨sÔ3Ð3r   c                ó`  — | sdgS t        | t        «      st        | «      } |€| j                  «       xs dgS |dk  rt        d«      ‚| j	                  d«      }g }|D ]I  }|dk(  r|j                  d«       Œt        j                  ||ddd¬«      }|j                  |xs dg«       ŒK |xs dgS )a.  
    Wrap `text` to the specified maximum line length, respecting existing
    newlines. Falls back to str() if `text` is not already a string.

    Args:
        text: The text (or object) to wrap.
        max_line_length: Maximum width for each wrapped line.

    Returns:
        Wrapped lines.
    Ú r   z*max_line_length must be a positive integerú
TF)ÚwidthÚbreak_long_wordsÚreplace_whitespaceÚdrop_whitespace)	r,   ÚstrÚ
splitlinesr+   ÚsplitÚappendÚtextwrapÚwrapÚextend)ÚtextÚmax_line_lengthÚ
paragraphsÚ	all_linesÚ	paragraphÚwrappeds         r   Ú	wrap_textri   Ÿ   sË   € ñ Øˆtˆä�dœCÔ Ü�4‹yˆàÐØ�‰Ó Ò( R DÐ(à˜!ÒÜÐEÓFÐFà—‘˜DÓ!€JØ€Iàò *ˆ	Ø˜Š?Ø×Ñ˜RÔ Øä—-‘-ØØ!Ø!Ø$Ø ô
ˆð 	×Ñ˜š R DÕ)ð*ð Ò˜˜Ðr   c                ó€   — | �<t        | «      t        |«      k7  r$t        dt        | «      › dt        |«      › d�«      ‚yy)ae  
    Validates that the number of provided labels matches the number of detections.

    Args:
        labels: A list of labels, one for each detection. Can
            be None.
        detections: The detections to be labeled.

    Raises:
        ValueError: If `labels` is not None and its length does not match the number
            of detections.
    NzThe number of labels (z+) does not match the number of detections (z.). Each detection should have exactly 1 label.)r*   r+   ©Úlabelsr3   s     r   Ú_validate_labelsrm   Í   sR   € ð Ðœc &›k¬S°«_Ò<ÜØ$¤S¨£[ Mð 2%Ü%(¨£_Ð$5ð 6+ð,ó
ð 	
ð =Ðr   z0.29.0z0.32.0)ÚtargetÚdeprecated_inÚ	remove_inc                ó   — t        | |«       y r   )r   rk   s     r   Úvalidate_labelsrr   â   s   € ô 	ˆ�Õr   c                ób  — |�|S g }t        t        | «      «      D ]‘  }t        | j                  v r/|j	                  t        | j                  t           |   «      «       ŒD| j                  �(|j	                  t        | j                  |   «      «       Œx|j	                  t        |«      «       Œ“ |S )aÞ  
    Retrieves the text labels for the detections.

    If `custom_labels` are provided, they are used. Otherwise, the labels are
    extracted from the `detections` object, prioritizing the 'class_name' field,
    then the `class_id`, and finally using the detection index as a string.

    Args:
        detections: The detections to get labels for.
        custom_labels: An optional list of custom labels.

    Returns:
        A list of text labels for each detection.
    )Úranger*   r   Údatar_   r\   r0   )r3   Úcustom_labelsrl   rO   s       r   Úget_labels_textrw   ë   s˜   € ð" Ð ØÐà€FÜ”S˜“_Ó%ò $ˆÜ  J§O¡OÑ3Ø�M‰Mœ#˜jŸo™oÔ.CÑDÀSÑIÓJÕKØ× Ñ Ð,Ø�M‰Mœ#˜j×1Ñ1°#Ñ6Ó7Õ8à�M‰Mœ#˜c›(Õ#ð$ð €Mr   c                ó  — t        j                  | «      }|\  }}|dd…df   dk  }||ddd…fxx   ||dd…f   z  cc<   | |dd…df   |kD  z  }|||df   z
  }||ddd…fxx   |dd…t         j                  f   z  cc<   |dd…df   dk  }||ddd…fxx   ||dd…f   z  cc<   | |dd…df   |kD  z  }	|||	df   z
  }
||	ddd…fxx   |
dd…t         j                  f   z  cc<   |j                  t         j                  «      S )a8  
    Shifts `label` bounding boxes into the frame so that they are fully contained
    within the given resolution, prioritizing the top/left edge.
    Unlike `clip_boxes`, this function does not crop boxes.
    It moves them entirely if they exceed the frame boundaries.

    Args:
        xyxy: A numpy array of shape `(N, 4)` where each
            row corresponds to a bounding box in the format
            `(x_min, y_min, x_max, y_max)`.
        resolution_wh: A tuple `(width, height)`
            representing the resolution of the frame.

    Returns:
        A numpy array of shape `(N, 4)` with boxes shifted into frame.

    Examples:
        ```pycon
        >>> import numpy as np
        >>> from supervision.annotators.utils import snap_boxes
        >>> xyxy = np.array([
        ...     [-10, 10, 30, 50],     # Off left edge
        ...     [310, 200, 350, 250],  # Off right edge
        ...     [100, -20, 150, 30],   # Off top edge
        ...     [200, 220, 250, 270],  # Off bottom edge
        ...     [-20, 10, 350, 50],    # Wider than frame (370 vs 320)
        ...     [10, -20, 30, 260]     # Taller than frame (280 vs 240)
        ... ])
        >>> resolution_wh = (320, 240)
        >>> snapped_boxes = snap_boxes(xyxy=xyxy, resolution_wh=resolution_wh)
        >>> snapped_boxes
        array([[  0.,  10.,  40.,  50.],
               [280., 190., 320., 240.],
               [100.,   0., 150.,  50.],
               [200., 190., 250., 240.],
               [  0.,  10., 370.,  50.],
               [ 10.,   0.,  30., 280.]], dtype=float32)

        ```
    Nr   é   r8   é   é   )r-   ÚcopyÚnewaxisÚastypeÚfloat32)ÚxyxyÚresolution_whÚresultrX   ÚheightÚleft_overflowÚright_overflowÚright_shiftÚtop_overflowÚbottom_overflowÚbottom_shifts              r   Ú
snap_boxesrŠ   
  sR  € ôX �W‰W�T‹]€FØ!�M€Eˆ6ð š1˜a˜4‘L 1Ñ$€MØ
ˆ=˜!˜A˜a˜%ÐÓ  F¨=¸!¸A¸#Ð+=Ñ$>Ñ>Ó à$�n¨²°1°©¸Ñ)=Ñ>€NØ˜& °Ð!2Ñ3Ñ3€KØ
ˆ>˜1˜Q˜q˜5Ð Ó! [²´B·J±J°Ñ%?Ñ?Ó!ð š!˜Q˜$‘< !Ñ#€LØ
ˆ<˜˜1˜Q˜ÐÓ 6¨,¸¸!¸Ð*;Ñ#<Ñ<Óà$�}¨²°1°©¸Ñ)>Ñ?€OØ˜F ?°AÐ#5Ñ6Ñ6€LØ
ˆ?˜A˜a ˜EÐ!Ó" l²1´b·j±j°=Ñ&AÑAÓ"à�=‰=œŸ™Ó$Ð$r   c                  óN   — e Zd Zddej                  f	 	 	 	 	 	 	 dd„Zdd„Zdd„Zy)	ÚTraceNr   c                ó  — || _         || _        || _        t        j                  g t
        ¬«      | _        t        j                  dt        j                  ¬«      | _	        t        j                  g t
        ¬«      | _
        y )N©Údtype)r   r8   )Úcurrent_frame_idÚmax_sizeÚanchorr-   Úarrayr/   Úframe_idÚemptyr   Úxyr1   )Úselfr‘   Ústart_frame_idr’   s       r   Ú__init__zTrace.__init__M  sT   € ð !/ˆÔØ ˆŒØˆŒäŸ™ ¬3Ô/ˆŒÜ—(‘(˜6¬¯©Ô4ˆŒÜŸ(™( 2¬SÔ1ˆ�r   c                óJ  — t        j                  t        |«      | j                  t        ¬«      }t        j
                  | j                  |g«      | _        t        j
                  | j                  |j                  | j                  «      g«      | _        |j                  €t        d«      ‚t        j
                  | j                  |j                  g«      | _
        t        j                  | j                  «      }| j                  �ˆd| j                  cxk  rt        |«      k  rjn ng| j                  | j                  z
  dz   }| j                  |k\  }| j                  |   | _        | j                  |   | _        | j                  |   | _
        | xj                  dz  c_        y )NrŽ   zNCould not put detections into Trace because Detections do not have tracker_id.r   rz   )r-   Úfullr*   r�   r/   Úconcatenater”   r–   Úget_anchors_coordinatesr’   r1   r+   Úuniquer‘   )r—   r3   r”   Úunique_frame_idÚmax_allowed_frame_idÚfiltering_masks         r   Úputz	Trace.put[  sF  € Ü)+¯©Ü�
‹O˜T×2Ñ2¼#ô*
ˆô Ÿ™¨¯©°xÐ'@ÓAˆŒÜ—.‘.à—‘Ø×2Ñ2°4·;±;Ó?ðó
ˆŒð × Ñ Ð(Üð5óð ô
 Ÿ.™.¨$¯/©/¸:×;PÑ;PÐ)QÓRˆŒäŸ)™) D§M¡MÓ2ˆà�=‰=Ð$¨¨T¯]©]Ô)Q¼SÀÓ=QÕ)QØ#'×#8Ñ#8¸4¿=¹=Ñ#HÈ1Ñ#LÐ Ø!Ÿ]™]Ð.BÑBˆNØ ŸM™M¨.Ñ9ˆDŒMØ—g‘g˜nÑ-ˆDŒGØ"Ÿo™o¨nÑ=ˆDŒOà×Ò Ñ"Ör   c                ó˜   — | j                   | j                  |k(     j                  «       j                  t        j
                  d¬«      }|S )NF)r|   )r–   r1   r|   r~   r-   r   )r—   r1   Úfiltereds      r   Úgetz	Trace.gety  sA   € à�G‰G�D—O‘O zÑ1Ñ2×7Ñ7Ó9×@Ñ@ÄÇÁÐRWÐ@ÓXð 	ð ˆr   )r‘   ú
int | Noner˜   r/   r’   r   r   ÚNone)r3   r	   r   r§   )r1   r/   r   ú%np.ndarray[Any, np.dtype[np.float32]])r    r!   r"   r   r<   r™   r¢   r¥   r(   r   r   rŒ   rŒ   L  sF   „ ð  $ØØ#Ÿ?™?ð	2àð2ð ð2ð ð	2ð
 
ó2ó#ô<r   rŒ   c                ód  — | j                  «       j                  d«      } t        | «      dk(  r| dz  } t        | «      dk7  rt        d| › �«      ‚	 t	        | dd d«      }t	        | dd	 d«      }t	        | d	d d«      }t	        | dd d«      }||||fS # t        $ r}t        d
| › �«      |‚d}~ww xY w)zö
    Converts a hex color string (e.g. "#FF00FF" or "#FF00FF80") to an RGBA tuple.

    Args:
        hex_color: A hex color string.

    Returns:
        RGBA values in range 0-255.

    Raises:
        ValueError: If the format is invalid.
    ú#é   ÚFFé   zInvalid hex color format: r   r8   é   r{   zInvalid hex digits in N)ÚstripÚlstripr*   r+   r/   )Ú	hex_colorÚrÚgÚbÚaÚexcs         r   Úhex_to_rgbar·   €  s×   € ð —‘Ó!×(Ñ(¨Ó-€IÜ
ˆ9ƒ~˜ÒØ�TÑˆ	Ü
ˆ9ƒ~˜ÒÜÐ5°i°[ÐAÓBÐBðHÜ�	˜!˜A� Ó#ˆÜ�	˜!˜A� Ó#ˆÜ�	˜!˜A� Ó#ˆÜ�	˜!˜A� Ó#ˆð ˆq�!�Qˆ<Ðøô ò HÜÐ1°)°Ð=Ó>ÀCÐGûðHús   Á<B Â	B/ÂB*Â*B/c                óv   — t        | «      dk7  st        d„ | D «       «      st        d«      ‚ dj                  | Ž S )a  
    Converts an RGBA tuple (0-255 each) to a hex color string.

    Args:
        rgba: RGBA values in range 0-255.

    Returns:
        Hex color string in the format "#RRGGBBAA".

    Raises:
        ValueError: If `rgba` is not a 4-tuple or contains values outside 0-255.
    r{   c              3  ó<   K  — | ]  }d |cxk  xr dk  nc –— Œ y­w)r   éÿ   Nr(   )Ú.0r   s     r   ú	<genexpr>zrgba_to_hex.<locals>.<genexpr>©  s   è ø€ Ò =°1  a¦¨3§ Ñ =ùs   ‚z1RGBA must be a 4-tuple with values between 0-255.z#{:02X}{:02X}{:02X}{:02X})r*   Úallr+   Úformat)Úrgbas    r   Úrgba_to_hexrÀ   œ  s<   € ô ˆ4ƒy�A‚~œSÑ =¸Ô =Ô=ÜÐLÓMÐMØ-Ð&×-Ñ-¨tÐ4Ð4r   c                ó\   — t        t        j                  d| j                  «       «      «      S )a#  
    Checks if a given string is a valid hex color.

    Args:
        hex_color: A hex color string with an optional leading "#". Supports
            6-digit (RGB) or 8-digit (RGBA) formats.

    Returns:
        True if the string is a valid 6- or 8-digit hex color, otherwise False.
    z!#?[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?)ÚboolÚreÚ	fullmatchr¯   )r±   s    r   Úis_valid_hexrÅ   ®  s"   € ô ”—‘ÐAÀ9Ç?Á?ÓCTÓUÓVÐVr   c                ó@   — t        dt        ||z
  || z
  «      dz  «      S )aÖ  
    Computes a blur kernel size proportional to the shorter side of a bounding box.

    Args:
        x1: Left edge of the bounding box.
        y1: Top edge of the bounding box.
        x2: Right edge of the bounding box.
        y2: Bottom edge of the bounding box.

    Returns:
        Kernel size as one-third of the shorter dimension, minimum 1.

    Examples:
        ```pycon
        >>> calculate_dynamic_kernel_size(0, 0, 90, 60)
        20

        ```
    rz   ry   ©ÚmaxÚmin©Úx1Úy1Úx2Úy2s       r   Úcalculate_dynamic_kernel_sizerÏ   ¼  ó%   € ô( ˆq”#�b˜2‘g˜r B™wÓ'¨1Ñ,Ó-Ð-r   c                ó@   — t        dt        ||z
  || z
  «      dz  «      S )aÒ  
    Computes a pixelation size proportional to the shorter side of a bounding box.

    Args:
        x1: Left edge of the bounding box.
        y1: Top edge of the bounding box.
        x2: Right edge of the bounding box.
        y2: Bottom edge of the bounding box.

    Returns:
        Pixel size as one-half of the shorter dimension, minimum 1.

    Examples:
        ```pycon
        >>> calculate_dynamic_pixel_size(0, 0, 90, 60)
        30

        ```
    rz   r8   rÇ   rÊ   s       r   Úcalculate_dynamic_pixel_sizerÒ   Ó  rÐ   r   )r3   r	   r4   r/   r5   ú"ColorLookup | npt.NDArray[np.int_]r   r/   )rC   útuple[int, int]rD   rÔ   rE   r   r   útuple[int, int, int, int])rN   úColor | ColorPaletterO   r/   r   r
   )
rN   rÖ   r3   r	   r4   r/   r5   rÓ   r   r
   r   )rc   r   rd   r¦   r   r   )rl   úlist[str] | Noner3   r	   r   r§   )r3   r	   rv   r×   r   r   )r€   r¨   r�   rÔ   r   r¨   )r±   r\   r   rÕ   )r¿   rÕ   r   r\   )r±   r\   r   rÂ   )
rË   r/   rÌ   r/   rÍ   r/   rÎ   r/   r   r/   ),Ú
__future__r   rÃ   r`   Úenumr   Útypingr   Únumpyr-   Únumpy.typingÚnptÚ	deprecater   r   Úsupervision.configr   Úsupervision.detection.corer	   Úsupervision.draw.colorr
   r   Úsupervision.geometry.corer   ÚGREYrS   rR   r   r%   r6   rJ   rP   rT   ri   rm   rr   rw   rŠ   rŒ   r·   rÀ   rÅ   rÏ   rÒ   r(   r   r   ú<module>rä      s}  ðÝ "ã 	Û Ý Ý ã Ý ß &å 4Ý 1ß 6Ý .à—j‘jÐ ØÐ ô1�$ô 1ð, 8C×7HÑ7Hð%KØð%Kàð%Kð 5ð%Kð 	ó	%KðP2
Ø'ð2
àð2
ð ð2
ð ó	2
ójð 8C×7HÑ7Hð	4Øð4àð4ð ð4ð 5ð	4ð
 ó4ô(+ó\
ñ* ØØØôò
óð
ðØðØ+;ðàóð>?%Ø
/ð?%à"ð?%ð +ó?%÷D1ñ 1óhó85ó$Wó.ô..r   