a
    d                     @   s&  d dl mZmZmZ d dlZd dlmZ d dlmZ d dl	m
Z
 d dlmZ ddlmZmZmZmZmZ g dZejejd	d
dZejejd	ddZejejejdddZejejejejejdddZejejdddZejejejdddZejejdddZdMejejeeeejd d!d"ZdNejejeeeejd d$d%ZdOejejedejf eeeejd&d'd(Z dPejejejejedejf eeeejd)	d*d+Z!dQejejeeeejd,d-d.Z"dRejejedejf eeeejd/d0d1Z#dSejejeeeejd2d3d4Z$dTe%e&eee%e%f d6d7d8Z'edUejee%ee%e%f f eee eeejd9d:d;Z(dVejee&ee&e&f f eee eejd<d=d>Z)G d?d@ d@ej*Z+G dAdB dBej*Z,G dCdD dDej*Z-G dEdF dFej*Z.G dGdH dHej*Z/G dIdJ dJej*Z0G dKdL dLej*Z1dS )W    )OptionalTupleUnionN)gaussian_blur2d)_extract_device_dtype)perform_keep_shape_image   )get_affine_matrix2dget_projective_transformget_rotation_matrix2dwarp_affinewarp_affine3d)affineaffine3dscalerotaterotate3d	translateshearresizerescaleScaleRotate	TranslateShearResizeRescaleAffine)tensorreturnc                 C   s|   dt | j  krdks.n td| j d| jdd \}}t|d d }t|d d }tj||g| j| jd}|S )	zJCompute the center of tensor plane for (H, W), (C, H, W) and (B, C, H, W).      z-Must be a 3D tensor as HW, CHW and BCHW. Got .Nr   devicedtypelenshapeAssertionErrorfloattorchr   r%   r&   )r   heightwidthcenter_xcenter_ycenter r2   j/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/kornia/geometry/transform/affwarp.py_compute_tensor_center"   s    r4   c                 C   s   dt | j  krdks.n td| j d| jdd \}}}t|d d }t|d d }t|d d }tj|||g| j| jd	}|S )
zSCompute the center of tensor plane for (D, H, W), (C, D, H, W) and (B, C, D, H, W).      z0Must be a 3D tensor as DHW, CDHW and BCDHW. Got r"   Nr   r    r$   r'   )r   depthr-   r.   r/   r0   Zcenter_zr1   r2   r2   r3   _compute_tensor_center3d-   s    r9   )angler1   r   c                 C   s   t |}t|| |}|S )&Compute a pure affine rotation matrix.)r,   	ones_liker   )r:   r1   r   matrixr2   r2   r3   _compute_rotation_matrix9   s    
r>   )yawpitchrollr1   r   c                 C   s4  t | jt |j  kr0t |j  kr0dkrXn n$| jdd} |jdd}|jdd}t | jt |j  krt |j  krdkrn n$| jdd} |jdd}|jdd}t | jt |j  krt |j  krdksn td| j d|j d|j dtj| ||gdd}t| }t|||}|S )r;   r   dimr   r    z,Expected yaw, pitch, roll to be (B, 1). Got z, r"   )r(   r)   	unsqueezer*   r,   catr<   r
   )r?   r@   rA   r1   ZanglesZscalesr=   r2   r2   r3   _compute_rotation_matrix3d@   s    444"
