
    hi                       S SK Jr  S SKrS SKrS SKrS SKrS SKrS SKrS SK	r	S SK
Js  Jr  S SKJr   " S S\R                   5      rS"S#S jjrS$S%S jjrS&S jrS	 rS
 rS'S jrS rS rS(S)S jjrS*S+S jjrS rS rS rS rS r S r!S r"S,S-S jjr#S r$S.S/S jjr%S r&S0S1S jjr'S2S3S jjr(S r)S4S5S jjr*S6S jr+S  r,S! r-g)7    )annotationsN)NOT_MACOS14c                  >    \ rS rSrSrS
SS jjrS rS rS rS r	S	r
g)Profile   a  
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l         X l        [        U=(       a    [        U5      R	                  S5      5      U l        g)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      O/home/james-whalen/.local/lib/python3.13/site-packages/ultralytics/utils/ops.py__init__Profile.__init__*   s.     BCK$:$:6$BC	    c                0    U R                  5       U l        U $ )zStart timing.)timestartr   s    r   	__enter__Profile.__enter__6   s    YY[
r   c                    U R                  5       U R                  -
  U l        U =R                  U R                  -  sl        g)zStop timing.N)r   r   dtr
   )r   typevalue	tracebacks       r   __exit__Profile.__exit__;   s*    ))+

*$''r   c                "    SU R                    S3$ )zIReturn a human-readable string representing the accumulated elapsed time.zElapsed time is z s)r
   r   s    r   __str__Profile.__str__@   s    !$&&,,r   c                    U R                   (       a)  [        R                   R                  U R                  5        [        R
                  " 5       $ )z9Get current time with CUDA synchronization if applicable.)r	   torchsynchronizer   r   perf_counterr   s    r   r   Profile.timeD   s.    99JJ""4;;/  ""r   )r	   r   r   r   r
   )        N)r
   floatr   ztorch.device | None)__name__
__module____qualname____firstlineno____doc__r   r   r   r"   r   __static_attributes__ r   r   r   r      s!    .
D

-#r   r   c                   U R                   u  p4[        R                  " UR                  5       S:  UR                  5       S:  UR	                  5       U:  UR	                  5       U:  /5      R                  5       S:  a$  UR                  SU5      nUR                  SU5      nUS:  US:  -  X1:*  -  XB:*  -  nX5   nXE   n[        U5      (       a[  [        R                  " UR                  5       UR                  5       UR	                  5       UR	                  5       /U R                  S9$ [        R                  " SU R                  S9$ )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 (torch.Tensor): 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anyr5   zeros)segmentwidthheightxyinsides         r   segment2boxrF   K   s    99DA	xx1aeegk1557U?AEEGf<LMNRRTXYYFF1eFF1f1fa AJ/1;?F		A		A q66 	!%%'1557AEEGQUUW5W]]K XXaw}}-r   c                   UcY  [        U S   US   -  U S   US   -  5      n[        U S   US   U-  -
  S-  S-
  5      n[        U S   US   U-  -
  S-  S-
  5      nOUS   S   nUS   u  pxU(       a;  US==   U-  ss'   US==   U-  ss'   U(       d  US==   U-  ss'   US	==   U-  ss'   US
SS24==   U-  ss'   U(       a  U$ [        X5      $ )a  
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): Shape of the source image (height, width).
    boxes (torch.Tensor): Bounding boxes to rescale in format (N, 4).
    img0_shape (tuple): 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): Rescaled bounding boxes in the same format as input.
Nr         皙?.r   .rH   .rI   .r3   .r6   )r:   round
clip_boxes)	
img1_shapeboxes
img0_shape	ratio_padpaddingxywhgainpad_xpad_ys	            r   scale_boxesrZ   i   s    $ :a=:a=0*Q-*Q-2OPz!}z!}t';;q@3FGz!}z!}t';;q@3FG|A |ff&MU"M&MU"M	#rr'NdN5;j;;r   c                    [        U[        R                  5      (       a  [        UR	                  5       5      n[
        R                  " X-  5      U-  $ )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intr;   mathceil)rC   divisors     r   make_divisiblerb      s;     '5<<((gkkm$99Q[!G++r   c                Z   USS u  p#[        U [        R                  5      (       a  [        (       aV  U S   R	                  SU5        U S   R	                  SU5        U S   R	                  SU5        U S   R	                  SU5        U $ U S   R                  SU5      U S'   U S   R                  SU5      U S'   U S   R                  SU5      U S'   U S   R                  SU5      U S'    U $ U SSS/4   R                  SU5      U SSS/4'   U SS	S
