Ë
    FêñiQf  ã                  ó’  — d dl mZ d dlZd dlZd dlZd dlZd dlZd dlZd dl	Z	d dl
mc mZ d dlmZ  G d„ dej                   «      Zd!d"d„Z	 	 	 d#	 	 	 	 	 	 	 	 	 	 	 	 	 d$d„Zd%d„Zd	„ Zd
„ Zd„ Zd„ Zd&d'd„Zd(d)d„Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Z d„ Z!d*d+d„Z"d,d„Z#d-d.d„Z$d„ Z%	 	 d/	 	 	 	 	 	 	 	 	 d0d„Z&d1d2d„Z'd„ Z(d3d4d„Z)d5d„Z*d„ Z+d „ Z,y)6é    )ÚannotationsN)ÚNOT_MACOS14c                  ó2   — e Zd ZdZdd	d„Zd„ Zd„ Zd„ Zd„ Zy)
ÚProfilea7  Ultralytics Profile class for timing code execution.

    Use as a decorator with @Profile() or as a context manager with 'with Profile():'. Provides accurate timing
    measurements with CUDA synchronization support for GPU operations.

    Attributes:
        t (float): Accumulated time in seconds.
        device (torch.device): Device used for model inference.
        cuda (bool): Whether CUDA is being used for timing synchronization.

    Examples:
        Use as a context manager to time code execution
        >>> with Profile(device=device) as dt:
        ...     pass  # slow operation here
        >>> print(dt)  # prints "Elapsed time is 9.5367431640625e-07 s"

        Use as a decorator to time function execution
        >>> @Profile()
        ... def slow_function():
        ...     time.sleep(0.1)
    Nc                óx   — || _         || _        t        |xr t        |«      j	                  d«      «      | _        y)zÞInitialize the Profile class.

        Args:
            t (float): Initial accumulated time in seconds.
            device (torch.device, optional): Device used for model inference to enable CUDA synchronization.
        ÚcudaN)ÚtÚdeviceÚboolÚstrÚ
startswithr   )Úselfr	   r
   s      úW/var/www/pod-logistic/pod-ai/venv/lib/python3.12/site-packages/ultralytics/utils/ops.pyÚ__init__zProfile.__init__)   s2   € ð ˆŒØˆŒÜ˜ÒB¤C¨£K×$:Ñ$:¸6Ó$BÓCˆ�	ó    c                ó0   — | j                  «       | _        | S )zStart timing.)ÚtimeÚstart©r   s    r   Ú	__enter__zProfile.__enter__4   s   € à—Y‘Y“[ˆŒ
Øˆr   c                ó†   — | j                  «       | j                  z
  | _        | xj                  | j                  z  c_        y)zStop timing.N)r   r   Údtr	   )r   ÚtypeÚvalueÚ	tracebacks       r   Ú__exit__zProfile.__exit__9   s*   € à—)‘)“+ §
¡
Ñ*ˆŒØ�Š�$—'‘'ÑŽr   c                ó"   — d| j                   › d�S )zIReturn a human-readable string representing the accumulated elapsed time.zElapsed time is z s)r	   r   s    r   Ú__str__zProfile.__str__>   s   € à! $§&¡& ¨Ð,Ð,r   c                ó”   — | j                   r)t        j                   j                  | j                  «       t	        j
                  «       S )z9Get current time with CUDA synchronization if applicable.)r   ÚtorchÚsynchronizer
   r   Úperf_counterr   s    r   r   zProfile.timeB   s.   € à�9Š9Ü�J‰J×"Ñ" 4§;¡;Ô/Ü× Ñ Ó"Ð"r   )ç        N)r	   Úfloatr
   ztorch.device | None)	Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r   © r   r   r   r      s!   „ ñô,	Dòò
ò
-ó#r   r   c                ó˜  — | j                   \  }}t        j                  |j                  «       dk  |j                  «       dk  |j	                  «       |kD  |j	                  «       |kD  g«      j                  «       dk\  r$|j                  d|«      }|j                  d|«      }|dkD  |dkD  z  ||k  z  ||k  z  }||   }||   }t        |«      r]t        j                  |j                  «       |j                  «       |j	                  «       |j	                  «       g| j                  ¬«      S t        j                  d| j                  ¬«      S )a$  Convert segment coordinates to bounding box coordinates.

    Converts a single segment label to a box label by finding the minimum and maximum x and y coordinates. Applies
    inside-image constraint and clips coordinates when necessary.

    Args:
        segment (np.ndarray): Segment coordinates in format (N, 2) where N is number of points.
        width (int): Width of the image in pixels.
        height (int): Height of the image in pixels.

    Returns:
        (np.ndarray): Bounding box coordinates in xyxy format [x1, y1, x2, y2].
    r   é   ©Údtypeé   )
ÚTÚnpÚarrayÚminÚmaxÚsumÚclipÚanyr-   Úzeros)ÚsegmentÚwidthÚheightÚxÚyÚinsides         r   Úsegment2boxr>   I   s  € ð �9‰9�D€A€qä	‡x�x�—‘“˜1‘˜aŸe™e›g¨™k¨1¯5©5«7°U©?¸A¿E¹E»GÀfÑ<LÐMÓN×RÑRÓTÐXYÒYØ�F‰F�1�eÓˆØ�F‰F�1�fÓˆØ�!‰e˜˜A™Ñ ! e¡)Ñ,°°F±
Ñ;€FØ	ˆ&‰	€AØ	ˆ&‰	€Aô ˆqŒ6ô 	�‰�!—%‘%“'˜1Ÿ5™5›7 A§E¡E£G¨Q¯U©U«WÐ5¸W¿]¹]ÔKðô �X‰X�a˜wŸ}™}Ô-ðr   c                ó®  — |€kt        | d   |d   z  | d   |d   z  «      }t        | d   t        |d   |z  «      z
  dz  dz
  «      }t        | d   t        |d   |z  «      z
  dz  dz
  «      }n|d   d   }|d   \  }}|r6|dxx   |z  cc<   |dxx   |z  cc<   |s|dxx   |z  cc<   |d	xx   |z  cc<   |d
