a
    d
[                     @   sh  d dl Z d dlmZmZ d dlZddlmZ g dZejj	ej
edddZejj	ej
edd	d
Zej
eej
ej
f dddZej
eej
ej
ej
f dddZej
eeej
dddZej
eeeef ej
dddZej
ej
ej
ej
ej
dddZej
ej
ej
ej
ej
ej
ej
dddZd"ej
ej
eee ej
dddZej
ej
eej
dd d!ZdS )#    N)OptionalTuple   )transform_points)
validate_bboxvalidate_bbox3dinfer_bbox_shapeinfer_bbox_shape3dbbox_to_maskbbox_to_mask3dbbox_generatorbbox_generator3dtransform_bboxnms)boxesreturnc              	   C   s  t | jdv r*| jdd tddgks<td| j dt | jdkrX| ddd} tj| ddd	d
f | ddd
d
f  d	 | dddd
f | dddd
f  d	 ddstdt| ddd	d
f | ddd
d
f  d	 t| dddd
f | dddd
f  d	 f tj| dddd	f | ddd
d	f  d	 | dddd	f | ddd	d	f  d	 ddstdt| dddd	f | ddd
d	f  d	 t| dddd	f | ddd	d	f  d	 f dS )a  Validate if a 2D bounding box usable or not. This function checks if the boxes are rectangular or not.

    Args:
        boxes: a tensor containing the coordinates of the bounding boxes to be extracted. The tensor must have the shape
            of Bx4x2, where each box is defined in the following ``clockwise`` order: top-left, top-right, bottom-right,
            bottom-left. The coordinates must be in the x, y order.
          Nr      z1Box shape must be (B, 4, 2) or (B, N, 4, 2). Got .r   r   r   g-C6?)Zatolz:Boxes must have be rectangular, while get widths %s and %sz;Boxes must have be rectangular, while get heights %s and %sT)	lenshapetorchSizeAssertionErrorviewallclose
ValueErrorstr)r    r"   ]/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/kornia/geometry/bbox.pyr      s"    	*ZVZVr   c              	   C   s  t | jdv r*| jdd tddgks<td| j dt | jdkrX| d	dd} t| d
tjg d| jtj	ddddddf }t| d
tjg d| jtj	ddddddf }|| d
 }t
|d
d|dddf std| dt| d
tjg d| jtj	dddddd
f }t| d
tjg d| jtj	dddddd
f }|| d
 }t
|d
d|dddf std| d| dddddf | dddddf  d
 }t
|d
d|dddf std| ddS )a  Validate if a 3D bounding box usable or not. This function checks if the boxes are cube or not.

    Args:
        boxes: a tensor containing the coordinates of the bounding boxes to be extracted. The tensor must have the shape
            of Bx8x3, where each box is defined in the following ``clockwise`` order: front-top-left, front-top-right,
            front-bottom-right, front-bottom-left, back-top-left, back-top-right, back-bottom-right, back-bottom-left.
            The coordinates must be in the x, y, z order.
    r   r   N   r   z1Box shape must be (B, 8, 3) or (B, N, 8, 3). Got r   r   r   r   r   r         devicedtyper   r   r   r      z4Boxes must have be cube, while get different widths r   r   r'   r,   r   r   r   r&   z5Boxes must have be cube, while get different heights r   z4Boxes must have be cube, while get different depths T)r   r   r   r   r   r   index_selecttensorr)   longr   Zpermuter   leftrightZwidthsZbotupperZheightsZdepthsr"   r"   r#   r   4   s$    