/4   R                  SU5      U SS	S
/4'   U $ )z
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.
NrI   rK   r   rL   rM   rN   .rH   r3   r\   r%   r]   r   clamp_clampr=   )rR   shapehws       r   rP   rP      sN    !9DA%&&;&M  A&&M  A&&M  A&&M  A& L "&M//15E&M!&M//15E&M!&M//15E&M!&M//15E&M L #3A;/44Q:cAq6k"3A;/44Q:cAq6kLr   c                   USS u  p#[        U [        R                  5      (       aj  [        (       a,  U S   R	                  SU5        U S   R	                  SU5        U $ U S   R                  SU5      U S'   U S   R                  SU5      U S'    U $ U S   R                  SU5      U S'   U S   R                  SU5      U S'   U $ )z
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.
NrI   rK   r   rL   rd   )coordsrg   rh   ri   s       r   clip_coordsrl      s     !9DA&%,,'';6N!!!Q'6N!!!Q' M $F^11!Q7F6N#F^11!Q7F6N M  ,,Q2v,,Q2vMr   c                8   USS u  p4U R                   u  pVnXS:X  a  Xd:X  a  U $ Uc%  [        XS-  Xd-  5      nXdU-  -
  S-  XSU-  -
  S-  4n	OUS   n	U	u  p[        [        US-
  5      5      n[        [        U
S-
  5      5      nU[        [        US-   5      5      -
  nU[        [        U
S-   5      5      -
  n[	        U R                   5      S:  a!  [        S[	        U R                   5       35      eXU2X24   n [        R                  " X R                   S   S-  S-   SS9 Vs/ s H  n[        R                  " UXC45      PM     n n[	        U 5      S:  a  [        R                  " U SS9OU S	   n [	        U R                   5      S:X  a  U SS2SS2S4   n U $ s  snf )
a(  
Rescale masks to original image size.

Takes resized and padded masks and rescales them back to the original image dimensions, removing any padding
that was applied during preprocessing.

Args:
    masks (np.ndarray): Resized and padded masks with shape [H, W, N] or [H, W, 3].
    im0_shape (tuple): Original image shape as HWC or HW (supports both).
    ratio_pad (tuple, optional): Ratio and padding values as ((ratio_h, ratio_w), (pad_h, pad_w)).

Returns:
    (np.ndarray): Rescaled masks with shape [H, W, N] matching original image dimensions.
NrI   rH   rJ   z/"len of masks shape" should be 2 or 3, but got i   axisr   )rg   r:   r^   rO   len
ValueErrorr8   array_splitcv2resizeconcatenate)masks	im0_shaperT   im0_him0_wim1_him1_w_rW   padpad_wpad_htopleftbottomrightr9   s                    r   scale_imager      s     Ra=LEkkOE!~%.5=%-0t|#q(54<+?1*DDlLE
eECK 
!CuUS[!"DSus{+,,FCeck*++E
5;;!J3u{{K[J\]^^f*dj()E<>NN5R]R]^`RaehRhklRlsu<vw<v5SZZ~.<vEw.1%j1nBNN5r*%(E
5;;1aDj!L xs   #"Fc                    U R                   S   S:X  d   SU R                    35       e[        U 5      nU S   U S   U S   U S   4u  p#pEX$-   S-  US'   X5-   S-  US'   XB-
  US'   XS-
  US'   U$ )	ax  
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.
rn   r6   9input shape last dimension expected 4 but input shape is rK   rL   rM   rN   rI   rg   
empty_like)rC   rD   x1y1x2y2s         r   	xyxy2xywhr      s     772;!bXYZY`Y`Xabb1AvY&	1V9ai?NBBAAfIAAfIAfIAfIHr   c                    U R                   S   S:X  d   SU R                    35       e[        U 5      nU SSS24   nU SSS24   S-  nX#-
  USSS24'   X#-   USSS24'   U$ )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.
rn   r6   r   .NrI   r   )rC   rD   xywhs       r   	xywh2xyxyr     s     772;!bXYZY`Y`Xabb1A	
37B	
37aBAc2A2gJAc12gJHr   c                   U R                   S   S:X  d   SU R                    35       e[        U 5      nU S   U S   U S   U S   4u  pgpUS-  U	S-  pXU
-
  -  U-   US'   X'U-
  -  U-   US'   XU
-   -  U-   US'   X'U-   -  U-   US'   U$ )	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:
    y (np.ndarray | torch.Tensor): The coordinates of the bounding box in the format [x1, y1, x2, y2] where
        x1,y1 is the top-left corner, x2,y2 is the bottom-right corner of the bounding box.
rn   r6   r   rK   rL   rM   rN   rI   r   )rC   ri   rh   padwpadhrD   xcycxwxhhalf_whalf_hs               r   
xywhn2xyxyr   )  s     772;!bXYZY`Y`Xabb1AvY&	1V9ai?NBB!VR!VF&[!D(AfI&[!D(AfI&[!D(AfI&[!D(AfIHr   c                "   U(       a  [        XU-
  X-
  45      n U R                  S   S:X  d   SU R                   35       e[        U 5      nU S   U S   U S   U S   4u  pgpXh-   S-  U-  US'   Xy-   S-  U-  US'   X-
  U-  US'   X-
  U-  US'   U$ )	a:  
Convert bounding box coordinates from (x1, y1, x2, y2) format to (x, y, width, height, normalized) 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.
rn   r6   r   rK   rL   rM   rN   rI   )rP   rg   r   )
rC   ri   rh   r=   epsrD   r   r   r   r   s
             r   
xyxy2xywhnr   C  s     qs7AG,-772;!bXYZY`Y`Xabb1AvY&	1V9ai?NBB'Q!#AfI'Q!#AfIAAfIAAfIHr   c                    [        U [        R                  5      (       a  U R                  5       O[        R
                  " U 5      nU S   U S   S-  -
  US'   U S   U S   S-  -
  US'   U$ )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 xyltwh format.
rK   rM   rI   rL   rN   r\   r%   r]   cloner8   copyrC   rD   s     r   	xywh2ltwhr   ^  b      5<<00	bggajA&	AfIM)AfI&	AfIM)AfIHr   c                    [        U [        R                  5      (       a  U R                  5       O[        R
                  " U 5      nU S   U S   -
  US'   U S   U S   -
  US'   U$ )z
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 xyltwh format.
rM   rK   rN   rL   r   r   s     r   	xyxy2ltwhr   n  Z      5<<00	bggajA&	AfI%AfI&	AfI%AfIHr   c                    [        U [        R                  5      (       a  U R                  5       O[        R
                  " U 5      nU S   U S   S-  -   US'   U S   U S   S-  -   US'   U$ )z
Convert bounding boxes from [x1, y1, w, h] to [x, y, w, h] where xy1=top-left, xy=center.

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

Returns:
    (np.ndarray | torch.Tensor): Bounding box coordinates in xywh format.
rK   rM   rI   rL   rN   r   r   s     r   	ltwh2xywhr   ~  r   r   c           	        [        U [        R                  5      nU(       a  U R                  5       R	                  5       OU nUR                  [        U 5      SS5      n/ nU HI  n[        R                  " U5      u  u  pVu  pxn	UR                  XVXxU	S-  [        R                  -  /5        MK     U(       a)  [        R                  " X0R                  U R                  S9$ [        R                  " U5      $ )az  
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 0 to pi/2.
rn   rI      r   r5   )r\   r%   r]   cpunumpyreshaperq   rt   minAreaRectappendr8   pitensorr   r5   asarray)
rC   is_torchpointsrboxesptscxcyri   rh   angles
             r   xyxyxyxy2xywhrr     s     !U\\*H (QUUW]]_aF^^CFB*FF #&//#"6&1%rqUS[255%89:	 
 DL5<<xxqww?cQSQ[Q[\bQccr   c                X  ^  [        T [        R                  5      (       a>  [        R                  [        R                  [        R
                  [        R                  4O=[        R                  [        R                  [        R                  [        R                  4u  pp4T SSS24   nU 4S j[        SS5       5       u  pgnU" U5      U" U5      pUS-  U	-  US-  U
-  /nU* S-  U
-  US-  U	-  /nU" US5      nU" US5      nX[-   U-   nX[-   U-
  nX[-
  U-
  nX[-
  U-   nU" XUU/S5      $ )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 0 to pi/2.

Returns:
    (np.ndarray | torch.Tensor): Converted corner points with shape (N, 4, 2) or (B, N, 4, 2).
.NrI   c              3  :   >#    U  H  nTS XS-   24   v   M     g7f).rH   Nr1   ).0irC   s     r   	<genexpr>!xywhr2xyxyxyxy.<locals>.<genexpr>  s      :k1S!!e)^$ks      rn   )
r\   r%   r]   cossincatstackr8   rv   range)rC   r   r   r   r   ctrri   rh   r   	cos_value	sin_valuevec1vec2pt1pt2pt3pt4s   `                r   xywhr2xyxyxyxyr     s#    a&& 
EIIuyy%++6ffbffbnnbhh7 Cc C!G*C:eAqk:KA%u:s5zyEIq1uy01DBFYA	 12DtR=DtR=D
*t
C
*t
C
*t
C
*t
C#C%r**r   c                    [        U [        R                  5      (       a  U R                  5       O[        R
                  " U 5      nU S   U S   -   US'   U S   U S   -   US'   U$ )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.
rM   rK   rN   rL   r   r   s     r   	ltwh2xyxyr     r   r   c                   / nU  H^  nUR                   u  p4UR                  UR                  5       UR                  5       UR                  5       UR                  5       /5        M`     [	        [
        R                  " U5      5      $ )a  
Convert segment labels to box labels, i.e. (cls, xy1, xy2, ...) to (cls, xywh).

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.
)r7   r   r:   r;   r   r8   r9   )segmentsrR   srC   rD   s        r   segments2boxesr     s`     Essaeegquuw9:  RXXe_%%r   c                   [        U 5       GHI  u  p#[        U5      U:X  a  M  [        R                  " X3SS2SS24   4SS9n[        R                  " S[        U5      S-
  [        U5      U:  a  U[        U5      -
  OU5      n[        R
                  " [        U5      5      n[        U5      U:  a,  [        R                  " U[        R                  " XE5      U5      OUn[        R                  " [        S5       Vs/ s H!  n[        R                  " XEUSS2U4   5      PM#     sn[        R                  S9R                  SS5      R                  U W'   GML     U $ s  snf )a  
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   rH   Nro   rI   r4   rn   )	enumeraterq   r8   rv   linspacearangeinsertsearchsortedr   interpfloat32r   r7   )r   nr   r   rC   xps         r   resample_segmentsr     s    (#q6Q;NNA1ay>2KK3q6A:SVaZq3q6zQGYYs1v8;A
BIIa/4NNuQxHx!BIIaQq!tW5xHPRPZPZ[ccdegijll 	 $ O Is   <(E
c                   U R                   u  p#nUS:  a\  [        UR                  5       R                  5       5       H/  u  nu  pgpSXSU24'   SXU	S24'   SXSS2SU24'   SXSS2US24'   M1     U $ [        R
                  " USS2SS2S4   SS5      u  pgp[        R                  " X@R                  UR                  S9SSSS24   n
[        R                  " X0R                  UR                  S9SSS2S4   nX
U:  X:  -  X:  -  X:  -  -  $ )z
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 relative point form.

Returns:
    (torch.Tensor): Cropped masks.
2   r   Nr6   rH   r   )	rg   r   rO   r^   r%   chunkr   r   r5   )rw   rR   r   rh   ri   r   r   r   r   r   rcs               r   	crop_maskr     s    kkGA!2v#,U[[]->->-@#AAESbS&MERS&M EQ) EQ)	 $B
 U1a:%61=LL<<rxx@tQOLL<<rxx@q$ObQV,8AFCDDr   c                   U R                   u  pVnXR                  5       R                  US5      -  R                  SXg5      nXsS   -  n	XcS   -  n
[        R                  " XX//UR
                  S9n[        XU-  S9nU(       a  [        R                  " US   USS9S   nUR                  S	5      R                  5       $ )
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.
rn   rH   r   )r   )rR   Nbilinearmoder)   )rg   r*   viewr%   r   r   r   Finterpolategt_byte)protosmasks_inbboxesrg   upsampler   mhmwrw   width_ratioheight_ratioratioss               r   process_maskr     s     IA2++Ar2288RDEQx-Ka=L\\K{QR[a[h[hiFeF?3EeDk5zB1E99S>  r   c                    U R                   u  pEnXR                  5       R                  US5      -  R                  SXV5      n[        US   U5      S   n[	        Xr5      nUR                  S5      R                  5       $ )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 (H, W, N).
rn   Nr   r)   )rg   r*   r   scale_masksr   r   r   )r   r   r   rg   r   r   r   rw   s           r   process_mask_nativer  3  so     IA2++Ar2288RDEdU+A.Ee$E99S>  r   c                   U R                   SS u  p4[        X1S   -  XAS   -  5      nXAS   U-  -
  nX1S   U-  -
  nU(       a
  US-  nUS-  nU(       a.  [        [        US-
  5      5      [        [        US-
  5      5      4OSu  pU[        [        US-   5      5      -
  n
U[        [        US-   5      5      -
  n[        R
                  " U SX2X24   USS	9$ )
a.  
Rescale segment masks to target shape.

Args:
    masks (torch.Tensor): Masks with shape (N, C, H, W).
    shape (tuple): Target height and width as (height, width).
    padding (bool): Whether masks are based on YOLO-style augmented images with padding.

Returns:
    (torch.Tensor): Rescaled masks.
rI   Nr   rH   rJ   )r   r   .r   r   )rg   r:   r^   rO   r   r   )rw   rg   rU   r   r   rW   r   r   r   r   r   r   s               r   r  r  G  s     [[_FBr!H}b8m,DqD EqD E

FMU53;'(#eECK.@*ABSYIC#eECK())FU53;'((E==sCJ
:;UTTr   c                f   USS u  pgUc,  U SS u  p[        X-  X-  5      n
XU
-  -
  S-  XU
-  -
  S-  4nOUS   S   n
US   nU(       a   US==   US   -  ss'   US==   US   -  ss'   US==   U
-  ss'   US==   U
-  ss'   [        X5      nU(       a  US==   U-  ss'   US==   U-  ss'   U$ )aO  
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_h, pad_w)).
    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.
NrI   r   rH   rK   rL   )r:   rl   )rQ   rk   rS   rT   	normalizerU   img0_himg0_wimg1_himg1_wrW   r~   s               r   scale_coordsr
  `  s      ^NF#BQ6?FO4%*Vtm-Cq,HH|Alv#a& v#a& 
6NdN
6NdN,Fv& v& Mr   c                .   U R                  SS9u  pp4nU[        R                  -  [        R                  S-  :  n[        R                  " XdU5      n[        R                  " XcU5      nU[        R                  S-  -  n[        R
                  " XXxU/SS9$ )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.
rn   )dimrI   )unbindr_   r   r%   wherer   )	r   rC   rD   ri   rh   r
   swapw_h_s	            r   regularize_rboxesr    s~     MMbM)MA!tww;$''A+%D	Ta	 B	Ta	 B	TWWq[A;;ba(b11r   c                "   SSK Jn  / nU R                  5       R                  5       R	                  5        GHK  n[
        R                  " U[
        R                  [
        R                  5      S   nU(       a  US:X  aa  [        U5      S:  a<  [        R                  " U" U Vs/ s H  oDR                  SS5      PM     sn5      5      OUS   R                  SS5      nOUS:X  ae  [        R                  " U[        R                  " U Vs/ s H  n[        U5      PM     sn5      R                  5          5      R                  SS5      nO[        R                  " S5      nUR!                  UR#                  S	5      5        GMN     U$ s  snf s  snf )
a
  
Convert masks to segments using contour detection.

Args:
    masks (torch.Tensor): Binary masks with shape (batch_size, 160, 160).
    strategy (str): Segmentation strategy, either 'all' or 'largest'.

Returns:
    (list): List of segment masks as float32 arrays.
r   )merge_multi_segmentallrH   rn   rI   largest)r   rI   r   )ultralytics.data.converterr  r   r   r   rt   findContoursRETR_EXTERNALCHAIN_APPROX_SIMPLErq   r8   rv   r   r9   argmaxr?   r   astype)rw   strategyr  r   rC   r   s         r   masks2segmentsr    s8    ?HZZ\%%'Q 1 133J3JKAN5  1vz NN#6RS7TRSQ		"a8HRS7T#UV1b!, 
 Y&HHQrxx(;AQ(;<CCEFGOOPRTUV A+, ( O 8U
 )<s   "F	Fc                    U R                  SSSS5      R                  5       S-  R                  SS5      R                  5       R	                  5       R                  5       $ )aL  
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   rI   r3   rH      )permute
contiguousrf   r   r   r   )batchs    r   convert_torch2numpy_batchr$    sO     MM!Q1%002S8??3GLLNRRTZZ\\r   c                .    [         R                  " SSU S9$ )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"   [|@#!¡·$€%&()=?¿^*;:,¨´><+]r}   )patternreplstring)resub)r   s    r   	clean_strr+    s     66>SQRSSr   c                    [        U [        R                  5      (       a#  [        R                  " U [        R                  S9$ [
        R                  " U [
        R                  S9$ )zSCreate empty torch.Tensor or np.ndarray with same shape as input and float32 dtype.r4   )r\   r%   r]   r   r   r8   )rC   s    r   r   r     sJ     5?q%,,4O4O%--0UWUbUbcdlnlvlvUwr   )  r-  )rA   r^   rB   r^   )NTF)rU   r   rV   r   )rC   r^   )N)r-  r-  r   r   )ri   r^   rh   r^   r   r^   r   r^   )r-  r-  Fr)   )ri   r^   rh   r^   r=   r   r   r*   )i  )r   r^   )F)r   r   )T)rU   r   )NFT)r  r   rU   r   )r  )r  r   )r#  ztorch.Tensorreturnz
np.ndarray).
__future__r   
contextlibr_   r)  r   rt   r   r8   r%   torch.nn.functionalnn
functionalr   ultralytics.utilsr   ContextDecoratorr   rF   rZ   rb   rP   rl   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r
  r  r  r$  r+  r   r1   r   r   <module>r6     s    #   	  
     )6#j)) 6#r<!<H, :2*Z*(46   d.+> &"0E4!8!(U2!H2&>
]
Tr   