dd…fxx   |z  cc<   |r|S t        ||«      S )aV  Rescale bounding boxes from one image shape to another.

    Rescales bounding boxes from img1_shape to img0_shape, accounting for padding and aspect ratio changes. Supports
    both xyxy and xywh box formats.

    Args:
        img1_shape (tuple[int, int]): Shape of the source image (height, width).
        boxes (torch.Tensor | np.ndarray): Bounding boxes to rescale in format (N, 4).
        img0_shape (tuple[int, int]): Shape of the target image (height, width).
        ratio_pad (tuple, optional): Tuple of (ratio, pad) for scaling. If None, calculated from image shapes.
        padding (bool): Whether boxes are based on YOLO-style augmented images with padding.
        xywh (bool): Whether box format is xywh (True) or xyxy (False).

    Returns:
        (torch.Tensor | np.ndarray): Rescaled bounding boxes in the same format as input.
    Nr   é   é   çš™™™™™¹?©.r   ©.r@   ©.rA   ©.r+   .r.   )r2   ÚroundÚ
clip_boxes)	Ú
img1_shapeÚboxesÚ
img0_shapeÚ	ratio_padÚpaddingÚxywhÚgainÚpad_xÚpad_ys	            r   Úscale_boxesrR   f   s  € ð0 ÐÜ�:˜a‘= :¨a¡=Ñ0°*¸Q±-À*ÈQÁ-Ñ2OÓPˆÜ�z !‘}¤u¨Z¸©]¸TÑ-AÓ'BÑBÀaÑGÈ#ÑMÓNˆÜ�z !‘}¤u¨Z¸©]¸TÑ-AÓ'BÑBÀaÑGÈ#ÑMÓN‰à˜‰|˜A‰ˆØ  ‘|‰ˆˆuáØˆf‹˜Ñ‹Øˆf‹˜Ñ‹ÙØ�&‹M˜UÑ"‹MØ�&‹M˜UÑ"‹MØ	ˆ#ˆr�ˆrˆ'ƒN�dÑƒNÙˆ5Ð;œj¨°
Ó;Ð;r   c                óž   — t        |t        j                  «      rt        |j	                  «       «      }t        j                  | |z  «      |z  S )zýReturn the nearest number that is divisible by the given divisor.

    Args:
        x (int): The number to make divisible.
        divisor (int | torch.Tensor): The divisor.

    Returns:
        (int): The nearest number divisible by the divisor.
    )Ú
