
    .hi                    b   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'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 Z$d.d/dZ%d Z&d0d1dZ'd2d3dZ(d Z)d4d5dZ*d6dZ+d  Z,d! Z-y)7    )annotationsN)NOT_MACOS14c                  2    e Zd ZdZdd	dZd Zd Zd Zd Zy)
Profilea<  
    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      S/var/www/html/ai-service/venv/lib/python3.12/site-packages/ultralytics/utils/ops.py__init__zProfile.__init__*   s2     BCK$:$:6$BC	    c                0    | j                         | _        | S )zStart timing.)timestartr   s    r   	__enter__zProfile.__enter__6   s    YY[
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__;   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.timeD   s.    99JJ""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k\  |dk\  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 (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anyr-   zeros)segmentwidthheightxyinsides         r   segment2boxr>   K   s    99DAq	xx1aeegk1557U?AEEGf<LMNRRTXYYFF1eFF1f1fa AJ/1;?F	&	A	&	A q6 	!%%'1557AEEGQUUW5W]]K XXaw}}-r   c                   |Yt        | d   |d   z  | d   |d   z        }t        | d   |d   |z  z
  dz  dz
        }t        | d   |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 )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   .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   i   s    $ :a=:a=0*Q-*Q-2OPz!}z!}t';;q@3FGz!}z!}t';;q@3FG|A |uff&MU"M&MU"M	#rr'NdN5;j
;;r   c                    t        |t        j                        rt        |j	                               }t        j                  | |z        |z  S )a  
    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<<(gkkm$99Q[!G++r   c                F   |dd \  }}t        | t        j                        rt        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    !9DAq%&&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                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     !9DAq&%,,'6N!!!Q'6N!!!Q' M $F^11!Q7F6N#F^11!Q7F6N M  ,,Q2v,,Q2vMr   c                F   |dd \  }}| j                   \  }}}||k(  r||k(  r| S |)t        ||z  ||z        }|||z  z
  dz  |||z  z
  dz  f}	n|d   }	|	\  }
}t        t        |dz
              }t        t        |
dz
              }|t        t        |dz               z
  }|t        t        |
dz               z
  }t	        | j                         dk  r!t        dt	        | j                                | ||||f   } t        j                  | | j                   d   dz  dz   d      D cg c]  }t        j                  |||f       } }t	        |       dkD  rt        j                  | d      n| d	   } t	        | j                         dk(  r| dddddf   } | S c c}w )
aP  
    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.
    NrA   r@   rB   z/"len of masks shape" should be 2 or 3, but got i   axisr   )r_   r2   rV   rG   len
ValueErrorr0   array_splitcv2resizeconcatenate)masks	im0_shaperL   im0_him0_wim1_him1_w_rO   padpad_wpad_htopleftbottomrightr1   s                    r   scale_imager}      s     Ra=LE5kkOE5!~%5.55=%%-0ut|#q(554<+?1*DDlLE5
eECK 
!CuUS[!"DSus{+,,FCeck*++E
5;;!J3u{{K[J\]^^#f*d5j()E<>NN5RWR]R]^`RaehRhklRlsu<vw5SZZu~.wEw.1%j1nBNN5r*%(E
5;;1aDj!L xs   -F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.
    rf   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   	xyxy2xywhr      s     772;!bXYZY`Y`Xabb1AvY&	1V9ai?NBBbAAfIbAAfIRAfIRAfI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.   r   .NrA   r   )r;   r<   xywhs       r   	xywh2xyxyr     s     772;!bXYZY`Y`Xabb1A	
37B	
37aBbAc2A2gJbAc12gJ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 )	aC  
    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.
    rf   r.   r   rC   rD   rE   rF   rA   r   )r;   ra   r`   padwpadhr<   xcycxwxhhalf_whalf_hs               r   
xywhn2xyxyr   )  s     772;!bXYZY`Y`Xabb1AvY&	1V9ai?NBB!VR!VFFR&[!D(AfIR&[!D(AfIR&[!D(AfIR&[!D(AfI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 )	af  
    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.
    rf   r.   r   rC   rD   rE   rF   rA   )rH   r_   r   )
r;   ra   r`   r5   epsr<   r   r   r   r   s
             r   
xyxy2xywhnr   C  s     q1s7AG,-772;!bXYZY`Y`Xabb1AvY&	1V9ai?NBBr'Q!#AfIr'Q!#AfIbAAfIbAAfI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 xyltwh format.
    rC   rE   rA   rD   rF   rT   r    rU   cloner0   copyr;   r<   s     r   	xywh2ltwhr   ^  _      5<<0	bggajA&	AfIM)AfI&	AfIM)AfI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 xyltwh format.
    rE   rC   rF   rD   r   r   s     r   	xyxy2ltwhr   n  W      5<<0	bggajA&	AfI%AfI&	AfI%AfI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 (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   ~  r   r   c           	        t        | t        j                        }|r| j                         j	                         n| }|j                  t        |       dd      }g }|D ]K  }t        j                  |      \  \  }}\  }}}	|j                  |||||	dz  t        j                  z  g       M |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 0 to pi/2.
    rf   rA      r
   r-   )rT   r    rU   cpunumpyreshaperi   rl   minAreaRectappendr0   pitensorr
   r-   asarray)