rF   )translationr   c                 C   st   t jd| j| jd}|| jd dd}t j| ddd\}}|ddddf  |7  < |ddddf  |7  < |S )	z&Compute affine matrix for translation.r5   r$   r   r   r    chunksrC   .r,   Zeyer%   r&   repeatr)   chunk)rG   r=   ZdxZdyr2   r2   r3   _compute_translation_matrixW   s    rN   )r   r1   r   c                 C   s.   t j| jdd | j| jd}t||| }|S )z"Compute affine matrix for scaling.Nr   r$   )r,   zerosr)   r%   r&   r   )r   r1   r:   r=   r2   r2   r3   _compute_scaling_matrixb   s    rP   )r   r   c                 C   st   t jd| j| jd}|| jd dd}t j| ddd\}}|ddddf  |7  < |ddddf  |7  < |S )	z#Compute affine matrix for shearing.r5   r$   r   r   r    rH   rI   .rK   )r   r=   Zshxshyr2   r2   r3   _compute_shear_matrixi   s    rR   bilinearrO   T)r   r=   modepadding_modealign_cornersr   c           	      C   sr   |   dk}|rtj| dd} || jd dd}| jd }| jd }t| |||f|||}|rntj|dd}|S )a%  Apply an affine transformation to the image.

    .. image:: _static/img/warp_affine.png

    Args:
        tensor: The image tensor to be warped in shapes of
            :math:`(H, W)`, :math:`(D, H, W)` and :math:`(B, C, H, W)`.
        matrix: The 2x3 affine transformation matrix.
        mode: interpolation mode to calculate output values ``'bilinear'`` | ``'nearest'``.
        padding_mode: padding mode for outside grid values
          ``'zeros'`` | ``'border'`` | ``'reflection'``.
        align_corners: interpolation flag.

    Returns:
        The warped image with the same shape as the input.

    Example:
        >>> img = torch.rand(1, 2, 3, 5)
        >>> aff = torch.eye(2, 3)[None]
        >>> out = affine(img, aff)
        >>> print(out.shape)
        torch.Size([1, 2, 3, 5])
    r5   r   rB   rH   r#   )
ndimensionr,   rD   expandr)   r   squeeze)	r   r=   rT   rU   rV   is_unbatchedr-   r.   warpedr2   r2   r3   r   x   s    

r   Fc           
      C   s~   |   dk}|rtj| dd} || jd dd}| jd }| jd }| jd }t| ||||f|||}	|rztj|	dd}	|	S )a  Apply an affine transformation to the 3d volume.

    Args:
        tensor: The image tensor to be warped in shapes of
            :math:`(D, H, W)`, :math:`(C, D, H, W)` and :math:`(B, C, D, H, W)`.
        matrix: The affine transformation matrix with shape :math:`(B, 3, 4)`.
        mode: interpolation mode to calculate output values
          ``'bilinear'`` | ``'nearest'``.
        padding_mode: padding mode for outside grid values
         `` 'zeros'`` | ``'border'`` | ``'reflection'``.
        align_corners: interpolation flag.

    Returns:
        The warped image.

    Example:
        >>> img = torch.rand(1, 2, 4, 3, 5)
        >>> aff = torch.eye(3, 4)[None]
        >>> out = affine3d(img, aff)
        >>> print(out.shape)
        torch.Size([1, 2, 4, 3, 5])
    r!   r   rB   rH   r7   r#   )rW   r,   rD   rX   r)   r   rY   )
r   r=   rT   rU   rV   rZ   r8   r-   r.   r[   r2   r2   r3   r      s    


r   )r   r:   r1   rT   rU   rV   r   c                 C   s   t | tjstdt|  t |tjs<tdt| |durbt |tjsbtdt| t| jdvrtd| j|du rt	| }|
| jd }|
| jd d}t||}t| |d	dd
ddf |||S )ai  Rotate the tensor anti-clockwise about the center.

    .. image:: _static/img/rotate.png

    Args:
        tensor: The image tensor to be warped in shapes of :math:`(B, C, H, W)`.
        angle: The angle through which to rotate. The tensor
          must have a shape of (B), where B is batch size.
        center: The center through which to rotate. The tensor
          must have a shape of (B, 2), where B is batch size and last
          dimension contains cx and cy.
        mode: interpolation mode to calculate output values
          ``'bilinear'`` | ``'nearest'``.
        padding_mode: padding mode for outside grid values
          ``'zeros'`` | ``'border'`` | ``'reflection'``.
        align_corners: interpolation flag.

    Returns:
        The rotated tensor with shape as input.

    .. note::
       See a working example `here <https://kornia-tutorials.readthedocs.io/en/latest/
       rotate_affine.html>`__.

    Example:
        >>> img = torch.rand(1, 3, 4, 4)
        >>> angle = torch.tensor([90.])
        >>> out = rotate(img, angle)
        >>> print(out.shape)
        torch.Size([1, 3, 4, 4])
    -Input tensor type is not a torch.Tensor. Got z,Input angle type is not a torch.Tensor. Got N-Input center type is not a torch.Tensor. Got r5   r!   9Invalid tensor shape, we expect CxHxW or BxCxHxW. Got: {}r   rH   .r    r5   )
