o
    oi<                     @   s4  d dl mZmZmZmZ d dlZd dlmZ d dlmZm	Z	 dedededefd	d
Z
dejdededejddf
ddZdejdejdejdejdejf
ddZ	d#dejdejdeej dee dejf
ddZdedededeeef fddZdee defddZdedeeee f d edefd!d"ZdS )$    )ListOptionalTupleUnionN)Tensor)KORNIA_CHECKKORNIA_CHECK_SHAPEimagepointscolorreturnc                 C   s   t t| jdkrt|jdkp| jd |jd kd |jtj| jd}t| \}}t|jdkr8tj|dd}|j| j	| jd}t| jdkrP|| ||f< | S || dd||f< | S )a  Set one or more coordinates in a Tensor to a color.

    Args:
        image: the input image on which to draw the points with shape :math`(C,H,W)` or :math`(H,W)`.
        points: the [x, y] points to be drawn on the image.
        color: the color of the pixel with :math`(C)` where :math`C` is the number of channels of the image.

    Return:
        The image with points set to the color.

          r   z;Color dim must match the channel dims of the provided imagedtypedevicedimN)
r   lenshapetotorchint64r   zip	unsqueezer   )r	   r
   r   xy r   E/home/ubuntu/.local/lib/python3.10/site-packages/kornia/utils/draw.pydraw_point2d   s   .r   r   r   c                 C   s   || dd||f< dS )am  Draws a pixel into an image.

    Args:
        image: the input image to where to draw the lines with shape :math`(C,H,W)`.
        x: the x coordinate of the pixel.
        y: the y coordinate of the pixel.
        color: the color of the pixel with :math`(C)` where :math`C` is the number of channels of the image.

    Return:
        Nothing is returned.

    Nr   )r	   r   r   r   r   r   r   _draw_pixel8   s   r    p1p2c                    s  |j d |j d ks|j d dks|j d dkrtd|d dk  sB|d  j d k sB|d dk  sB|d  j d k rFtd|d dk  sl|d  j d k sl|d dk  sl|d  j d k rptd	t  d
kr|td|d dkrtd| jtj}| jtj}| }|d |d }}|d |d }}|| }|| }	t	|}
t	|	}t
|t
|	}}	|dk}|	dk}||	k||B  @ }||B |B  }g g }}g g }}g g }}g g }}| r$dd t|| |	| D } fddt|| || |	| D }| rJ fddt|| |
| || D }dd t|| || D }| rx fddt|| |
| || D } fddt|| || || |	| D }| r fddt|| |
| || |	| D } fddt|| || |	| D }tjt|| | |  d j d d d}tjt|| | |  d j d d d}|dd dd||f<  S )at  Draw a single line into an image.

    Args:
        image: the input image to where to draw the lines with shape :math`(C,H,W)`.
        p1: the start point [x y] of the line with shape (2, ) or (B, 2).
        p2: the end point [x y] of the line with shape (2, ) or (B, 2).
        color: the color of the line with shape :math`(C)` where :math`C` is the number of channels of the image.

    Return:
        the image with containing the line.

    Examples:
        >>> image = torch.zeros(1, 8, 8)
        >>> draw_line(image, torch.tensor([6, 4]), torch.tensor([1, 4]), torch.tensor([255]))
        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.,   0.,   0.,   0.,   0.,   0.,   0.,   0.],
                 [  0., 255., 255., 255., 255., 255., 255.,   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   z]Input points must be 2D points with shape (2, ) or (B, 2) and must have the same batch sizes.).r   ).r   zp1 is out of bounds.zp2 is out of bounds.   z%image must have 3 dimensions (C,H,W).z9color must have the same number of channels as the image.c                 S   0   g | ]\}}| t| d  D ]}|qqS r   repeatintitem).0x_idy_ir   r   r   r   
<listcomp>   
    zdraw_line.<locals>.<listcomp>c              
      <   g | ]\}}}||t jd |d d jd  D ]}|qqS r   r   r   r   aranger   )r,   y_isdy_r   r	   r   r   r/          c              
      r1   r2   r4   r,   r-   r7   dx_ir   r9   r   r   r/      r:   c                 S   r&   r'   r(   )r,   r6   r<   r   r   r   r   r/      r0   c              
      r1   r2   r4   r;   r9   r   r   r/      r:   c              
      sZ   g | ])\}}}}||t jd |d ||  jddt| d     D ]}|q&qS r   r   r3   Nr   r5   r   r*   r+   ceil)r,   r6   r7   r<   r.   r   r9   r   r   r/      s    
:c              
      sZ   g | ])\}}}}||t jd |d ||  jddt| d     D ]}|q&qS r=   r>   )r,   r-   r7   r<   r8   r   r9   r   r   r/      s    
:c              
      r1   r2   r4   )r,   r6   r7   r.   r   r9   r   r   r/      r:   r   )minmaxN)r   
ValueErroranyr   sizer   r   r   r   signabsr   clamptensorlongview)r	   r!   r"   r   x1y1x2y2dxdydx_signdy_signdx_zero_maskdy_zero_maskdx_gt_dy_mask	rest_maskdx_zero_x_coordsdx_zero_y_coordsdy_zero_x_coordsdy_zero_y_coordsdx_gt_dy_x_coordsdx_gt_dy_y_coordsrest_x_coordsrest_y_coordsx_coordsy_coordsr   r9   r   	draw_lineH   s   0














	

