a
    yfy?                     @   s   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 dd	 Zed
ZedZg dZdZG dd dZG dd dZdS )    )abc)repeat)Number)ListN   )	ltwh2xywh	ltwh2xyxy	xywh2ltwh	xywh2xyxy	xyxy2ltwh	xyxy2xywhc                    s    fdd}|S )zFrom PyTorch internals.c                    s   t | tjr| S tt|  S )z2Parse bounding boxes format between XYWH and LTWH.)
isinstancer   Iterabletupler   )xn V/var/www/html/django/DPS/env/lib/python3.9/site-packages/ultralytics/utils/instance.pyparse   s    z_ntuple.<locals>.parser   )r   r   r   r   r   _ntuple   s    r         )xyxyxywhZltwh)Bboxesc                   @   sp   e Zd ZdZdddddZdd Zd	d
 Zdd Zdd Zdd Z	e
ded  d dddZd dddZdS )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.
    r   Nreturnc                 C   sj   |t v sJ d| dt  |jdkr6|dddf n|}|jdksHJ |jd dksZJ || _|| _dS )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$   r   r   r   __init__1   s    zBboxes.__init__c                 C   s   |t v sJ d| dt  | j|kr*dS | jdkrF|dkr@tnt}n,| jdkrb|dkr\tnt}n|dkrntnt}|| j| _|| _dS )z6Converts bounding box format from one type to another.r   r   Nr   r   )	r    r$   r   r   r
   r	   r   r   r#   )r%   r$   funcr   r   r   convert;   s    


zBboxes.convertc                 C   sv   | j dkrR| jdddf | jdddf  | jdddf | jdddf   S | jdddf | jdddf  S )zReturn box areas.r   Nr   r      r   )r$   r#   r%   r   r   r   areasI   s    J"zBboxes.areasc                 C   s   t |trt|}t |ttfs$J t|dks4J | jdddf  |d 9  < | jdddf  |d 9  < | jdddf  |d 9  < | jdddf  |d 9  < dS )z
        Multiply bounding box coordinates by scale factor(s).

        Args:
            scale (int | tuple | list): Scale factor(s) for four coordinates.
                If int, the same scale is applied to all coordinates.
        r   Nr   r   r   r)   r   r   	to_4tupler   listlenr#   )r%   scaler   r   r   mula   s    
z
Bboxes.mulc                 C   s   t |trt|}t |ttfs$J t|dks4J | jdddf  |d 7  < | jdddf  |d 7  < | jdddf  |d 7  < | jdddf  |d 7  < dS )z
        Add offset to bounding box coordinates.

        Args:
            offset (int | tuple | list): Offset(s) for four coordinates.
                If int, the same offset is applied to all coordinates.
        r   Nr   r   r   r)   r,   )r%   offsetr   r   r   addr   s    
z
Bboxes.addc                 C   s
   t | jS )zReturn the number of boxes.r/   r#   r*   r   r   r   __len__   s    zBboxes.__len__r   )
boxes_listr   c                 C   sj   t |ttfsJ |s$| tdS tdd |D s:J t|dkrN|d S | tjdd |D |dS )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                 s   s   | ]}t |tV  qd S N)r   r   ).0boxr   r   r   	<genexpr>       z%Bboxes.concatenate.<locals>.<genexpr>r   c                 S   s   g | ]
}|j qS r   r#   r8   br   r   r   
<listcomp>   r;   z&Bboxes.concatenate.<locals>.<listcomp>axis)r   r.   r   npemptyallr/   concatenate)clsr6   rA   r   r   r   rE      s    zBboxes.concatenatec                 C   sL   t |tr t| j| ddS | j| }|jdksDJ 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%   indexr>   r   r   r   __getitem__   s
    

zBboxes.__getitem__)r   )r   )__name__
__module____qualname____doc__r&   r(   r+   r1   r3   r5   classmethodr   rE   rK   r   r   r   r   r   "   s   
r   c                   @   s   e Zd ZdZd)ddddZdd	 Zed
d Zd*ddZdd Z	dd Z
dd Zd dddZdd Zdd Zdd Zdd Zd+dd Zd!d" Zed,ed  d d$d%d&Zed'd( ZdS )-	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   Tr   c                 C   s$   t ||d| _|| _|| _|| _dS )a'  
        Initialize the object with bounding boxes, segments, and keypoints.

        Args:
            bboxes (np.ndarray): Bounding boxes, shape [N, 4].
            segments (list | np.ndarray, optional): Segmentation masks. Defaults to None.
            keypoints (np.ndarray, optional): Keypoints, shape [N, 17, 3] and format (x, y, visible). Defaults to None.
            bbox_format (str, optional): Format of bboxes. Defaults to "xywh".
            normalized (bool, optional): Whether the coordinates are normalized. Defaults to True.
        )r#   r$   N)r   _bboxes	keypoints
normalizedsegments)r%   r#   rU   rS   bbox_formatrT   r   r   r   r&      s    zInstances.__init__c                 C   s   | j j|d dS )zConvert bounding box format.r$   N)rR   r(   )r%   r$   r   r   r   convert_bbox   s    zInstances.convert_bboxc                 C   s
   | j  S )z%Calculate the area of bounding boxes.)rR   r+   r*   r   r   r   