isinstancer,   Tensor	TypeErrortyper(   r)   
ValueErrorformatr4   rX   r>   r   )r   r:   r1   rT   rU   rV   rotation_matrixr2   r2   r3   r      s    '
r   )	r   r?   r@   rA   r1   rT   rU   rV   r   c           	      C   s>  t | tjstdt|  t |tjs<tdt| t |tjsZtdt| t |tjsxtdt| |durt |tjstdt| t| jdvrtd| j|du rt	| }|
| jd	 }|
| jd	 }|
| jd	 }|
| jd	 d
}t||||}t| |dddddf |||S )a  Rotate 3D the tensor anti-clockwise about the centre.

    Args:
        tensor: The image tensor to be warped in shapes of :math:`(B, C, D, H, W)`.
        yaw: The yaw angle through which to rotate. The tensor
          must have a shape of (B), where B is batch size.
        pitch: The pitch angle through which to rotate. The tensor
          must have a shape of (B), where B is batch size.
        roll: The roll angle through which to rotate. The tensor
          must have a shape of (B), where B is batch size.
        center: The center through which to rotate. The tensor
          must have a shape of (B, 2), where B is batch size and last
          dimension contains cx and cy.
        mode: interpolation mode to calculate output values
          ``'bilinear'`` | ``'nearest'``.
        padding_mode: padding mode for outside grid values
          ``'zeros'`` | ``'border'`` | ``'reflection'``.
        align_corners: interpolation flag.

    Returns:
        torch.Tensor: The rotated tensor with shape as input.
    r\   zyaw is not a torch.Tensor. Got z!pitch is not a torch.Tensor. Got z roll is not a torch.Tensor. Got Nr]   )r!   r6   z=Invalid tensor shape, we expect CxDxHxW or BxCxDxHxW. Got: {}r   rH   .r5   r!   )r`   r,   ra   rb   rc   r(   r)   rd   re   r9   rX   rF   r   )	r   r?   r@   rA   r1   rT   rU   rV   rf   r2   r2   r3   r   #  s(     r   )r   rG   rT   rU   rV   r   c                 C   s   t | tjstdt|  t |tjs<tdt| t| jdvrZtd| jt	|}t
| |dddddf |||S )	a  Translate the tensor in pixel units.

    .. image:: _static/img/translate.png

    Args:
        tensor: The image tensor to be warped in shapes of :math:`(B, C, H, W)`.
        translation: tensor containing the amount of pixels to
          translate in the x and y direction. The tensor must have a shape of
          (B, 2), where B is batch size, last dimension contains dx dy.
        mode: interpolation mode to calculate output values
          ``'bilinear'`` | ``'nearest'``.
        padding_mode: padding mode for outside grid values
          ``'zeros'`` | ``'border'`` | ``'reflection'``.
        align_corners: interpolation flag.

    Returns:
        The translated tensor with shape as input.

    Example:
        >>> img = torch.rand(1, 3, 4, 4)
        >>> translation = torch.tensor([[1., 0.]])
        >>> out = translate(img, translation)
        >>> print(out.shape)
        torch.Size([1, 3, 4, 4])
    r\   z2Input translation type is not a torch.Tensor. Got r^   r_   .Nr    r5   )r`   r,   ra   rb   rc   r(   r)   rd   re   rN   r   )r   rG   rT   rU   rV   Ztranslation_matrixr2   r2   r3   r   e  s     r   )r   scale_factorr1   rT   rU   rV   r   c                 C   s   t | tjstdt|  t |tjs<tdt| t|jdkrV|dd}|du rft| }|	| jd d}|	| jd d}t