ra   	rectanglefillc                 C   s  | j \}}}}|j \}}	}
||krtd|
dkrtd|  }t|dddddddf d|d |dddddddf< t|dddddddf d|d |dddddddf< |du rvtdg| ||	|}|du r|d	}t|j dkr|||	|}|j \}}}|dkr|d
kr|||	|}t	|D ]}t	|	D ]}|r|||ddddf | |ddt
|||df t
|||d
f d t
|||df t
|||df d f< q|||dddf | |ddt
|||df t
|||d
f d |||df f< |||dddf | |ddt
|||df t
|||d
f d |||df f< |||dddf | |dd|||df t
|||df t
|||df d f< |||dddf | |dd|||d
f t
|||df t
|||df d f< qq| S )aH  Draw N rectangles on a batch of image tensors.

    Args:
        image: is tensor of BxCxHxW.
        rectangle: represents number of rectangles to draw in BxNx4
            N is the number of boxes to draw per batch index[x1, y1, x2, y2]
            4 is in (top_left.x, top_left.y, bot_right.x, bot_right.y).
        color: a size 1, size 3, BxNx1, or BxNx3 tensor.
            If C is 3, and color is 1 channel it will be broadcasted.
        fill: is a flag used to fill the boxes with color if True.

    Returns:
        This operation modifies image inplace but also returns the drawn tensor for
        convenience with same shape the of the input BxCxHxW.

    Example:
        >>> img = torch.rand(2, 3, 10, 12)
        >>> rect = torch.tensor([[[0, 0, 4, 4]], [[4, 4, 10, 10]]])
        >>> out = draw_rectangle(img, rect)

    z-Image batch and rectangle batch must be equal   z'Number of points in rectangle must be 4Nr   r   r   g        Fr%   )r   AssertionErrorrI   cloner   rG   rH   expandr   ranger*   )r	   rb   r   rc   batchchw
batch_rectnum_rectangle
num_pointsbncolor_channelsr   r   r   draw_rectangle   sV   BB&&BBBDrs   polygonrk   rl   c              	   C   s  | j }t| ddddf | ddddf s)tj| | dddddf fdd} | ddddf | ddddf }}| ddddf | ddddf }}tj|| j|d}|| || d	  | |}	|ddddf |ddddf  |	ddddf  |ddddf  }
|ddddf |ddddf k|ddddf |ddddf k}||ddddf |ddddf k|ddddf |ddddf kO }|
 }||| < |
 }d|| < |j	ddj
}|jddj
}||fS )
a  Get the left and right edges of a polygon for each y-coordinate y \in [0, h).

    Args:
        polygon: represents polygons to draw in BxNx2
            N is the number of points
            2 is (x, y).
        h: bottom most coordinate (top coordinate is assumed to be 0)
        w: right most coordinate (left coordinate is assumed to be 0)

    Returns:
        The left and right edges of the polygon of shape (B,B).

    .r#   Nr   r   r$   r   r   r   g-q=)r   r   allclosecatr5   r   rG   logical_andrf   r@   valuesrA   )rt   rk   rl   r   x_starty_startx_endy_endysrO   xsvalid_edgesx_left_edgesx_right_edgesx_leftx_rightr   r   r   _get_convex_edges  s"   ($&&HJN

r   polygonsc              	   C   s   t | t t| t d}}tj||d| d j| d jd}t| D ]!\}}t ||k r>t||dd |t | dfn|||< q!|S )a  Convert a List of variable length polygons into a fixed size tensor.

    Works by repeating the last element in the tensor.

    Args:
        polygons: List of variable length polygons of shape [N_1 x 2, N_2 x 2, ..., N_B x 2].
                    B is the batch size,
                    N_i is the number of points,
                    2 is (x, y).

    Returns:
        A fixed size tensor of shape (B, N, 2) where N = max_i(N_i)

    )keyr   r   r   r#   N)	r   rA   r   zerosr   r   	enumeraterw   rg   )r   BNbatched_polygonsrp   pr   r   r   _batch_polygonsG  s
    <r   imagescolorsc                 C   sj  t | g d g | j| jR \}}}}}t|trt|}g |j|j|jR \}}	}
}}t|jdkr<|||}g |j|jR \}}	}t	|
dkd t	||  koY|kn  d t	||  koh|kn  d t
|||\}}tj|||dddddf }||d	dddf k||d	dddf k@ }| |dddf  |dddf |d
   | S )a  Draws convex polygons on a batch of image tensors.

    Args:
        images: is tensor of BxCxHxW.
        polygons: represents polygons as points, either BxNx2 or List of variable length polygons.
            N is the number of points.
            2 is (x, y).
        colors: a B x 3 tensor or 3 tensor with color to fill in.

    Returns:
        This operation modifies image inplace but also returns the drawn tensor for
        convenience with same shape the of the input BxCxHxW.

    Note:
        This function assumes a coordinate system (0, h - 1), (0, w - 1) in the image, with (0, 0) being the center
        of the top-left pixel and (w - 1, h - 1) being the center of the bottom-right coordinate.

    Example:
        >>> img = torch.rand(1, 3, 12, 16)
        >>> poly = torch.tensor([[[4, 4], [12, 4], [12, 8], [4, 8]]])
        >>> color = torch.tensor([[0.5, 0.5, 0.5]])
        >>> out = draw_convex_polygon(img, poly, color)

    )r   CHWr   r   z/Polygon vertices must be xy, i.e. 2-dimensionalz8Image, polygon, and color must have same batch dimensionz/Image, polygon, and color must have same deviceru   N.).NN)r   r   r   
isinstancer   r   r   r   rg   r   r   r   r5   mul_add_)r   r   r   b_ic_ih_iw_ir   b_p_xydevice_pdtype_pb_cdevice_cr   r   wsfill_regionr   r   r   draw_convex_polygon]  s    
",2r   )NN)typingr   r   r   r   r   r   kornia.core.checkr   r   r   r*   r    ra   boolrs   r   r   r   r   r   r   r   <module>   s.   "( 	
"M+*