
    FPh@>                         d dl mZ d dlmZ d dlmZ d dlmZ d dlZ	ddl
mZmZmZmZmZmZmZ d Z ed	      Z ed
      Zg dZdZ G d d      Z G d d      Zy)    )abc)repeat)Number)ListN   )	ltwh2xywh	ltwh2xyxyresample_segments	xywh2ltwh	xywh2xyxy	xyxy2ltwh	xyxy2xywhc                       fd}|S )zFrom PyTorch internals.c                 f    t        | t        j                        r| S t        t	        |             S )z2Parse bounding boxes format between XYWH and LTWH.)
isinstancer   Iterabletupler   )xns    eC:\Users\daisl\Desktop\realtime-object-detection\venv\Lib\site-packages\ultralytics/utils/instance.pyparsez_ntuple.<locals>.parse   s&    q#,,/qHU6!Q<5HH     )r   r   s   ` r   _ntupler      s    I Lr         )xyxyxywhltwh)Bboxesc                   b    e Zd ZdZdddZd Zd Zd Zd Zd	 Z	e
dd
ed    dd fd       ZddZy)r    a  
    A class for handling bounding boxes.

    The class supports various bounding box formats like 'xyxy', 'xywh', and 'ltwh'.
    Bounding box data should be provided in numpy arrays.

    Attributes:
        bboxes (numpy.ndarray): The bounding boxes stored in a 2D numpy array.
        format (str): The format of the bounding boxes ('xyxy', 'xywh', or 'ltwh').

    Note:
        This class does not handle normalization or denormalization of bounding boxes.
    returnNc                     |t         v sJ d| dt                 |j                  dk(  r	|dddf   n|}|j                  dk(  sJ |j                  d   dk(  sJ || _        || _        y)zJInitializes the Bboxes class with bounding box data in a specified format.Invalid bounding box format: , format must be one of r   Nr   r   )_formatsndimshapebboxesformat)selfr)   r*   s      r   __init__zBboxes.__init__1   sv    !m%B6(Jbckbl#mm!$*KK1$4a&{{a||A!###r   c                 8   |t         v sJ d| dt                 | j                  |k(  ry| j                  dk(  r|dk(  rt        nt        }n2| j                  dk(  r|dk(  rt        nt
        }n|dk(  rt        nt        } || j                        | _        || _        y)z6Converts bounding box format from one type to another.r$   r%   Nr   r   )	r&   r*   r   r   r   r   r	   r   r)   )r+   r*   funcs      r   convertzBboxes.convert;   s    !m%B6(Jbckbl#mm!;;& [[F" && 09iD[[F" && 09iD && 09iD4;;'r   c                     | j                  d       | j                  dddf   | j                  dddf   z
  | j                  dddf   | j                  dddf   z
  z  S )zReturn box areas.r   Nr   r      r   )r/   r)   r+   s    r   areaszBboxes.areasI   sZ    VAqD!DKK1$55$++ad:KdkkZ[]^Z^N_:_``r   c                 z   t        |t              rt        |      }t        |t        t        f      sJ t        |      dk(  sJ | j                  dddfxx   |d   z  cc<   | j                  dddfxx   |d   z  cc<   | j                  dddfxx   |d   z  cc<   | j                  dddfxx   |d   z  cc<   y)zZ
        Args:
            scale (tuple | list | int): the scale for four coords.
        r   Nr   r   r   r1   r   r   	to_4tupler   listlenr)   )r+   scales     r   mulz
Bboxes.mul^   s    
 eV$e$E%%///5zQAqDU1X%AqDU1X%AqDU1X%AqDU1X%r   c                 z   t        |t              rt        |      }t        |t        t        f      sJ t        |      dk(  sJ | j                  dddfxx   |d   z  cc<   | j                  dddfxx   |d   z  cc<   | j                  dddfxx   |d   z  cc<   | j                  dddfxx   |d   z  cc<   y)z\
        Args:
            offset (tuple | list | int): the offset for four coords.
        r   Nr   r   r   r1   r5   )r+   offsets     r   addz
Bboxes.addl   s    
 ff%v&F&5$-0006{aAqDVAY&AqDVAY&AqDVAY&AqDVAY&r   c                 ,    t        | j                        S )zReturn the number of boxes.r8   r)   r2   s    r   __len__zBboxes.__len__z       4;;r   