isinstancer    ÚTensorÚintr3   ÚmathÚceil)r;   Údivisors     r   Úmake_divisiblerZ   �   s:   € ô �'œ5Ÿ<™<Ô(Ü�g—k‘k“mÓ$ˆÜ�9‰9�Q˜‘[Ó! GÑ+Ð+r   c                óF  — |dd \  }}t        | t        j                  «      r¾t        rV| d   j	                  d|«       | d   j	                  d|«       | d   j	                  d|«       | d   j	                  d|«       | S | d   j                  d|«      | d<   | d   j                  d|«      | d<   | d   j                  d|«      | d<   | d   j                  d|«      | d<   | S | dddgf   j                  d|«      | dddgf<   | dd	d
gf   j                  d|«      | dd	d
gf<   | S )a  Clip bounding boxes to image boundaries.

    Args:
        boxes (torch.Tensor | np.ndarray): Bounding boxes to clip.
        shape (tuple): Image shape as HWC or HW (supports both).

    Returns:
        (torch.Tensor | np.ndarray): Clipped bounding boxes.
    NrA   rC   r   rD   rE   rF   .r@   r+   ©rT   r    rU   r   Úclamp_Úclampr5   )rJ   ÚshapeÚhÚws       r   rH   rH   Ÿ   sK  € ð ��!ˆ9�D€A€qÜ�%œŸ™Ô&ÝØ�&‰M× Ñ   AÔ&Ø�&‰M× Ñ   AÔ&Ø�&‰M× Ñ   AÔ&Ø�&‰M× Ñ   AÔ&ð €Lð " &™M×/Ñ/°°1Ó5ˆE�&‰MØ! &™M×/Ñ/°°1Ó5ˆE�&‰MØ! &™M×/Ñ/°°1Ó5ˆE�&‰MØ! &™M×/Ñ/°°1Ó5ˆE�&‰Mð €Lð # 3¨¨A¨ ;Ñ/×4Ñ4°Q¸Ó:ˆˆc�A�q�6ˆkÑØ" 3¨¨A¨ ;Ñ/×4Ñ4°Q¸Ó:ˆˆc�A�q�6ˆkÑØ€Lr   c                ór  — |dd \  }}t        | t        j                  «      rdt        r,| d   j	                  d|«       | d   j	                  d|«       | S | d   j                  d|«      | d<   | d   j                  d|«      | d<   | S | d   j                  d|«      | d<   | d   j                  d|«      | d<   | S )a	  Clip line coordinates to image boundaries.

    Args:
        coords (torch.Tensor | np.ndarray): Line coordinates to clip.
        shape (tuple): Image shape as HWC or HW (supports both).

    Returns:
        (torch.Tensor | np.ndarray): Clipped coordinates.
    NrA   rC   r   rD   r\   )Úcoordsr_   r`   ra   s       r   Úclip_coordsrd   »   sË   € ð ��!ˆ9�D€A€qÜ�&œ%Ÿ,™,Ô'ÝØ�6‰N×!Ñ! ! QÔ'Ø�6‰N×!Ñ! ! QÔ'ð €Mð $ F™^×1Ñ1°!°QÓ7ˆF�6‰NØ# F™^×1Ñ1°!°QÓ7ˆF�6‰Nð €Mð   ™×,Ñ,¨Q°Ó2ˆˆv‰Ø ™×,Ñ,¨Q°Ó2ˆˆv‰Ø€Mr   c                óâ   — | j                   d   dk(  sJ d| j                   › �«       ‚t        | «      }| d   | d   | d   | d   f\  }}}}||z   dz  |d<   ||z   dz  |d<   ||z
  |d<   ||z
  |d<   |S )	a�  Convert bounding box coordinates from (x1, y1, x2, y2) format to (x, y, width, height) format where (x1, y1) is
    the top-left corner and (x2, y2) is the bottom-right corner.

    Args:
        x (np.ndarray | torch.Tensor): Input bounding box coordinates in (x1, y1, x2, y2) format.

    Returns:
        (np.ndarray | torch.Tensor): Bounding box coordinates in (x, y, width, height) format.
    éÿÿÿÿr.   ú9input shape last dimension expected 4 but input shape is rC   rD   rE   rF   rA   ©r_   Ú
empty_like)r;   r<   Úx1Úy1Úx2Úy2s         r   Ú	xyxy2xywhrn   Ó   sŸ   € ð �7‰7�2‰;˜!ÒÐbÐXÐYZ×Y`ÑY`ÐXaÐbÓbÐÜ�1‹€AØ�v‘Y  &¡	¨1¨V©9°a¸±iÐ?�N€BˆˆB�Ø�b‘˜A‘€A€f�IØ�b‘˜A‘€A€f�IØ�R‘€A€f�IØ�R‘€A€f�IØ€Hr   c                óÂ   — | j                   d   dk(  sJ d| j                   › �«       ‚t        | «      }| ddd…f   }| ddd…f   dz  }||z
  |ddd…f<   ||z   |ddd…f<   |S )aÁ  Convert bounding box coordinates from (x, y, width, height) format to (x1, y1, x2, y2) format where (x1, y1) is
    the top-left corner and (x2, y2) is the bottom-right corner. Note: ops per 2 channels faster than per channel.

    Args:
        x (np.ndarray | torch.Tensor): Input bounding box coordinates in (x, y, width, height) format.

    Returns:
        (np.ndarray | torch.Tensor): Bounding box coordinates in (x1, y1, x2, y2) format.
    rf   r.   rg   .NrA   rh   )r;   r<   ÚxyÚwhs       r   Ú	xywh2xyxyrr   ç   s‰   € ð �7‰7�2‰;˜!ÒÐbÐXÐYZ×Y`ÑY`ÐXaÐbÓbÐÜ�1‹€AØ	
ˆ3���ˆ7‰€BØ	
ˆ3�‘ˆ7‰�a‰€BØ�b‘€A€cˆ2ˆAˆ2€g�JØ�b‘€A€cˆ1‰2€g�JØ€Hr   c                ó  — | j                   d   dk(  sJ d| j                   › �«       ‚t        | «      }| d   | d   | d   | d   f\  }}}}	|dz  |	dz  }}
|||
z
  z  |z   |d<   |||z
  z  |z   |d<   |||
z   z  |z   |d<   |||z   z  |z   |d<   |S )	aÈ  Convert normalized bounding box coordinates to pixel coordinates.

    Args:
        x (np.ndarray | torch.Tensor): Normalized bounding box coordinates in (x, y, w, h) format.
        w (int): Image width in pixels.
        h (int): Image height in pixels.
        padw (int): Padding width in pixels.
        padh (int): Padding height in pixels.

    Returns:
        (np.ndarray | torch.Tensor): Bounding box coordinates in (x1, y1, x2, y2) format.
    rf   r.   rg   rC   rD   rE   rF   rA   rh   )r;   ra   r`   ÚpadwÚpadhr<   ÚxcÚycÚxwÚxhÚhalf_wÚhalf_hs               r   Ú