||}t| |ddddd	f |||S )
ae  Scale the tensor by a factor.

    .. image:: _static/img/scale.png

    Args:
        tensor: The image tensor to be warped in shapes of :math:`(B, C, H, W)`.
        scale_factor: The scale factor apply. The tensor
          must have a shape of (B) or (B, 2), where B is batch size.
          If (B), isotropic scaling will perform.
          If (B, 2), x-y-direction specific scaling will perform.
        center: The center through which to scale. The tensor
          must have a shape of (B, 2), where B is batch size and last
          dimension contains cx and cy.
        mode: interpolation mode to calculate output values
          ``'bilinear'`` | ``'nearest'``.
        padding_mode: padding mode for outside grid values
          ``'zeros'`` | ``'border'`` | ``'reflection'``.
        align_corners: interpolation flag.

    Returns:
        The scaled tensor with the same shape as the input.

    Example:
        >>> img = torch.rand(1, 3, 4, 4)
        >>> scale_factor = torch.tensor([[2., 2.]])
        >>> out = scale(img, scale_factor)
        >>> print(out.shape)
        torch.Size([1, 3, 4, 4])
    r\   z3Input scale_factor type is not a torch.Tensor. Got r   r    Nr   rH   .r5   )r`   r,   ra   rb   rc   r(   r)   rL   r4   rX   rP   r   )r   rg   r1   rT   rU   rV   Zscaling_matrixr2   r2   r3   r     s    %
r   )r   r   rT   rU   rV   r   c                 C   s   t | tjstdt|  t |tjs<tdt| t| jdvrZtd| jt	|}t
| |dddddf |||S )	a|  Shear the tensor.

    .. image:: _static/img/shear.png

    Args:
        tensor: The image tensor to be skewed with shape of :math:`(B, C, H, W)`.
        shear: tensor containing the angle to shear
          in the x and y direction. The tensor must have a shape of
          (B, 2), where B is batch size, last dimension contains shx shy.
        mode: interpolation mode to calculate output values
          ``'bilinear'`` | ``'nearest'``.
        padding_mode: padding mode for outside grid values
          ``'zeros'`` | ``'border'`` | ``'reflection'``.
        align_corners: interpolation flag.

    Returns:
        The skewed tensor with shape same as the input.

    Example:
        >>> img = torch.rand(1, 3, 4, 4)
        >>> shear_factor = torch.tensor([[0.5, 0.0]])
        >>> out = shear(img, shear_factor)
        >>> print(out.shape)
        torch.Size([1, 3, 4, 4])
    r\   z,Input shear type is not a torch.Tensor. Got r^   r_   .Nr    r5   )r`   r,   ra   rb   rc   r(   r)   rd   re   rR   r   )r   r   rT   rU   rV   Zshear_matrixr2   r2   r3   r     s     r   short)	side_sizeaspect_ratiosider   c                 C   sx   |dvrt d| d|dkr0| t| | fS |dkrHt| | | fS |dk|dk A rh| t| | fS t| | | fS )N)rh   longverthorzz=side can be one of 'short', 'long', 'vert', and 'horz'. Got ''rm   rn   rh         ?)rd   int)ri   rj   rk   r2   r2   r3   _side_to_image_size  s    rr   )inputsizeinterpolationrV   rk   	antialiasr   c                 C   sx  t | tjstdt|  t| jdk r@tdt| j | jdd  }\}}t |trt|| }	t	||	|}||kr| S ||d  ||d  f}