bbox_areas   s    zInstances.bbox_areasFc                 C   st   | j j||||fd |rdS | jd  |9  < | jd  |9  < | jdurp| jd  |9  < | jd  |9  < dS )z8Similar to denormalize func but without normalized sign.r0   N.r   .r   )rR   r1   rU   rS   )r%   Zscale_wZscale_hZ	bbox_onlyr   r   r   r0      s    
zInstances.scalec                 C   s|   | j s
dS | jj||||fd | jd  |9  < | jd  |9  < | jdurr| jd  |9  < | jd  |9  < d| _ dS )zHDenormalizes boxes, segments, and keypoints from normalized coordinates.NrZ   r[   r\   FrT   rR   r1   rU   rS   r%   whr   r   r   denormalize   s    
zInstances.denormalizec                 C   s   | j r
dS | jjd| d| d| d| fd | jd  |  < | jd  |  < | jdur| jd  |  < | jd  |  < d| _ dS )zFNormalize bounding boxes, segments, and keypoints to image dimensions.Nr   rZ   r[   r\   Tr]   r^   r   r   r   	normalize	  s    &
zInstances.normalizec                 C   sz   | j rJ d| jj||||fd | jd  |7  < | jd  |7  < | jdurv| jd  |7  < | jd  |7  < dS )z!Handle rect and mosaic situation.z1you should add padding with absolute coordinates.)r2   r[   r\   N)rT   rR   r3   rU   rS   )r%   ZpadwZpadhr   r   r   add_padding  s    
zInstances.add_paddingc                 C   sX   t | jr| j| n| j}| jdur.| j| nd}| j| }| jj}t||||| jd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#   rU   rS   rV   rT   )r/   rU   rS   r#   rR   r$   rQ   rT   )r%   rJ   rU   rS   r#   rV   r   r   r   rK     s    
zInstances.__getitem__c                 C   s   | j jdkrf| jdddf  }| jdddf  }|| | jdddf< || | jdddf< n$|| jdddf  | jdddf< || jd  | jd< | jdur|| jd  | jd< dS )zLFlips the coordinates of bounding boxes, segments, and keypoints vertically.r   Nr   r)   r\   rR   r$   r#   copyrU   rS   )r%   r`   y1y2r   r   r   flipud;  s    $
zInstances.flipudc                 C   s   | j jdkrf| jdddf  }| jdddf  }|| | jdddf< || | jdddf< n$|| jdddf  | jdddf< || jd  | jd< | jdur|| jd  | jd< dS )zCReverses the order of the bounding boxes and segments horizontally.r   Nr   r   r[   rd   )r%   r_   x1Zx2r   r   r   fliplrH  s    $
zInstances.fliplrc                 C   s   | j j}| jdd | jddddgf d|| jddddgf< | jddddgf d|| jddddgf< |dkr| j|d | jd d|| jd< | jd	 d|| jd	< | jdur| jd d|| jd< | jd	 d|| jd	< dS )
zUClips bounding boxes, segments, and keypoints values to stay within image boundaries.r   rW   Nr   r   r   r)   r[   r\   )rR   r$   rX   r#   cliprU   rS   )r%   r_   r`   Z
ori_formatr   r   r   rk   U  s    00
zInstances.clipc                 C   sN   | j dk}t|sJ| j| | _t| jr4| j| | _| jdurJ| j| | _|S )zURemove zero-area boxes, i.e. after clipping some boxes may have zero width or height.r   N)rY   rD   rR   r/   rU   rS   )r%   Zgoodr   r   r   remove_zero_area_boxesc  s    


z Instances.remove_zero_area_boxesc                 C   s2   t || jjd| _|dur || _|dur.|| _dS )zUpdates instance variables.rW   N)r   rR   r$   rU   rS   )r%   r#   rU   rS   r   r   r   updaten  s
    zInstances.updatec                 C   s
   t | jS )z'Return the length of the instance list.r4   r*   r   r   r   r5   v  s    zInstances.__len__r   )instances_listr   c           	      C   s   t |ttfsJ |s$| tdS tdd |D s:J t|dkrN|d S |d jdu}|d jj	}|d j
}tjdd |D |d}tjd	d |D |d}|rtjd
d |D |dnd}| |||||S )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                 s   s   | ]}t |tV  qd S r7   )r   rQ   )r8   instancer   r   r   r:     r;   z(Instances.concatenate.<locals>.<genexpr>r   Nc                 S   s   g | ]
}|j qS r   r<   )r8   Zinsr   r   r   r?     r;   z)Instances.concatenate.<locals>.<listcomp>r@   c                 S   s   g | ]
}|j qS r   )rU   r=   r   r   r   r?     r;   c                 S   s   g | ]
}|j qS r   )rS   r=   r   r   r   r?     r;   )r   r.   r   rB   rC   rD   r/   rS   rR   r$   rT   rE   )	rF   rn   rA   Zuse_keypointrV   rT   Z	cat_boxesZcat_segmentsZcat_keypointsr   r   r   rE   z  s    
 zInstances.concatenatec                 C   s   | j jS )zReturn bounding boxes.)rR   r#   r*   r   r   r   r#     s    zInstances.bboxes)NNr   T)F)NN)r   )rL   rM   rN   rO   r&   rX   propertyrY   r0   ra   rb   rc   rK   rh   rj   rk   rl   rm   r5   rP   r   rE   r#   r   r   r   r   rQ      s(   



"rQ   )collectionsr   	itertoolsr   numbersr   typingr   numpyrB   opsr   r   r	   r
   r   r   r   Z	to_2tupler-   r    __all__r   rQ   r   r   r   r   <module>   s    
 