xywhn2xyxyr|   ú   sÐ   € ð �7‰7�2‰;˜!ÒÐbÐXÐYZ×Y`ÑY`ÐXaÐbÓbÐÜ�1‹€AØ�v‘Y  &¡	¨1¨V©9°a¸±iÐ?�N€BˆˆB�Ø˜!‘V˜R !™VˆF€FØ�R˜&‘[Ñ! DÑ(€A€f�IØ�R˜&‘[Ñ! DÑ(€A€f�IØ�R˜&‘[Ñ! DÑ(€A€f�IØ�R˜&‘[Ñ! DÑ(€A€f�IØ€Hr   c                ó&  — |rt        | ||z
  ||z
  f«      } | j                  d   dk(  sJ d| j                  › �«       ‚t        | «      }| d   | d   | d   | d   f\  }}}}	||z   dz  |z  |d<   ||	z   dz  |z  |d<   ||z
  |z  |d<   |	|z
  |z  |d<   |S )	a`  Convert bounding box coordinates from (x1, y1, x2, y2) format to normalized (x, y, width, height) format. x, y,
    width and height are normalized to image dimensions.

    Args:
        x (np.ndarray | torch.Tensor): Input bounding box coordinates in (x1, y1, x2, y2) format.
        w (int): Image width in pixels.
        h (int): Image height in pixels.
        clip (bool): Whether to clip boxes to image boundaries.
        eps (float): Minimum value for box width and height.

    Returns:
        (np.ndarray | torch.Tensor): Normalized bounding box coordinates in (x, y, width, height) format.
    rf   r.   rg   rC   rD   rE   rF   rA   )rH   r_   ri   )
r;   ra   r`   r5   Úepsr<   rj   rk   rl   rm   s
             r   Ú
xyxy2xywhnr     sÍ   € ñ Ü�q˜1˜s™7 A¨¡GÐ,Ó-ˆØ�7‰7�2‰;˜!ÒÐbÐXÐYZ×Y`ÑY`ÐXaÐbÓbÐÜ�1‹€AØ�v‘Y  &¡	¨1¨V©9°a¸±iÐ?�N€BˆˆB�Ø�r‘'˜Q‘ !Ñ#€A€f�IØ�r‘'˜Q‘ !Ñ#€A€f�IØ�b‘˜A‘€A€f�IØ�b‘˜A‘€A€f�IØ€Hr   c                óÈ   — t        | t        j                  «      r| j                  «       nt	        j
                  | «      }| d   | d   dz  z
  |d<   | d   | d   dz  z
  |d<   |S )a(  Convert bounding box format from [x, y, w, h] to [x1, y1, w, h] where x1, y1 are top-left coordinates.

    Args:
        x (np.ndarray | torch.Tensor): Input bounding box coordinates in xywh format.

    Returns:
        (np.ndarray | torch.Tensor): Bounding box coordinates in ltwh format.
    rC   rE   rA   rD   rF   ©rT   r    rU   Úcloner0   Úcopy©r;   r<   s     r   Ú	xywh2ltwhr…   ,  ó_   € ô   ¤5§<¡<Ô0ˆ�‰Œ	´b·g±g¸a³j€AØ�&‘	˜A˜f™I¨™MÑ)€A€f�IØ�&‘	˜A˜f™I¨™MÑ)€A€f�IØ€Hr   c                ó¼   — t        | t        j                  «      r| j                  «       nt	        j
                  | «      }| d   | d   z
  |d<   | d   | d   z
  |d<   |S )a  Convert bounding boxes from [x1, y1, x2, y2] to [x1, y1, w, h] format.

    Args:
        x (np.ndarray | torch.Tensor): Input bounding box coordinates in xyxy format.

    Returns:
        (np.ndarray | torch.Tensor): Bounding box coordinates in ltwh format.
    rE   rC   rF   rD   r�   r„   s     r   Ú	xyxy2ltwhrˆ   ;  óW   € ô   ¤5§<¡<Ô0ˆ�‰Œ	´b·g±g¸a³j€AØ�&‘	˜A˜f™IÑ%€A€f�IØ�&‘	˜A˜f™IÑ%€A€f�IØ€Hr   c                óÈ   — t        | t        j                  «      r| j                  «       nt	        j
                  | «      }| d   | d   dz  z   |d<   | d   | d   dz  z   |d<   |S )a  Convert bounding boxes from [x1, y1, w, h] to [x, y, w, h] where xy1=top-left, xy=center.

    Args:
        x (np.ndarray | torch.Tensor): Input bounding box coordinates.

    Returns:
        (np.ndarray | torch.Tensor): Bounding box coordinates in xywh format.
    rC   rE   rA   rD   rF   r�   r„   s     r   Ú	ltwh2xywhr‹   J  r†   r   c                ó.  — t        | t        j                  «      }|r| j                  «       j	                  «       n| }|j                  t        | «      dd«      }g }|D ]ô  }t        j                  |«      \  \  }}\  }}}	|	dz  t        j                  z  }