|ot
|
dk}|r^t
|
d d d	 d
t
|
d d d	 d
f}tt
d|d  dtt
d|d  df}|d d dkr,|d d |d f}|d d dkrR|d |d d f}t| ||} tjjj| |||d}|S )a  Resize the input torch.Tensor to the given size.

    .. image:: _static/img/resize.png

    Args:
        tensor: The image tensor to be skewed with shape of :math:`(..., H, W)`.
            `...` means there can be any number of dimensions.
        size: Desired output size. If size is a sequence like (h, w),
            output size will be matched to this. If size is an int, smaller edge of the image will
            be matched to this number. i.e, if height > width, then image will be rescaled
            to (size * height / width, size)
        interpolation:  algorithm used for upsampling: ``'nearest'`` | ``'linear'`` | ``'bilinear'`` |
            'bicubic' | 'trilinear' | 'area'.
        align_corners: interpolation flag.
        side: Corresponding side if ``size`` is an integer. Can be one of ``'short'``, ``'long'``, ``'vert'``,
            or ``'horz'``.
        antialias: if True, then image will be filtered with Gaussian before downscaling.
            No effect for upscaling.

    Returns:
        The resized tensor with the shape as the specified size.

    Example:
        >>> img = torch.rand(1, 3, 4, 4)
        >>> out = resize(img, (6, 8))
        >>> print(out.shape)
        torch.Size([1, 3, 6, 8])
    r\   r    z4Input tensor must have at least two dimensions. Got r#   Nr   r   rp   g       @gMbP?g      @r5   )rt   rT   rV   )r`   r,   ra   rb   rc   r(   r)   rd   rq   rr   maxr   nnZ
functionalZinterpolate)rs   rt   ru   rV   rk   rv   Z
input_sizehwrj   ZfactorsZsigmasksoutputr2   r2   r3   r     s,    %
,,r   )rs   factorru   rV   rv   r   c           
      C   sZ   t |tr| }}n|\}}|  dd \}}t|| t|| f}	t| |	|||dS )a  Rescale the input torch.Tensor with the given factor.

    .. image:: _static/img/rescale.png

    Args:
        input: The image tensor to be scale with shape of :math:`(B, C, H, W)`.
        factor: Desired scaling factor in each direction. If scalar, the value is used
            for both the x- and y-direction.
        interpolation:  algorithm used for upsampling: ``'nearest'`` | ``'linear'`` | ``'bilinear'`` |
            ``'bicubic'`` | ``'trilinear'`` | ``'area'``.
        align_corners: interpolation flag.
        side: Corresponding side if ``size`` is an integer. Can be one of ``'short'``, ``'long'``, ``'vert'``,
            or ``'horz'``.
        antialias: if True, then image will be filtered with Gaussian before downscaling.
            No effect for upscaling.

    Returns:
        The rescaled tensor with the shape as the specified size.

    Example:
        >>> img = torch.rand(1, 3, 4, 4)
        >>> out = rescale(img, (2, 3))
        >>> print(out.shape)
        torch.Size([1, 3, 8, 12])
    r#   N)ru   rV   rv   )r`   r+   rt   rq   r   )
rs   r}   ru   rV   rv   Zfactor_vertZfactor_horzr-   r.   rt   r2   r2   r3   r   ]  s     

r   c                       sZ   e Zd ZdZdeeeeef f eee	 ee	dd fddZ
ejejd	d
dZ  ZS )r   a   Resize the input torch.Tensor to the given size.

    Args:
        size: Desired output size. If size is a sequence like (h, w),
            output size will be matched to this. If size is an int, smaller edge of the image will
            be matched to this number. i.e, if height > width, then image will be rescaled
            to (size * height / width, size)
        interpolation:  algorithm used for upsampling: ``'nearest'`` | ``'linear'`` | ``'bilinear'`` |
            'bicubic' | 'trilinear' | 'area'.
        align_corners: interpolation flag.
        side: Corresponding side if ``size`` is an integer. Can be one of ``'short'``, ``'long'``, ``'vert'``,
            or ``'horz'``.
        antialias: if True, then image will be filtered with Gaussian before downscaling.
            No effect for upscaling.

    Returns:
        The resized tensor with the shape of the given size.

    Example:
        >>> img = torch.rand(1, 3, 4, 4)
        >>> out = Resize((6, 8))(img)
        >>> print(out.shape)
        torch.Size([1, 3, 6, 8])
    rS   Nrh   F)rt   ru   rV   rk   rv   r   c                    s,   t    || _|| _|| _|| _|| _d S N)super__init__rt   ru   rV   rk   rv   )selfrt   ru   rV   rk   rv   	__class__r2   r3   r     s    