boxes_listc                 .   t        |t        t        f      sJ |s | t        j                  d            S t        d |D              sJ t        |      dk(  r|d   S  | t        j                  |D cg c]  }|j                   c}|            S c c}w )a  
        Concatenate a list of Bboxes objects into a single Bboxes object.

        Args:
            boxes_list (List[Bboxes]): A list of Bboxes objects to concatenate.
            axis (int, optional): The axis along which to concatenate the bounding boxes.
                                   Defaults to 0.

        Returns:
            Bboxes: A new Bboxes object containing the concatenated bounding boxes.

        Note:
            The input should be a list or tuple of Bboxes objects.
        r   c              3   <   K   | ]  }t        |t                y wN)r   r    ).0boxs     r   	<genexpr>z%Bboxes.concatenate.<locals>.<genexpr>   s     Ajs:c6*j   r   axis)	r   r7   r   npemptyallr8   concatenater)   )clsrB   rK   bs       r   rO   zBboxes.concatenate~   s      *tUm444rxx{##AjAAAAz?aa= 2>>Z"@Z188Z"@tLMM"@s   2Bc                     t        |t              r(t        | j                  |   j	                  dd            S | j                  |   }|j
                  dk(  sJ d| d       t        |      S )a  
        Retrieve a specific bounding box or a set of bounding boxes using indexing.

        Args:
            index (int, slice, or np.ndarray): The index, slice, or boolean array to select
                                               the desired bounding boxes.

        Returns:
            Bboxes: A new Bboxes object containing the selected bounding boxes.

        Raises:
            AssertionError: If the indexed bounding boxes do not form a 2-dimensional matrix.

        Note:
            When using boolean indexing, make sure to provide a boolean array with the same
            length as the number of bounding boxes.
        r   r   zIndexing on Bboxes with z failed to return a matrix!)r   intr    r)   viewr'   )r+   indexrQ   s      r   __getitem__zBboxes.__getitem__   sg    $ eS!$++e,11!R899KKvv{Y6ug=XYY{ayr   )r   r"   Nr   )r"   r    )__name__
__module____qualname____doc__r,   r/   r3   r:   r=   r@   classmethodr   rO   rW   r   r   r   r    r    "   sU    a*&'  NT(^ N N N0r   r    c                       e Zd ZdZdddZd Zed        ZddZd Z	d	 Z
d
 ZddZd Zd Zd Zd ZddZd Zedded    dd fd       Zed        Zy)	Instancesa  
    Container for bounding boxes, segments, and keypoints of detected objects in an image.

    Attributes:
        _bboxes (Bboxes): Internal object for handling bounding box operations.
        keypoints (ndarray): keypoints(x, y, visible) with shape [N, 17, 3]. Default is None.
        normalized (bool): Flag indicating whether the bounding box coordinates are normalized.
        segments (ndarray): Segments array with shape [N, 1000, 2] after resampling.

    Args:
        bboxes (ndarray): An array of bounding boxes with shape [N, 4].
        segments (list | ndarray, optional): A list or array of object segments. Default is None.
        keypoints (ndarray, optional): An array of keypoints with shape [N, 17, 3]. Default is None.
        bbox_format (str, optional): The format of bounding boxes ('xywh' or 'xyxy'). Default is 'xywh'.
        normalized (bool, optional): Whether the bounding box coordinates are normalized. Default is True.

    Examples:
        ```python
        # Create an Instances object
        instances = Instances(
            bboxes=np.array([[10, 10, 30, 30], [20, 20, 40, 40]]),
            segments=[np.array([[5, 5], [10, 10]]), np.array([[15, 15], [20, 20]])],
            keypoints=np.array([[[5, 5, 1], [10, 10, 1]], [[15, 15, 1], [20, 20, 1]]])
        )
        ```

    Note:
        The bounding box format is either 'xywh' or 'xyxy', and is determined by the `bbox_format` argument.
        This class does not perform input validation, and it assumes the inputs are well-formed.
    Nr"   c                    |g }t        ||      | _        || _        || _        t	        |      dkD  r*t        |      }t        j                  |d      }|| _
        yt        j                  dt        j                        }|| _
        y)z
        Args:
            bboxes (ndarray): bboxes with shape [N, 4].
            segments (list | ndarray): segments.
            keypoints (ndarray): keypoints(x, y, visible) with shape [N, 17, 3].
        N)r)   r*   r   rJ   )r   i  r   )dtype)r    _bboxes	keypoints