||k  r||}}|
t        j                  dz  z  }
|
dt        j                  z  dz  k\  r-|
t        j                  z  }
|
dt        j                  z  dz  k\  rŒ-|
t        j                   dz  k  r+|
t        j                  z  }
|
t        j                   dz  k  rŒ+|j                  |||||
g«       Œö |r,t        j                  || j                  | j                  ¬«      S t        j                  |«      S )a–  Convert batched Oriented Bounding Boxes (OBB) from [xy1, xy2, xy3, xy4] to [xywh, rotation] format.

    Args:
        x (np.ndarray | torch.Tensor): Input box corners with shape (N, 8) in [xy1, xy2, xy3, xy4] format.

    Returns:
        (np.ndarray | torch.Tensor): Converted data in [cx, cy, w, h, rotation] format with shape (N, 5). Rotation
            values are in radians from [-pi/4, 3pi/4).
    rf   rA   é´   r+   r.   ©r
   r-   )rT   r    rU   ÚcpuÚnumpyÚreshapeÚlenÚcv2ÚminAreaRectr0   ÚpiÚappendÚtensorr
   r-   Úasarray)r;   Úis_torchÚpointsÚrboxesÚptsÚcxÚcyra   r`   ÚangleÚthetas              r   Úxyxyxyxy2xywhrr¡   Y  sZ  € ô ˜!œUŸ\™\Ó*€HÙ (ˆQ�U‰U‹W�]‰]Œ_¨a€FØ�^‰^œC ›F B¨Ó*€FØ€FØò -ˆô #&§/¡/°#Ó"6Ñ‰ˆˆR‘&�1�a˜%à˜‘œbŸe™eÑ#ˆØˆqŠ5Ø�aˆqˆAØ”R—U‘U˜Q‘YÑˆEØ�qœ2Ÿ5™5‘y 1‘}Ò$Ø”R—U‘U‰NˆEð �qœ2Ÿ5™5‘y 1‘}Ó$à”r—u‘u�f˜q‘jÒ Ø”R—U‘U‰NˆEð ”r—u‘u�f˜q‘jÓ à�‰�r˜2˜q ! UÐ+Õ,ð-ñ DLŒ5�<‰<˜ q§x¡x°q·w±wÔ?ÐcÔQS×Q[ÑQ[Ð\bÓQcÐcr   c                ó^  ‡ — t        ‰ t        j                  «      r>t        j                  t        j                  t        j
                  t        j                  fn=t        j                  t        j                  t        j                  t        j                  f\  }}}}‰ ddd…f   }ˆ fd„t        dd«      D «       \  }}} ||«       ||«      }
}	|dz  |	z  |dz  |
z  g}| dz  |
z  |dz  |	z  g} ||d«      } ||d«      }||z   |z   }||z   |z
  }||z
  |z
  }||z
  |z   } |||||gd«      S )aš  Convert batched Oriented Bounding Boxes (OBB) from [xywh, rotation] to [xy1, xy2, xy3, xy4] format.

    Args:
        x (np.ndarray | torch.Tensor): Boxes in [cx, cy, w, h, rotation] format with shape (N, 5) or (B, N, 5). Rotation
            values should be in radians from [-pi/4, 3pi/4).

    Returns:
        (np.ndarray | torch.Tensor): Converted corner points with shape (N, 4, 2) or (B, N, 4, 2).
    .NrA   c              3  ó6   •K  — | ]  }‰d ||dz   …f   –— Œ y­w).r@   Nr)   )Ú.0Úir;   s     €r   ú	<genexpr>z!xywhr2xyxyxyxy.<locals>.<genexpr>‰  s"   øè ø€ Ò:¨�1�S˜!˜a !™e˜)�^Õ$Ñ:ùs   ƒé   rf   éþÿÿÿ)
rT   r    rU   ÚcosÚsinÚcatÚstackr0   ÚconcatenateÚrange)r;   r©   rª   r«   r¬   Úctrra   r`   rŸ   Ú	cos_valueÚ	sin_valueÚvec1Úvec2Úpt1Úpt2Úpt3Úpt4s   `                r   Úxywhr2xyxyxyxyr¸   x  s2  ø€ ô �aœŸ™Ô&ô 
�‰”E—I‘IœuŸy™y¬%¯+©+Ñ6ä�f‰f”b—f‘fœbŸn™n¬b¯h©hÐ7ñ €Cˆˆc�5ð ˆC��!�ˆG‰*€CÛ:¬e°A°q«kÔ:�K€A€qˆ%Ù˜u›:¡s¨5£zˆy€IØ�‰E�IÑ˜q 1™u yÑ0Ð1€DØˆB�‰F�YÑ  A¡¨	Ñ 1Ð2€DÙˆt�R‹=€DÙˆt�R‹=€DØ
�‰*�tÑ
€CØ
�‰*�tÑ
€CØ
�‰*�tÑ
€CØ
�‰*�tÑ
€CÙ�#�s˜C Ð% rÓ*Ð*r   c                ó¼   — t        | t        j                  «      r| j                  «       nt	        j
                  | «      }| d   | d   z   |d<   | d   | d   z   |d<   |S )a  Convert bounding box from [x1, y1, w, h] to [x1, y1, x2, y2] where xy1=top-left, xy2=bottom-right.

    Args:
        x (np.ndarray | torch.Tensor): Input bounding box coordinates.

    Returns:
        (np.ndarray | torch.Tensor): Bounding box coordinates in xyxy format.
    rE   rC   rF   rD   r�   r„   s     r   Ú	ltwh2xyxyrº   –  r‰   r   c                ó  — g }| D ]^  }|j                   \  }}|j                  |j                  «       |j                  «       |j                  «       |j                  «       g«       Œ` t	        t        j                  |«      «      S )a  Convert segment coordinates to bounding box labels in xywh format.

    Args:
        segments (list): List of segments where each segment is a list of points, each point is [x, y] coordinates.

    Returns:
        (np.ndarray): Bounding box coordinates in xywh format.
    )r/   r–   r2   r3   rn   r0   r1   )ÚsegmentsrJ   Úsr;   r<   s        r   Úsegments2boxesr¾   ¥  sg   € ð €EØò ;ˆØ�s‰s‰ˆˆ1Ø�‰�a—e‘e“g˜qŸu™u›w¨¯©«°·±³Ð9Õ:ð;ô ”R—X‘X˜e“_Ó%Ð%r   c                ó¶  — t        | «      D �]D  \  }}t        |«      |k(  rŒt        j                  ||dd…dd…f   fd¬«      }t        j                  dt        |«      dz
  t        |«      |k  r|t        |«      z
  n|«      }t        j
                  t        |«      «      }t        |«      |k  r+t        j                  |t        j                  ||«      |«      n|}t        j                  t        d«      D �cg c]   }t        j                  |||dd…|f   «      ‘Œ" c}t        j                  ¬«      j                  dd«      j                  | <   �ŒG | S c c}w )a2  Resample segments to n points each using linear interpolation.

    Args:
        segments (list): List of (N, 2) arrays where N is the number of points in each segment.
        n (int): Number of points to resample each segment to.

    Returns:
        (list): Resampled segments with n points each.
    r   r@   N)ÚaxisrA   r,   rf   )Ú	enumerater’   r0   r­   ÚlinspaceÚarangeÚinsertÚsearchsortedr®   ÚinterpÚfloat32r‘   r/   )r¼   Únr¥   r½   r;   Úxps         r   Úresample_segmentsrÊ   µ  s  € ô ˜(Ó#ó 	
‰ˆˆ1Üˆq‹6�QŠ;ØÜ�N‰N˜A˜q  1 ¢a ™y˜>°Ô2ˆÜ�K‰K˜œ3˜q›6 A™:´S¸³V¸a²Z q¬3¨q«6¢zÀQÓGˆÜ�Y‰Y”s˜1“vÓˆÜ8;¸A»Àº
ŒB�I‰I�aœŸ™¨¨BÓ/°Ô4Èˆä�N‰N¼uÀQ»xÖH¸!œBŸI™I a¨¨Qªq°!¨t©WÕ5ÒHÔPR×PZÑPZÔ[×cÑcÐdeÐgiÓj×lÑlð 	�‹ð	
ð €Oùò Is   Ã8%E
c                óÜ  — |j                   | j                   k7  r|j                  | j                   «      }| j                  \  }}}|dk  r|| j                  spt	        |j                  d¬«      j                  «       j                  «       «      D ]4  \  }\  }}}}	d| |d|…f<   d| ||	d…f<   d| |dd…d|…f<   d| |dd…|d…f<   Œ6 | S t        j                  |dd…dd…df   dd«      \  }}}}	t        j                  || j                   |j                  ¬«      dddd…f   }
t        j                  || j                   |j                  ¬«      ddd…df   }| |
|k\  |
|k  z  ||k\  z  ||	k  z  z  S )a  Crop masks to bounding box regions.

    Args:
        masks (torch.Tensor): Masks with shape (N, H, W).
        boxes (torch.Tensor): Bounding box coordinates with shape (N, 4) in xyxy pixel format.

    Returns:
        (torch.Tensor): Cropped masks.
    é2   r   )r2   Nr.   r@   rŽ   )r
   Útor_   Úis_cudarÁ   r^   rG   rV   r    ÚchunkrÃ   r-   )ÚmasksrJ   rÈ   r`   ra   r¥   rj   rk   rl   rm   ÚrÚcs               r   Ú	crop_maskrÓ   Ì  sg  € ð ‡|�|�u—|‘|Ò#Ø—‘˜Ÿ™Ó&ˆØ�k‰k�G€A€qˆ!Øˆ2‚v�e—m’mÜ#,¨U¯[©[¸Q¨[Ó-?×-EÑ-EÓ-G×-KÑ-KÓ-MÓ#Nò 	!ÑˆAÑ��B˜˜BØˆE�!�S�b�S�&‰MØˆE�!�R‘S�&‰MØ ˆE�!’Q˜˜˜�)ÑØ ˆE�!’Q˜™�)Òð		!ð
 ˆäŸ™ Uª1ªa°¨:Ñ%6¸¸1Ó=‰ˆˆB��BÜ�L‰L˜ 5§<¡<°r·x±xÔ@ÀÀtÊQÀÑOˆÜ�L‰L˜ 5§<¡<°r·x±xÔ@ÀÂqÈ$ÀÑOˆØ˜˜b™ Q¨¡VÑ,°°R±Ñ8¸AÀ¹FÑCÑDÐDr   c                ó”  — | j                   \  }}}|| j                  «       j                  |d«      z  j                  d||«      }||d   z  }	||d   z  }
t        j                  |	|
|	|
gg|j
                  ¬«      }t        |||z  ¬«      }|rt        j                  |d   |d¬«      d   }|j                  d	«      j                  «       S )
aã  Apply masks to bounding boxes using mask head output.

    Args:
        protos (torch.Tensor): Mask prototypes with shape (mask_dim, mask_h, mask_w).
        masks_in (torch.Tensor): Mask coefficients with shape (N, mask_dim) where N is number of masks after NMS.
        bboxes (torch.Tensor): Bounding boxes with shape (N, 4) where N is number of masks after NMS.
        shape (tuple): Input image size as (height, width).
        upsample (bool): Whether to upsample masks to original image size.

    Returns:
        (torch.Tensor): A binary mask tensor of shape [n, h, w], where n is the number of masks after NMS, and h and w
            are the height and width of the input image. The mask is applied to the bounding boxes.
    rf   r@   r   )r
   )rJ   NÚbilinear©Úmoder#   )r_   r$   Úviewr    r—   r
   rÓ   ÚFÚinterpolateÚgt_Úbyte)ÚprotosÚmasks_inÚbboxesr_   ÚupsamplerÒ   ÚmhÚmwrÐ   Úwidth_ratioÚheight_ratioÚratioss               r   Úprocess_maskræ   ç  sÁ   € ð —‘�I€A€rˆ2Ø˜Ÿ™›×+Ñ+¨A¨rÓ2Ñ2×8Ñ8¸¸RÀÓD€Eà�u˜Q‘x‘-€KØ˜˜a™‘=€LÜ�\‰\˜K¨°{ÀLÐQÐRÐ[a×[hÑ[hÔi€Fä�e 6¨F¡?Ô3€EÙÜ—‘˜e D™k¨5°zÔBÀ1ÑEˆØ�9‰9�S‹>×ÑÓ Ð r   c                ó  — | j                   \  }}}|| j                  «       j                  |d«      z  j                  d||«      }t        |d   |«      d   }t	        ||«      }|j                  d«      j                  «       S )a  Apply masks to bounding boxes using mask head output with native upsampling.

    Args:
        protos (torch.Tensor): Mask prototypes with shape (mask_dim, mask_h, mask_w).
        masks_in (torch.Tensor): Mask coefficients with shape (N, mask_dim) where N is number of masks after NMS.
        bboxes (torch.Tensor): Bounding boxes with shape (N, 4) where N is number of masks after NMS.
        shape (tuple): Input image size as (height, width).

    Returns:
        (torch.Tensor): Binary mask tensor with shape (N, H, W).
    rf   Nr   r#   )r_   r$   rØ   Úscale_masksrÓ   rÛ   rÜ   )rÝ   rÞ   rß   r_   rÒ   rá   râ   rÐ   s           r   Úprocess_mask_nativeré     sw   € ð —‘�I€A€rˆ2Ø˜Ÿ™›×+Ñ+¨A¨rÓ2Ñ2×8Ñ8¸¸RÀÓD€EÜ˜˜d™ UÓ+¨AÑ.€EÜ�e˜VÓ$€EØ�9‰9�S‹>×ÑÓ Ð r   c                óÎ  — | j                   dd \  }}|dd \  }}||k(  r||k(  r| S |€At        ||z  ||z  «      }|t        ||z  «      z
  |t        ||z  «      z
  }
}	|r|	dz  }	|
dz  }
n|d   \  }	}
|rt        |
dz
  «      t        |	dz
  «      fnd\  }}|t        |
dz   «      z
  }|t        |	dz   «      z
  }t        j                  | d||…||…f   j                  «       |d¬«      S )	aº  Rescale segment masks to target shape.

    Args:
        masks (torch.Tensor): Masks with shape (N, C, H, W).
        shape (tuple[int, int]): Target height and width as (height, width).
        ratio_pad (tuple, optional): Ratio and padding values as ((ratio_h, ratio_w), (pad_w, pad_h)).
        padding (bool): Whether masks are based on YOLO-style augmented images with padding.

    Returns:
        (torch.Tensor): Rescaled masks.
    rA   Nr@   rB   )r   r   .rÕ   rÖ   )r_   r2   rG   rÙ   rÚ   r$   )rÐ   r_   rL   rM   Úim1_hÚim1_wÚim0_hÚim0_wrO   Úpad_wÚpad_hÚtopÚleftÚbottomÚrights                  r   rè   rè     s  € ð" —;‘;˜q˜r�?�L€Eˆ5Ø˜˜!�9�L€Eˆ5Ø�‚~˜% 5š.ØˆàÐÜ�5˜5‘= %¨%¡-Ó0ˆØ¤ e¨d¡lÓ 3Ñ3°u¼uÀUÈTÁ\Ó?RÑ7RˆuˆÙØ�Q‰JˆEØ�Q‰J‰Eà  ‘|‰ˆˆuÙ<C”�u˜s‘{Ó#¤U¨5°3©;Ó%7Ñ8È�I€CˆØ”U˜5 3™;Ó'Ñ'€FØ”E˜% #™+Ó&Ñ&€EÜ�=‰=˜˜s C¨ J°°U°
Ð:Ñ;×AÑAÓCÀUÐQ[Ô\Ð\r   c                ó‚  — |dd \  }}|€C| dd \  }}	t        ||z  |	|z  «      }
|	t        ||
z  «      z
  dz  |t        ||
z  «      z
  dz  f}n|d   d   }
|d   }|r |dxx   |d   z  cc<   |dxx   |d   z  cc<   |dxx   |
z  cc<   |dxx   |
z  cc<   t        ||«      }|r|dxx   |z  cc<   |dxx   |z  cc<   |S )av  Rescale segment coordinates from img1_shape to img0_shape.

    Args:
        img1_shape (tuple): Source image shape as HWC or HW (supports both).
        coords (torch.Tensor): Coordinates to scale with shape (N, 2).
        img0_shape (tuple): Image 0 shape as HWC or HW (supports both).
        ratio_pad (tuple, optional): Ratio and padding values as ((ratio_h, ratio_w), (pad_w, pad_h)).
        normalize (bool): Whether to normalize coordinates to range [0, 1].
        padding (bool): Whether coordinates are based on YOLO-style augmented images with padding.

    Returns:
        (torch.Tensor): Scaled coordinates.
    NrA   r   r@   rC   rD   )r2   rG   rd   )rI   rc   rK   rL   Ú	normalizerM   Úimg0_hÚimg0_wÚimg1_hÚimg1_wrO   Úpads               r   Úscale_coordsrü   9  sö   € ð    �^�N€FˆFØÐØ# B Q˜‰ˆ�Ü�6˜F‘? F¨V¡OÓ4ˆØœ˜f t™mÓ,Ñ,°Ñ1°F¼UÀ6ÈDÁ=Ó=QÑ4QÐUVÑ3VÐV‰à˜‰|˜A‰ˆØ˜‰lˆáØˆv‹˜#˜a™&Ñ ‹Øˆv‹˜#˜a™&Ñ ‹Ø
ˆ6ƒN�dÑƒNØ
ˆ6ƒN�dÑƒNÜ˜ Ó,€FÙØˆv‹˜&Ñ ‹Øˆv‹˜&Ñ ‹Ø€Mr   c                ó@  — | j                  d¬«      \  }}}}}|t        j                  z  t        j                  dz  k\  }t        j                  |||«      }t        j                  |||«      }|t        j                  dz  z  }t        j
                  |||||gd¬«      S )zÜRegularize rotated bounding boxes to range [0, pi/2).

    Args:
        rboxes (torch.Tensor): Input rotated boxes with shape (N, 5) in xywhr format.

    Returns:
        (torch.Tensor): Regularized rotated boxes.
    rf   )ÚdimrA   )ÚunbindrW   r•   r    Úwherer¬   )	r›   r;   r<   ra   r`   r	   ÚswapÚw_Úh_s	            r   Úregularize_rboxesr  \  sŠ   € ð —M‘M b�MÓ)�M€A€qˆ!ˆQ�àŒt�w‰w‰;œ$Ÿ'™' A™+Ñ%€DÜ	�‰�T˜1˜aÓ	 €BÜ	�‰�T˜1˜aÓ	 €BØ	ŒT�W‰W�q‰[Ñ€AÜ�;‰;˜˜1˜b " aÐ(¨bÔ1Ð1r   c                óz  — ddl m} t        | t        j                  «      r| j                  d«      n+| j                  «       j                  «       j                  «       } g }t        j                  | «      D �]8  }t        j                  |t        j                  t        j                  «      d   }|rÈ|dk(  r]t        |«      dkD  r9t        j                   ||D �cg c]  }|j!                  dd«      ‘Œ c}«      «      n|d   j!                  dd«      }n{|dk(  rvt        j"                  |t        j"                  |D �cg c]  }t        |«      ‘Œ c}«      j%                  «          «      j!                  dd«      }nt        j&                  d	«      }|j)                  |j                  d
«      «       �Œ; |S c c}w c c}w )a!  Convert masks to segments using contour detection.

    Args:
        masks (np.ndarray | torch.Tensor): Binary masks with shape (N, H, W).
        strategy (str): Segmentation strategy, either 'all' or 'largest'.

    Returns:
        (list): List of segment masks as float32 arrays.
    r   )Úmerge_multi_segmentÚuint8Úallr@   rf   rA   Úlargest)r   rA   rÇ   )Úultralytics.data.converterr  rT   r0   ÚndarrayÚastyperÜ   r�   r�   Úascontiguousarrayr“   ÚfindContoursÚRETR_EXTERNALÚCHAIN_APPROX_SIMPLEr’   r­   r‘   r1   Úargmaxr7   r–   )rÐ   Ústrategyr  r¼   r;   rÒ   s         r   Úmasks2segmentsr  n  s\  € õ ?ä%/°´r·z±zÔ%BˆE�L‰L˜Ô!ÈÏ