*44 44"0"r   c                 C   s`   t |  | ddddf | ddddf  d }| ddddf | ddddf  d }||fS )ay  Auto-infer the output sizes for the given 2D bounding boxes.

    Args:
        boxes: a tensor containing the coordinates of the bounding boxes to be extracted. The tensor must have the shape
            of Bx4x2, where each box is defined in the following ``clockwise`` order: top-left, top-right, bottom-right,
            bottom-left. The coordinates must be in the x, y order.

    Returns:
        - Bounding box heights, shape of :math:`(B,)`.
        - Boundingbox widths, shape of :math:`(B,)`.

    Example:
        >>> boxes = torch.tensor([[
        ...     [1., 1.],
        ...     [2., 1.],
        ...     [2., 2.],
        ...     [1., 2.],
        ... ], [
        ...     [1., 1.],
        ...     [3., 1.],
        ...     [3., 2.],
        ...     [1., 2.],
        ... ]])  # 2x4x2
        >>> infer_bbox_shape(boxes)
        (tensor([2., 2.]), tensor([2., 3.]))
    Nr   r   r   )r   )r   widthheightr"   r"   r#   r   W   s    ((r   c              	   C   sN  t |  t| dtjg d| jtjddddddf }t| dtjg d| jtjddddddf }|| d dddf }t| dtjg d| jtjddddddf }t| dtjg d| jtjddddddf }|| d dddf }| ddd	dd
f | dddd	d
f  d dddf }|||fS )aK  Auto-infer the output sizes for the given 3D bounding boxes.

    Args:
        boxes: a tensor containing the coordinates of the bounding boxes to be extracted. The tensor must have the shape
            of Bx8x3, where each box is defined in the following ``clockwise`` order: front-top-left, front-top-right,
            front-bottom-right, front-bottom-left, back-top-left, back-top-right, back-bottom-right, back-bottom-left.
            The coordinates must be in the x, y, z order.

    Returns:
        - Bounding box depths, shape of :math:`(B,)`.
        - Bounding box heights, shape of :math:`(B,)`.
        - Bounding box widths, shape of :math:`(B,)`.

    Example:
        >>> boxes = torch.tensor([[[ 0,  1,  2],
        ...         [10,  1,  2],
        ...         [10, 21,  2],
        ...         [ 0, 21,  2],
        ...         [ 0,  1, 32],
        ...         [10,  1, 32],
        ...         [10, 21, 32],
        ...         [ 0, 21, 32]],
        ...        [[ 3,  4,  5],
        ...         [43,  4,  5],
        ...         [43, 54,  5],
        ...         [ 3, 54,  5],
        ...         [ 3,  4, 65],
        ...         [43,  4, 65],
        ...         [43, 54, 65],
        ...         [ 3, 54, 65]]]) # 2x8x3
        >>> infer_bbox_shape3d(boxes)
        (tensor([31, 61]), tensor([21, 51]), tensor([11, 41]))
    r   r%   r(   Nr   r+   r-   r.   r   r   )r   r   r/   r0   r)   r1   r2   r"   r"   r#   r	   x   s    "4444<r	   )r   r6   r7   r   c                 C   s   t |  tjt| |d |d ftj| jd}| d  }t||D ]4\}}d||d |d d |d |d d f< qD|d	d	dd
dd
f S )a  Convert 2D bounding boxes to masks. Covered area is 1. and the remaining is 0.

    Args:
        boxes: a tensor containing the coordinates of the bounding boxes to be extracted. The tensor must have the shape
            of Bx4x2, where each box is defined in the following ``clockwise`` order: top-left, top-right, bottom-right
            and bottom-left. The coordinates must be in the x, y order.
        width: width of the masked image.
        height: height of the masked image.

    Returns:
        the output mask tensor.

    Note:
        It is currently non-differentiable.

    Examples:
        >>> boxes = torch.tensor([[
        ...        [1., 1.],
        ...        [3., 1.],
        ...        [3., 2.],
        ...        [1., 2.],
        ...   ]])  # 1x4x2
        >>> bbox_to_mask(boxes, 5, 5)
        tensor([[[0., 0., 0., 0., 0.],
                 [0., 1., 1., 1., 0.],
                 [0., 1., 1., 1., 0.],
                 [0., 0., 0., 0., 0.],
                 [0., 0., 0., 0., 0.]]])
    r   )r*   r)   r   g      ?r   r   r   r   r   r   r   r   Nr   )r   r   zerosr   floatr)   r1   zip)r   r6   r7   maskZbox_iZmskbxr"   r"   r#   r
      s    &.r
   )r   sizer   c              
   C   s  t |  tt| g|R }g }t|| D ]T\}}|dtj|d  |d  d |jtj	dtj
d|j|jd}|dtj|d  |d  d |jtj	dtj
d|j|jd}|dtj|d	  |d
  d |jtj	dtj
d|j|jd}|jdd}t|}||dkjdddjddd }||dkjdddjddd }||dkjdddjddd }|| q,tj|dd S )aH  Convert 3D bounding boxes to masks. Covered area is 1. and the remaining is 0.

    Args:
        boxes: a tensor containing the coordinates of the bounding boxes to be extracted. The tensor must have the shape
            of Bx8x3, where each box is defined in the following ``clockwise`` order: front-top-left, front-top-right,
            front-bottom-right, front-bottom-left, back-top-left, back-top-right, back-bottom-right, back-bottom-left.
            The coordinates must be in the x, y, z order.
        size: depth, height and width of the masked image.

    Returns:
        the output mask tensor.

    Examples:
        >>> boxes = torch.tensor([[
        ...     [1., 1., 1.],
        ...     [2., 1., 1.],
        ...     [2., 2., 1.],
        ...     [1., 2., 1.],
        ...     [1., 1., 2.],
        ...     [2., 1., 2.],
        ...     [2., 2., 2.],
        ...     [1., 2., 2.],
        ... ]])  # 1x8x3
        >>> bbox_to_mask3d(boxes, (4, 5, 5))
        tensor([[[[[0., 0., 0., 0., 0.],
                   [0., 0., 0., 0., 0.],
                   [0., 0., 0., 0., 0.],
                   [0., 0., 0., 0., 0.],
                   [0., 0., 0., 0., 0.]],
        <BLANKLINE>
                  [[0., 0., 0., 0., 0.],
                   [0., 1., 1., 0., 0.],
                   [0., 1., 1., 0., 0.],
                   [0., 0., 0., 0., 0.],
                   [0., 0., 0., 0., 0.]],
        <BLANKLINE>
                  [[0., 0., 0., 0., 0.],
                   [0., 1., 1., 0., 0.],
                   [0., 1., 1., 0., 0.],
                   [0., 0., 0., 0., 0.],
                   [0., 0., 0., 0., 0.]],
        <BLANKLINE>
                  [[0., 0., 0., 0., 0.],
                   [0., 0., 0., 0., 0.],
                   [0., 0., 0., 0., 0.],
                   [0., 0., 0., 0., 0.],
                   [0., 0., 0., 0., 0.]]]]])
    r   )r   r   )r   r   r   r(   )r   r   r9   r   r:   r;   dimT)rC   Zkeepdimr   )r   r   r<   r   r>   Z
index_fillZarangeitemr)   r1   r0   r*   	unsqueezeZ	ones_likeallappendstackr=   )r   rA   r?   Zmask_outmZboxZm_outr"   r"   r#   r      s4    1(((
   r   )x_starty_startr6   r7   r   c              
   C   s  | j |j kr|  dv s.td|  d| d|j |j krF| dv s\td| d| d| j|j  kr|j  kr|jksn td| j d| j d|j d	|j d
	| j|j  kr|j  kr|jksn td| j d| j d|j d	|j d
	tjddgddgddgddggg| j| jd|  dkrBdnt| dd}|dddddf  | 	dd7  < |dddddf  |	dd7  < |ddddf  |d 7  < |ddddf  |d 7  < |ddddf  |d 7  < |ddddf  |d 7  < |S )aN  Generate 2D bounding boxes according to the provided start coords, width and height.

    Args:
        x_start: a tensor containing the x coordinates of the bounding boxes to be extracted. Shape must be a scalar
            tensor or :math:`(B,)`.
        y_start: a tensor containing the y coordinates of the bounding boxes to be extracted. Shape must be a scalar
            tensor or :math:`(B,)`.
        width: widths of the masked image. Shape must be a scalar tensor or :math:`(B,)`.
        height: heights of the masked image. Shape must be a scalar tensor or :math:`(B,)`.

    Returns:
        the bounding box tensor.

    Examples:
        >>> x_start = torch.tensor([0, 1])
        >>> y_start = torch.tensor([1, 0])
        >>> width = torch.tensor([5, 3])
        >>> height = torch.tensor([7, 4])
        >>> bbox_generator(x_start, y_start, width, height)
        tensor([[[0, 1],
                 [4, 1],
                 [4, 7],
                 [0, 7]],
        <BLANKLINE>
                [[1, 0],
                 [3, 0],
                 [3, 3],
                 [1, 3]]])
    r8   z6`x_start` and `y_start` must be a scalar or (B,). Got , r   z3`width` and `height` must be a scalar or (B,). Got 5All tensors must be in the same dtype. Got `x_start`(), `y_start`(), `width`(), `height`().6All tensors must be in the same device. Got `x_start`(r   r(   r   Nr   r   r   )
r   rC   r   r*   r)   r   r0   repeatr   r   )rJ   rK   r6   r7   bboxr"   r"   r#   r   "  sL     (*.&&r   )rJ   rK   z_startr6   r7   depthr   c                 C   s  | j |j   kr|j kr*n n|  dv sFtd|  d| d| d|j |j   kr`|j krpn n| dv std| d| d| d| j|j  kr|j  kr|j  kr|j  kr|jksn td| j d| j d| j d	|j d
|j d|j d| j|j  krP|j  krP|j  krP|j  krP|jksn td| j d| j d| j d	|j d
|j d|j dtjg dg dg dg dgg| j| jdt| dd}|dddddf  | 	dd7  < |dddddf  |	dd7  < |dddddf  |	dd7  < |ddddf  |7  < |ddddf  |7  < |ddddf  |7  < |ddddf  |7  < |
 }|dddddf  |jdddd7  < tj||gdd}|S )a  Generate 3D bounding boxes according to the provided start coords, width, height and depth.

    Args:
        x_start: a tensor containing the x coordinates of the bounding boxes to be extracted. Shape must be a scalar
            tensor or :math:`(B,)`.
        y_start: a tensor containing the y coordinates of the bounding boxes to be extracted. Shape must be a scalar
            tensor or :math:`(B,)`.
        z_start: a tensor containing the z coordinates of the bounding boxes to be extracted. Shape must be a scalar
            tensor or :math:`(B,)`.
        width: widths of the masked image. Shape must be a scalar tensor or :math:`(B,)`.
        height: heights of the masked image. Shape must be a scalar tensor or :math:`(B,)`.
        depth: depths of the masked image. Shape must be a scalar tensor or :math:`(B,)`.

    Returns:
        the 3d bounding box tensor :math:`(B, 8, 3)`.

    Examples:
        >>> x_start = torch.tensor([0, 3])
        >>> y_start = torch.tensor([1, 4])
        >>> z_start = torch.tensor([2, 5])
        >>> width = torch.tensor([10, 40])
        >>> height = torch.tensor([20, 50])
        >>> depth = torch.tensor([30, 60])
        >>> bbox_generator3d(x_start, y_start, z_start, width, height, depth)
        tensor([[[ 0,  1,  2],
                 [10,  1,  2],
                 [10, 21,  2],
                 [ 0, 21,  2],
                 [ 0,  1, 32],
                 [10,  1, 32],
                 [10, 21, 32],
                 [ 0, 21, 32]],
        <BLANKLINE>
                [[ 3,  4,  5],
                 [43,  4,  5],
                 [43, 54,  5],
                 [ 3, 54,  5],
                 [ 3,  4, 65],
                 [43,  4, 65],
                 [43, 54, 65],
                 [ 3, 54, 65]]])
    r8   zA`x_start`, `y_start` and `z_start` must be a scalar or (B,). Got rL   r   z<`width`, `height` and `depth` must be a scalar or (B,). Got rM   rN   z), `z_start`(rO   rP   z) and `depth`(rQ   rR   )r   r   r   r(   r   Nr   r   r   r   rB   r   )r   rC   r   r*   r)   r   r0   rS   r   r   clonerE   cat)rJ   rK   rU   r6   r7   rV   rT   Z	bbox_backr"   r"   r#   r   `  sl    2**BJ$