zResize.__init__rs   r   c                 C   s   t || j| j| j| j| jdS )N)rV   rk   rv   )r   rt   ru   rV   rk   rv   r   rs   r2   r2   r3   forward  s    zResize.forward)rS   Nrh   F)__name__
__module____qualname____doc__r   rq   r   strr   boolr   r,   ra   r   __classcell__r2   r2   r   r3   r     s       r   c                       sj   e Zd ZdZdeej eej eej eej eej eeedd	 fddZ	ejejd	d
dZ
  ZS )r   a`  Apply multiple elementary affine transforms simultaneously.

    Args:
        angle: Angle in degrees for counter-clockwise rotation around the center. The tensor
            must have a shape of (B), where B is the batch size.
        translation: Amount of pixels for translation in x- and y-direction. The tensor must
            have a shape of (B, 2), where B is the batch size and the last dimension contains dx and dy.
        scale_factor: Factor for scaling. The tensor must have a shape of (B), where B is the
            batch size.
        shear: Angles in degrees for shearing in x- and y-direction around the center. The
            tensor must have a shape of (B, 2), where B is the batch size and the last dimension contains sx and sy.
        center: Transformation center in pixels. The tensor must have a shape of (B, 2), where
            B is the batch size and the last dimension contains cx and cy. Defaults to the center of image to be
            transformed.
        mode: interpolation mode to calculate output values
          ``'bilinear'`` | ``'nearest'``.
        padding_mode: padding mode for outside grid values
          ``'zeros'`` | ``'border'`` | ``'reflection'``.
        align_corners: interpolation flag.

    Raises:
        RuntimeError: If not one of ``angle``, ``translation``, ``scale_factor``, or ``shear`` is set.

    Returns:
        The transformed tensor with same shape as input.

    Example:
        >>> img = torch.rand(1, 2, 3, 5)
        >>> angle = 90. * torch.rand(1)
        >>> out = Affine(angle)(img)
        >>> print(out.shape)
        torch.Size([1, 2, 3, 5])
    NrS   rO   T)	r:   rG   rg   r   r1   rT   rU   rV   r   c	                    s   dd ||||fD }	|	s&d}
t |
|	d  t fdd|	dd  D sZt d|	  | _t   t|||g\}}|d u rtj ||d	}|| _|d u rtj d
||d	}|| _	|d u rtj
 d
||d	}|| _|| _|| _|| _|| _|| _d S )Nc                 S   s    g | ]}|d ur|  d qS )Nr   )rt   ).0argr2   r2   r3   
<listcomp>      z#Affine.__init__.<locals>.<listcomp>zzAffine was created without any affine parameter. At least one of angle, translation, scale_factor, or shear has to be set.r   c                 3   s   | ]}| kV  qd S r~   r2   )r   otherZ
batch_sizer2   r3   	<genexpr>  r   z"Affine.__init__.<locals>.<genexpr>r   z3The batch sizes of the affine parameters mismatch: r$   r    )RuntimeErrorallZ_batch_sizer   r   r   r,   rO   r:   rG   Zonesrg   r   r1   rT   rU   rV   )r   r:   rG   rg   r   r1   rT   rU   rV   Zbatch_sizesmsgr%   r&   r   r   r3   r     s2    
zAffine.__init__r   c                 C   s   | j d u rd  }}n| j d | j d  }}| jd u rNt|| d d}n| j}t| j|| j| j ||d}t	||dd dd df | j
| j| jS )	N).r   ).r   r   rH   )sxsy.r    r5   )r   r1   r4   rX   rt   r	   rG   rg   r:   r   rT   rU   rV   )r   rs   r   r   r1   r=   r2   r2   r3   r     s    


zAffine.forward)NNNNNrS   rO   T)r   r   r   r   r   r,   ra   r   r   r   r   r   r2   r2   r   r3   r     s*   $        .r   c                       sT   e Zd ZdZdeeeeef f eeedd fddZ	e
je
jd	d
dZ  ZS )r   a  Rescale the input torch.Tensor with the given factor.

    Args:
        factor: Desired scaling factor in each direction. If scalar, the value is used
            for both the x- and y-direction.
        interpolation:  algorithm used for upsampling: ``'nearest'`` | ``'linear'`` | ``'bilinear'`` |
            ``'bicubic'`` | ``'trilinear'`` | ``'area'``.
        align_corners: interpolation flag.
        side: Corresponding side if ``size`` is an integer. Can be one of ``'short'``, ``'long'``, ``'vert'``,
            or ``'horz'``.
        antialias: if True, then image will be filtered with Gaussian before downscaling.
            No effect for upscaling.

    Returns:
        The rescaled tensor with the shape according to the given factor.

    Example:
        >>> img = torch.rand(1, 3, 4, 4)
        >>> out = Rescale((2, 3))(img)
        >>> print(out.shape)
        torch.Size([1, 3, 8, 12])
    rS   TFN)r}   ru   rV   rv   r   c                    s&   t    || _|| _|| _|| _d S r~   )r   r   r}   ru   rV   rv   )r   r}   ru   rV   rv   r   r2   r3   r   3  s
    
zRescale.__init__r   c                 C   s   t || j| j| j| jdS )N)rV   rv   )r   r}   ru   rV   rv   r   r2   r2   r3   r   @  s    zRescale.forward)rS   TF)r   r   r   r   r   r+   r   r   r   r   r,   ra   r   r   r2   r2   r   r3   r     s      r   c                       sR   e Zd ZdZdejedejf eeedd fddZ	ejejd	d
dZ
  ZS )r   ay  Rotate the tensor anti-clockwise about the centre.

    Args:
        angle: The angle through which to rotate. The tensor
          must have a shape of (B), where B is batch size.
        center: The center through which to rotate. The tensor
          must have a shape of (B, 2), where B is batch size and last
          dimension contains cx and cy.
        mode: interpolation mode to calculate output values
          ``'bilinear'`` | ``'nearest'``.
        padding_mode: padding mode for outside grid values
          ``'zeros'`` | ``'border'`` | ``'reflection'``.
        align_corners: interpolation flag.

    Returns:
        The rotated tensor with the same shape as the input.

    Example:
        >>> img = torch.rand(1, 3, 4, 4)
        >>> angle = torch.tensor([90.])
        >>> out = Rotate(angle)(img)
        >>> print(out.shape)
        torch.Size([1, 3, 4, 4])
    NrS   rO   T)r:   r1   rT   rU   rV   r   c                    s,   t    || _|| _|| _|| _|| _d S r~   )r   r   r:   r1   rT   rU   rV   )r   r:   r1   rT   rU   rV   r   r2   r3   r   `  s    