É
Ë×HXÑHXÓHZ×H`ÑH`ÓHb€EØ€HÜ×!Ñ! %Ó(ó -ˆÜ×Ñ˜Q¤× 1Ñ 1´3×3JÑ3JÓKÈAÑNˆÙØ˜5Ò ô ˜1“v ’zô —N‘NÑ#6ÐRSÖ7TÈQ¸¿	¹	À"ÀaÕ8HÒ7TÓ#UÔVà˜1™Ÿ™ b¨!Ó,ñ ð
 ˜YÒ&Ü—H‘H˜QœrŸx™x¸Ö(;°A¬¨Q­Ò(;Ó<×CÑCÓEÑFÓG×OÑOÐPRÐTUÓV‘ä—‘˜Ó ˆAØ�‰˜Ÿ™ Ó+Ö,ð-ð €Oùò 8Uùò
 )<s   ÃF3Ä;F8c                óÀ   — | j                  dddd«      j                  «       dz  j                  dd«      j                  «       j	                  «       j                  «       S )a_  Convert a batch of FP32 torch tensors to NumPy uint8 arrays, changing from BCHW to BHWC layout.

    Args:
        batch (torch.Tensor): Input tensor batch with shape (Batch, Channels, Height, Width) and dtype torch.float32.

    Returns:
        (np.ndarray): Output NumPy array batch with shape (Batch, Height, Width, Channels) and dtype uint8.
    r   rA   r+   r@   éÿ   )ÚpermuteÚ