&&&.r   xyxy)	trans_matr   moderestore_coordinatesr   c                 C   s  t |tstdt| |dvr2td| |du r`|jdd tddgks`t	d |d	kr|d
 |d  |d< |d |d  |d< t
| ||jd dd}||}|du s|rt|jdd tddgkst| }tj|dddgf ddd |d
< tj|dddgf ddd |d< tj|dddgf ddd |d< tj|dddgf ddd |d< |}|d	kr|d |d
  |d< |d |d  |d< |S )aq  Apply a transformation matrix to a box or batch of boxes.

    Args:
        trans_mat: The transformation matrix to be applied with a shape of :math:`(3, 3)`
            or batched as :math:`(B, 3, 3)`.
        boxes: The boxes to be transformed with a common shape of :math:`(N, 4)` or batched as :math:`(B, N, 4)`, the
            polygon shape of :math:`(B, N, 4, 2)` is also supported.
        mode: The format in which the boxes are provided. If set to 'xyxy' the boxes are assumed to be in the format
            ``xmin, ymin, xmax, ymax``. If set to 'xywh' the boxes are assumed to be in the format
            ``xmin, ymin, width, height``
        restore_coordinates: In case the boxes are flipped, adding a post processing step to restore the
            coordinates to a valid bounding box.

    Returns:
        The set of transformed points in the specified mode
    zMode must be a string. Got )rY   xywhz(Mode must be one of 'xyxy', 'xywh'. Got Nr   r   r   aP  Previous behaviour produces incorrect box coordinates if a flip transformation performed on boxes.The previous wrong behaviour has been corrected and will be removed in the future versions.If you wish to keep the previous behaviour, please set `restore_coordinates=False`.Otherwise, set `restore_coordinates=True` as an acknowledgement.r]   ).r   ).r   ).r   ).r   r   r   .rB   r   r   )