zRotate.__init__r   c                 C   s   t || j| j| j| j| jS r~   )r   r:   r1   rT   rU   rV   r   r2   r2   r3   r   o  s    zRotate.forward)NrS   rO   Tr   r   r   r   r,   ra   r   r   r   r   r   r   r2   r2   r   r3   r   F  s       r   c                       sF   e Zd ZdZdejeeedd fddZejejd	d
dZ	  Z
S )r   a2  Translate the tensor in pixel units.

    Args:
        translation: tensor containing the amount of pixels to
          translate in the x and y direction. The tensor must have a shape of
          (B, 2), where B is batch size, last dimension contains dx dy.
        mode: interpolation mode to calculate output values
          ``'bilinear'`` | ``'nearest'``.
        padding_mode: padding mode for outside grid values
          ``'zeros'`` | ``'border'`` | ``'reflection'``.
        align_corners: interpolation flag.

    Returns:
        The translated tensor with the same shape as the input.

    Example:
        >>> img = torch.rand(1, 3, 4, 4)
        >>> translation = torch.tensor([[1., 0.]])
        >>> out = Translate(translation)(img)
        >>> print(out.shape)
        torch.Size([1, 3, 4, 4])
    rS   rO   TN)rG   rT   rU   rV   r   c                    s&   t    || _|| _|| _|| _d S r~   )r   r   rG   rT   rU   rV   )r   rG   rT   rU   rV   r   r2   r3   r     s
    