contiguousr^   rÜ   r�   r�   )Úbatchs    r   Úconvert_torch2numpy_batchr  �  sO   € ð �M‰M˜!˜Q  1Ó%×0Ñ0Ó2°SÑ8×?Ñ?ÀÀ3ÓG×LÑLÓN×RÑRÓT×ZÑZÓ\Ð\r   c                ó2   — t        j                  dd| ¬«      S )zìClean a string by replacing special characters with '_' character.

    Args:
        s (str): A string needing special characters replaced.

    Returns:
        (str): A string with special characters replaced by an underscore _.
    u!   [|@#!Â¡Â·$â‚¬%&()=?Â¿^*;:,Â¨`><+]Ú_)ÚpatternÚreplÚstring)ÚreÚsub)r½   s    r   Ú	clean_strr!  ™  s   € ô �6‰6Ð=ÀCÐPQÔRÐRr   c                óº   — t        | t        j                  «      r!t        j                  | | j                  ¬«      S t        j                  | | j                  ¬«      S )zKCreate empty torch.Tensor or np.ndarray with same shape and dtype as input.r,   )rT   r    rU   ri   r-   r0   )r;   s    r   ri   ri   ¥  sA   € ä1;¸A¼u¿|¹|Ô1LŒ5×Ñ˜A Q§W¡WÔ-ÐqÔRT×R_ÑR_Ð`aÐij×ipÑipÔRqÐqr   )é€  r#  )r8   ú
np.ndarrayr9   rV   r:   rV   Úreturnr$  )NTF)rI   útuple[int, int]rJ   útorch.Tensor | np.ndarrayrK   r&  rL   ztuple | NonerM   r   rN   r   r%  r'  )r;   rV   )r#  r#  r   r   )ra   rV   r`   rV   rt   rV   ru   rV   )r#  r#  Fr#   )ra   rV   r`   rV   r5   r   r~   r$   )iè  )rÈ   rV   )rÐ   útorch.TensorrJ   r(  r%  r(  )F)rà   r   )NT)
rÐ   r(  r_   r&  rL   z.tuple[tuple[int, int], tuple[int, int]] | NonerM   r   r%  r(  )NFT)rö   r   rM   r   )r  )rÐ   znp.ndarray | torch.Tensorr  r   r%  zlist[np.ndarray])r  r(  r%  r$  )-Ú
__future__r   Ú
contextlibrW   r  r   r“   r�   r0   r    Útorch.nn.functionalÚnnÚ
functionalrÙ   Úultralytics.utilsr   ÚContextDecoratorr   r>   rR   rZ   rH   rd   rn   rr   r|   r   r…   rˆ   r‹   r¡   r¸   rº   r¾   rÊ   rÓ   ræ   ré   rè   rü   r  r  r  r!  ri   r)   r   r   ú<module>r0     sV  ðõ #ã Û Û 	Û ã 
Û Û ß Ð å )ô4#ˆj×)Ñ)ô 4#ônðB #ØØð'<Øð'<à$ð'<ð  ð'<ð ð	'<ð
 ð'<ð ð'<ð ó'<óT,òò8ò0ò(ô&ô0ò4òòòdò>+ò<ò&ô ó.Eô6!ò6!ð, AEØð	!]Øð!]àð!]ð >ð!]ð ð	!]ð
 ó!]ôH òF2ô$ó>	]ò	Sórr   