normalizedr8   r
   rL   stackzerosfloat32segments)r+   r)   ri   rd   bbox_formatre   s         r   r,   zInstances.__init__   sw     HVK@"$x=1(2Hxxq1H ! xxBJJ?H r   c                 <    | j                   j                  |       y)zConvert bounding box format.r*   N)rc   r/   )r+   r*   s     r   convert_bboxzInstances.convert_bbox   s    F+r   c                 6    | j                   j                         S )z%Calculate the area of bounding boxes.)rc   r3   r2   s    r   
bbox_areaszInstances.bbox_areas   s     ||!!##r   c                    | j                   j                  ||||f       |ry| j                  dxx   |z  cc<   | j                  dxx   |z  cc<   | j                  /| j                  dxx   |z  cc<   | j                  dxx   |z  cc<   yy)zHThis might be similar with denormalize func but without normalized sign.r9   N.r   .r   )rc   r:   ri   rd   )r+   scale_wscale_h	bbox_onlys       r   r9   zInstances.scale   s    '7CDf(f(>>%NN6"g-"NN6"g-" &r   c                 <   | j                   sy| j                  j                  ||||f       | j                  dxx   |z  cc<   | j                  dxx   |z  cc<   | j                  .| j                  dxx   |z  cc<   | j                  dxx   |z  cc<   d| _         y)zHDenormalizes boxes, segments, and keypoints from normalized coordinates.Nrq   rr   rs   Fre   rc   r:   ri   rd   r+   whs      r   denormalizezInstances.denormalize   s    1a|,f"f">>%NN6"a'"NN6"a'"r   c                 T   | j                   ry| j                  j                  d|z  d|z  d|z  d|z  f       | j                  dxx   |z  cc<   | j                  dxx   |z  cc<   | j                  .| j                  dxx   |z  cc<   | j                  dxx   |z  cc<   d| _         y)zFNormalize bounding boxes, segments, and keypoints to image dimensions.Nr   rq   rr   rs   Trx   ry   s      r   	normalizezInstances.normalize  s    ??Aq1ua!eQU;<f"f">>%NN6"a'"NN6"a'"r   c                 <   | j                   rJ d       | j                  j                  ||||f       | j                  dxx   |z  cc<   | j                  dxx   |z  cc<   | j                  /| j                  dxx   |z  cc<   | j                  dxx   |z  cc<   yy)z!Handle rect and mosaic situation.z1you should add padding with absolute coordinates.)r<   rr   rs   N)re   rc   r=   ri   rd   )r+   padwpadhs      r   add_paddingzInstances.add_padding  s    ??W$WW"tT4 89f%f%>>%NN6"d*"NN6"d*" &r   c                    t        | j                        r| j                  |   n| j                  }| j                  | j                  |   nd}| j                  |   }| j                  j
                  }t        ||||| j                        S )aB  
        Retrieve a specific instance or a set of instances using indexing.

        Args:
            index (int, slice, or np.ndarray): The index, slice, or boolean array to select
                                               the desired instances.

        Returns:
            Instances: A new Instances object containing the selected bounding boxes,
                       segments, and keypoints if present.

        Note:
            When using boolean indexing, make sure to provide a boolean array with the same
            length as the number of instances.
        N)r)   ri   rd   rj   re   )r8   ri   rd   r)   rc   r*   r`   re   )r+   rV   ri   rd   r)   rj   s         r   rW   zInstances.__getitem__  sy      ,/t}}+=4=='4==-1^^-GDNN5)T	U#ll))#
 	
r   c                    | j                   j                  dk(  ro| j                  dddf   j                         }| j                  dddf   j                         }||z
  | j                  dddf<   ||z
  | j                  dddf<   n'|| j                  dddf   z
  | j                  dddf<   || j                  d   z
  | j                  d<   | j
                   || j
                  d   z
  | j
                  d<   yy)zLFlips the coordinates of bounding boxes, segments, and keypoints vertically.r   Nr   r1   rs   rc   r*   r)   copyri   rd   )r+   r{   y1y2s       r   flipudzInstances.flipud8      <<&(QT"'')BQT"'')B !BDKK1 !BDKK1 !DKK1$5 5DKK1 !DMM&$9 9f>>%%&)?%?DNN6" &r   c                    | j                   j                  dk(  ro| j                  dddf   j                         }| j                  dddf   j                         }||z
  | j                  dddf<   ||z
  | j                  dddf<   n'|| j                  dddf   z
  | j                  dddf<   || j                  d   z
  | j                  d<   | j
                   || j
                  d   z
  | j
                  d<   yy)zCReverses the order of the bounding boxes and segments horizontally.r   Nr   r   rr   r   )r+   rz   x1x2s       r   fliplrzInstances.fliplrE  r   r   c                    | j                   j                  }| j                  d       | j                  ddddgf   j	                  d|      | j                  ddddgf<   | j                  ddddgf   j	                  d|      | j                  ddddgf<   |dk7  r| j                  |       | j
                  d   j	                  d|      | j
                  d<   | j
                  d	   j	                  d|      | j
                  d	<   | j                  Y| j                  d   j	                  d|      | j                  d<   | j                  d	   j	                  d|      | j                  d	<   yy)
zUClips bounding boxes, segments, and keypoints values to stay within image boundaries.r   rl   Nr   r   r   r1   rr   rs   )rc   r*   rm   r)   clipri   rd   )r+   rz   r{   
ori_formats       r   r   zInstances.clipR  sB   \\((
(!%QAY!7!<!<Q!BA1vI!%QAY!7!<!<Q!BA1vIZ0 $f 5 : :1a @f $f 5 : :1a @f>>%%)^^F%;%@%@A%FDNN6"%)^^F%;%@%@A%FDNN6" &r   c                     | j                   dkD  }t        |      s]| j                  |   | _        t        | j                        r| j                  |   | _        | j
                  | j
                  |   | _        |S )z
        Remove zero-area boxes, i.e. after clipping some boxes may have zero width or height.

        This removes them.
        r   )ro   rN   rc   r8   ri   rd   )r+   goods     r   remove_zero_area_boxesz Instances.remove_zero_area_boxes`  sd     "4y<<-DL4==! $d 3~~)!%!5r   c                 v    t        || j                  j                        | _        ||| _        ||| _        yy)zUpdates instance variables.rl   N)r    rc   r*   ri   rd   )r+   r)   ri   rd   s       r   updatezInstances.updateo  s9    fT\\-@-@A$DM &DN !r   c                 ,    t        | j                        S )z'Return the length of the instance list.r?   r2   s    r   r@   zInstances.__len__w  rA   r   instances_listc                    t        |t        t        f      sJ |s | t        j                  d            S t        d |D              sJ t        |      dk(  r|d   S |d   j                  du}|d   j                  j                  }|d   j                  }t        j                  |D cg c]  }|j                   c}|      }t        j                  |D cg c]  }|j                   c}|      }	|r/t        j                  |D cg c]  }|j                   c}|      nd}
 | ||	|