r;   is_torchpointsrboxesptscxcyra   r`   angles
             r   xyxyxyxy2xywhrr     s     !U\\*H (QUUW]]_aF^^CFB*FF ; #&//#"6R&1a%r2q!US[255%89:	;
 DL5<<qxxqww?cQSQ[Q[\bQc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 0 to pi/2.

    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"     :1S!a!e)^$:s      rf   )
rT   r    rU   cossincatstackr0   rn   range)r;   r   r   r   r   ctrra   r`   r   	cos_value	sin_valuevec1vec2pt1pt2pt3pt4s   `                r   xywhr2xyxyxyxyr     s2    a& 
EIIuyy%++6ffbffbnnbhh7 Cc5 C!G*C:eAqk:KAq%u:s5zyIEIq1uy01DBFYA	 12DtR=DtR=D
*t
C
*t
C
*t
C
*t
C#sC%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 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.
    )r/   r   r2   r3   r   r0   r1   )segmentsrJ   sr;   r<   s        r   segments2boxesr     sg     E ;ss1aeegquuw9:; RXXe_%%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 )a7  
    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@   Nrg   rA   r,   rf   )	enumerateri   r0   rn   linspacearangeinsertsearchsortedr   interpfloat32r   r/   )r   nr   r   r;   xps         r   resample_segmentsr     s    (# 	
1q6Q;NNAq1ay>2KK3q6A:SVaZq3q6zQGYYs1v8;A
BIIaB/4NNuQxH!BIIaQq!tW5HPRPZPZ[ccdegijll 		
 O Is   8%E
c                <   | j                   \  }}}|dk  r`t        |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 relative point form.

    Returns:
        (torch.Tensor): Cropped masks.
    2   r   Nr.   r@   r   )	r_   r   rG   rV   r    chunkr   r
   r-   )ro   rJ   r   r`   ra   r   r   r   r   r   rcs               r   	crop_maskr     s1    kkGAq!2v#,U[[]->->-@#A 	!ABBE!SbS&ME!RS&M E!Q) E!Q)		!
 U1a:%61=BBLL5<<rxx@tQOLL5<<rxx@q$ObQV,R8A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mwro   width_ratioheight_ratioratioss               r   process_maskr     s     IAr2++Ar2288RDEuQx-Ka=L\\K{LQR[a[h[hiFe6F?3EeDk5zB1E99S>  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 (H, W, N).
    rf   Nr   r#   )r_   r$   r   scale_masksr   r   r   )r   r   r   r_   r   r   r   ro   s           r   process_mask_nativer   3  sw     IAr2++Ar2288RDEdU+A.EeV$E99S>  r   c                   | j                   dd \  }}t        ||d   z  ||d   z        }||d   |z  z
  }||d   |z  z
  }|r
|dz  }|dz  }|r.t        t        |dz
              t        t        |dz
              fnd\  }}	|t        t        |dz               z
  }
|t        t        |dz               z
  }t	        j
                  | d||
|	|f   |d	      S )
aN  
    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.
    rA   Nr   r@   rB   )r   r   .r   r   )r_   r2   rV   rG   r   r   )ro   r_   rM   r   r   rO   rw   rx   ry   rz   r{   r|   s               r   r   r   G  s     [[_FBrE!H}b58m,DqD EqD E

FMU53;'(#eECK.@*ABSYIC#eECK())FU53;'((E==sCJU
:;UTTr   c                ^   |dd \  }}|1| dd \  }}	t        ||z  |	|z        }
|	||
z  z
  dz  |||
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 )a{  
    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.
    NrA   r   r@   rC   rD   )r2   rd   )rI   rc   rK   rL   	normalizerM   img0_himg0_wimg1_himg1_wrO   rv   s               r   scale_coordsr  `  s      ^NFF#BQ6F?FVO4%*Vftm-Cq,HH|Alv#a& v#a& 
6NdN
6Nd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     MMbM)MAq!Qtww;$''A+%D	T1a	 B	T1a	 B	TWWq[A;;1b"a(b11r   c                   ddl m} g }| j                         j                         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 (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allr@   rf   rA   largest)r   rA   r   )ultralytics.data.converterr  r   r   r   rl   findContoursRETR_EXTERNALCHAIN_APPROX_SIMPLEri   r0   rn   r   r1   argmaxr7   r   astype)ro   strategyr  r   r;   r   s         r   masks2segmentsr    s4    ?HZZ\%%' -Q 1 133J3JKAN5  1vz NN#6RS7TQ		"a8H7T#UV1b!, 
 Y&HHQrxx(;AQ(;<CCEFGOOPRTUV A+,- O 8U
 )<s   E3;E8c                    | j                  dddd      j                         dz  j                  dd      j                         j	                         j                         S )ad  
    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     MM!Q1%002S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"   [|@#!¡·$€%&()=?¿^*;:,¨´><+]ru   )patternreplstring)resub)r   s    r   	clean_strr"    s     66>SQRSSr   c                    t        | t        j                        r%t        j                  | t        j                        S t        j                  | t
        j                        S )zSCreate empty torch.Tensor or np.ndarray with same shape as input and float32 dtype.r,   )rT   r    rU   r   r   r0   )r;   s    r   r   r     sG     5?q%,,4O%--0UWUbUbcdlnlvlvUwr   )  r$  )r9   rV   r:   rV   )NTF)rM   r   rN   r   )r;   rV   )N)r$  r$  r   r   )ra   rV   r`   rV   r   rV   r   rV   )r$  r$  Fr#   )ra   rV   r`   rV   r5   r   r   r$   )i  )r   rV   )F)r   r   )T)rM   r   )NFT)r   r   rM   r   )r  )r  r   )r  ztorch.Tensorreturnz
np.ndarray).
__future__r   
contextlibrW   r   r   rl   r   r0   r    torch.nn.functionalnn
functionalr   ultralytics.utilsr   ContextDecoratorr   r>   rR   rZ   rH   rd   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   <module>r-     s    #   	  
     )6#j)) 6#r<!<H, :2*Z*(46   d.+> &"0E4!8!(U2!H2&>
]
Tr   