isinstancer!   	TypeErrortyper    r   r   r   warningswarnr   r   Zview_asrW   minmax)rZ   r   r[   r\   Ztransformed_boxesZrestored_boxesr"   r"   r#   r     s0    
$
,""""
r   )r   scoresiou_thresholdr   c                 C   s  t | jdkr.| jd dkr.td| j dt |jdkrNtd|j d| jd |jd krztd	| j|jf d| d\}}}}|| ||  }|jd
d\}}	g }
|	jd dkr|	d }|
| t|| ||	dd  }t|| ||	dd  }t|| ||	dd  }t|| ||	dd  }tj	|| dd}tj	|| dd}|| }||| ||	dd   |  }t
||kd }|	|d  }	qt |
dkrt|
S t|
S )aa  Perform non-maxima suppression (NMS) on a given tensor of bounding boxes according to the intersection-over-
    union (IoU).

    Args:
        boxes: tensor containing the encoded bounding boxes with the shape :math:`(N, (x_1, y_1, x_2, y_2))`.
        scores: tensor containing the scores associated to each bounding box with shape :math:`(N,)`.
        iou_threshold: the throshold to discard the overlapping boxes.

    Return:
        A tensor mask with the indices to keep from the input set of boxes and scores.

    Example:
        >>> boxes = torch.tensor([
        ...     [10., 10., 20., 20.],
        ...     [15., 5., 15., 25.],
        ...     [100., 100., 200., 200.],
        ...     [100., 100., 200., 200.]])
        >>> scores = torch.tensor([0.9, 0.8, 0.7, 0.9])
        >>> nms(boxes, scores, iou_threshold=0.8)
        tensor([0, 3, 1])
    r   r   r   zboxes expected as Nx4. Got: r   r   zscores expected as N. Got: r   z+boxes and scores mus have same shape. Got: T)Z
descendingNg        )rc   )r   r   r    ZunbindsortrG   r   rd   rc   clampwhererH   r0   )r   re   rf   x1y1Zx2y2Zareas_orderZkeepiZxx1Zyy1Zxx2Zyy2whinterZovrZindsr"   r"   r#   r     s4    
 
r   )rY   N)ra   typingr   r   r   Zlinalgr   __all__ZjitignoreZTensorboolr   r   r   r	   intr
   r   r   r   r!   r   r=   r   r"   r"   r"   r#   <module>   s:   "!"0* Q?[ ;