||      S c c}w c c}w c c}w )a  
        Concatenates a list of Instances objects into a single Instances object.

        Args:
            instances_list (List[Instances]): A list of Instances objects to concatenate.
            axis (int, optional): The axis along which the arrays will be concatenated. Defaults to 0.

        Returns:
            Instances: A new Instances object containing the concatenated bounding boxes,
                       segments, and keypoints if present.

        Note:
            The `Instances` objects in the list should have the same properties, such as
            the format of the bounding boxes, whether keypoints are present, and if the
            coordinates are normalized.
        r   c              3   <   K   | ]  }t        |t                y wrE   )r   r`   )rF   instances     r   rH   z(Instances.concatenate.<locals>.<genexpr>  s     R>x:h	2>rI   r   NrJ   )r   r7   r   rL   rM   rN   r8   rd   rc   r*   re   rO   r)   ri   )rP   r   rK   use_keypointrj   re   ins	cat_boxesrQ   cat_segmentscat_keypointss              r   rO   zInstances.concatenate{  s%   $ .4-888rxx{##R>RRRR~!#!!$$%a(22$>$Q'//66#A&11
NN.#I.3CJJ.#IPTU	~~>&J>aqzz>&JQUV\h^'L^^'LSWXnr9lM;
SS $J&J'Ls   )D3D8	D=c                 .    | j                   j                  S )zReturn bounding boxes.)rc   r)   r2   s    r   r)   zInstances.bboxes  s     ||"""r   )NNr   TrX   )F)r"   r`   )NNrY   )rZ   r[   r\   r]   r,   rm   propertyro   r9   r|   r~   r   rW   r   r   r   r   r   r@   r^   r   rO   r)   r   r   r   r`   r`      s    >!,, $ $	.
 
+
8@@G'   Tk):  T{  T  TD # #r   r`   )collectionsr   	itertoolsr   numbersr   typingr   numpyrL   opsr   r	   r
   r   r   r   r   r   	to_2tupler6   r&   __all__r    r`   r   r   r   <module>r      s]         d d d AJ	AJ	
 $
K K\q# q#r   