zTranslate.__init__r   c                 C   s   t || j| j| j| jS r~   )r   rG   rT   rU   rV   r   r2   r2   r3   r     s    zTranslate.forward)rS   rO   Tr   r   r   r   r,   ra   r   r   r   r   r   r2   r2   r   r3   r   s  s    
	r   c                       sR   e Zd ZdZdejedejf eeedd fddZ	ejejd	d
dZ
  ZS )r   a  Scale the tensor by a factor.

    Args:
        scale_factor: The scale factor apply. The tensor
          must have a shape of (B) or (B, 2), where B is batch size.
          If (B), isotropic scaling will perform.
          If (B, 2), x-y-direction specific scaling will perform.
        center: The center through which to scale. The tensor
          must have a shape of (B, 2), where B is batch size and last
          dimension contains cx and cy.
        mode: interpolation mode to calculate output values
          ``'bilinear'`` | ``'nearest'``.
        padding_mode: padding mode for outside grid values
          ``'zeros'`` | ``'border'`` | ``'reflection'``.
        align_corners: interpolation flag.

    Returns:
        The scaled tensor with the same shape as the input.

    Example:
        >>> img = torch.rand(1, 3, 4, 4)
        >>> scale_factor = torch.tensor([[2., 2.]])
        >>> out = Scale(scale_factor)(img)
        >>> print(out.shape)
        torch.Size([1, 3, 4, 4])
    NrS   rO   T)rg   r1   rT   rU   rV   r   c                    s,   t    || _|| _|| _|| _|| _d S r~   )r   r   rg   r1   rT   rU   rV   )r   rg   r1   rT   rU   rV   r   r2   r3   r     s    
zScale.__init__r   c                 C   s   t || j| j| j| j| jS r~   )r   rg   r1   rT   rU   rV   r   r2   r2   r3   r     s    zScale.forward)NrS   rO   Tr   r2   r2   r   r3   r     s       r   c                       sF   e Zd ZdZdejeeedd fddZejejd	d
dZ	  Z
S )r   a  Shear the tensor.

    Args:
        shear: tensor containing the angle to shear
          in the x and y direction. The tensor must have a shape of
          (B, 2), where B is batch size, last dimension contains shx shy.
        mode: interpolation mode to calculate output values
          ``'bilinear'`` | ``'nearest'``.
        padding_mode: padding mode for outside grid values
          ``'zeros'`` | ``'border'`` | ``'reflection'``.
        align_corners: interpolation flag.

    Returns:
        The skewed tensor with the same shape as the input.

    Example:
        >>> img = torch.rand(1, 3, 4, 4)
        >>> shear_factor = torch.tensor([[0.5, 0.0]])
        >>> out = Shear(shear_factor)(img)
        >>> print(out.shape)
        torch.Size([1, 3, 4, 4])
    rS   rO   TN)r   rT   rU   rV   r   c                    s&   t    || _|| _|| _|| _d S r~   )r   r   r   rT   rU   rV   )r   r   rT   rU   rV   r   r2   r3   r     s
    
zShear.__init__r   c                 C   s   t || j | j| j| jS r~   )r   rT   rU   rV   r   r2   r2   r3   r     s    zShear.forward)rS   rO   Tr   r2   r2   r   r3   r     s    
	r   )rS   rO   T)rS   rO   F)NrS   rO   T)NrS   rO   F)rS   rO   T)NrS   rO   T)rS   rO   F)rh   )rS   Nrh   F)rS   NF)2typingr   r   r   r,   Ztorch.nnrx   Zkornia.filtersr   Zkornia.utilsr   Zkornia.utils.imager   Zimgwarpr	   r
   r   r   r   __all__ra   r4   r9   r>   rF   rN   rP   rR   r   r   r   r   r   r   r   r   r   rq   r+   rr   r   r   Moduler   r   r   r   r   r   r   r2   r2   r2   r3   <module>   s     6   :    F    E   3    @   0    Q   *4`+-%/