o
    oi%                     @   s   d dl mZmZmZmZmZmZ d dlmZ	 d dl
mZ d dlmZ d dlmZmZ d dlmZ d dlmZmZ d dlmZ G d	d
 d
eZG dd deZdS )    )AnyDictListOptionalTupleUnion)random_generator)GeometricAugmentationBase2D)Resample)Tensor	as_tensor)affine)_compute_rotation_matrix_compute_tensor_center)eye_likec                       s  e Zd ZdZejjddddfdeee	e
e	e	f ee	 f deeeef deded	e	d
eddf fddZdedeeef deeef defddZ	ddedeeef deeef dee def
ddZ		ddedeeef dee dee
eef  def
ddZ  ZS )RandomRotationa  Apply a random rotation to a tensor image or a batch of tensor images given an amount of degrees.

    .. image:: _static/img/RandomRotation.png

    Args:
        degrees: range of degrees to select from. If degrees is a number the
          range of degrees to select from will be (-degrees, +degrees).
        resample: Default: the interpolation mode.
        same_on_batch: apply the same transformation across the batch.
        align_corners: interpolation flag.
        p: probability of applying the transformation.
        keepdim: whether to keep the output shape the same as input (True) or broadcast it
                 to the batch form (False).

    Shape:
        - Input: :math:`(C, H, W)` or :math:`(B, C, H, W)`, Optional: :math:`(B, 3, 3)`
        - Output: :math:`(B, C, H, W)`

    .. note::
        This function internally uses :func:`kornia.geometry.transform.affine`.

    Examples:
        >>> rng = torch.manual_seed(0)
        >>> input = torch.tensor([[1., 0., 0., 2.],
        ...                       [0., 0., 0., 0.],
        ...                       [0., 1., 2., 0.],
        ...                       [0., 0., 1., 2.]])
        >>> aug = RandomRotation(degrees=45.0, p=1.)
        >>> out = aug(input)
        >>> out
        tensor([[[[0.9824, 0.0088, 0.0000, 1.9649],
                  [0.0000, 0.0029, 0.0000, 0.0176],
                  [0.0029, 1.0000, 1.9883, 0.0000],
                  [0.0000, 0.0088, 1.0117, 1.9649]]]])
        >>> aug.transform_matrix
        tensor([[[ 1.0000, -0.0059,  0.0088],
                 [ 0.0059,  1.0000, -0.0088],
                 [ 0.0000,  0.0000,  1.0000]]])
        >>> inv = aug.inverse(out)

    To apply the exact augmenation again, you may take the advantage of the previous parameter state:
        >>> input = torch.randn(1, 3, 32, 32)
        >>> aug = RandomRotation(degrees=45.0, p=1.)
        >>> (aug(input) == aug(input, params=aug._params)).all()
        tensor(True)

    FT      ?degreesresamplesame_on_batchalign_cornerspkeepdimreturnNc                    <   t  j|||d t|dddf| _t||d| _d S )Nr   r   r   r           )g     vg     v@r   r   super__init__rgPlainUniformGenerator_param_generatorr
   getflags)selfr   r   r   r   r   r   	__class__ ^/home/ubuntu/.local/lib/python3.10/site-packages/kornia/augmentation/_2d/geometric/rotation.pyr    P      	zRandomRotation.__init__inputparamsr%   c                 C   sx   |d  |}t|}t|||jd d}td|dd}|d d df |d d df< |d d df |d d df< |S )Nr   r      Fshared_memory   )tor   r   expandshaper   r&   r,   r-   r%   anglescenterrotation_mat	trans_matr)   r)   r*   compute_transformation^   s   z%RandomRotation.compute_transformation	transformc                 C   N   t |tstdt| dt||dd dd df |d j d|d S 	N*Expected the `transform` be a Tensor. Got ..   r/   r   zerosr   
isinstancer   	TypeErrortyper   namelowerr&   r,   r-   r%   r<   r)   r)   r*   apply_transforml      
0zRandomRotation.apply_transformsizec                 C   @   t |tstdt| d| j|| jt||j|jd|dS Nr?   r@   )devicedtype)r-   r<   r%   	rD   r   rE   rF   rJ   _paramsr   rO   rP   r&   r,   r%   r<   rL   r)   r)   r*   inverse_transformt      
z RandomRotation.inverse_transformNNN)__name__
__module____qualname____doc__r
   BILINEARrG   r   r   floatr   r   strintboolr    r   r   r;   r   rJ   rT   __classcell__r)   r)   r'   r*   r      s`    5*



r   c                       s   e Zd ZdZejjddddfdeeef de	e
eef deded	ed
eddf fddZdedee
ef dee
ef defddZ	ddedee
ef dee
ef dee def
ddZ		ddedee
ef dee deeeef  def
ddZ  ZS )RandomRotation90aT  Apply a random 90 * n degree rotation to a tensor image or a batch of tensor images.

    Args:
        times: the range of n times 90 degree rotation needs to be applied.
        resample: Default: the interpolation mode.
        same_on_batch: apply the same transformation across the batch.
        align_corners: interpolation flag.
        p: probability of applying the transformation.
        keepdim: whether to keep the output shape the same as input (True) or broadcast it
                 to the batch form (False).

    Shape:
        - Input: :math:`(C, H, W)` or :math:`(B, C, H, W)`, Optional: :math:`(B, 3, 3)`
        - Output: :math:`(B, C, H, W)`

    .. note::
        This function internally uses :func:`kornia.geometry.transform.affine`. This version is relatively
        slow as it operates based on affine transformations.

    Examples:
        >>> rng = torch.manual_seed(1)
        >>> torch.set_printoptions(sci_mode=False)
        >>> input = torch.tensor([[1., 0., 0., 2.],
        ...                       [0., 0., 0., 0.],
        ...                       [0., 1., 2., 0.],
        ...                       [0., 0., 1., 2.]])
        >>> aug = RandomRotation90(times=(1, 1), p=1.)
        >>> out = aug(input)
        >>> out
        tensor([[[[    2.0000,     0.0000,     0.0000,     2.0000],
                  [    0.0000,     0.0000,     2.0000,     1.0000],
                  [    0.0000,     0.0000,     1.0000,     0.0000],
                  [    1.0000,     0.0000,     0.0000,     0.0000]]]])
        >>> aug.transform_matrix
        tensor([[[    -0.0000,      1.0000,      0.0000],
                 [    -1.0000,     -0.0000,      3.0000],
                 [     0.0000,      0.0000,      1.0000]]])
        >>> inv = aug.inverse(out)
        >>> torch.set_printoptions(profile='default')

    To apply the exact augmenation again, you may take the advantage of the previous parameter state:
        >>> input = torch.randn(1, 3, 32, 32)
        >>> aug = RandomRotation90(times=(-1, 1), p=1.)
        >>> (aug(input) == aug(input, params=aug._params)).all()
        tensor(True)

    FTr   timesr   r   r   r   r   r   Nc                    r   )Nr   rc   r   )r/   r   r   )r&   rc   r   r   r   r   r   r'   r)   r*   r       r+   zRandomRotation90.__init__r,   r-   r%   c                 C   s   d|d   | }t|}t|||jd d}td|dd}|d d df |d d df< |d d df |d d df< |S )	Ng     V@rc   r   r.   r/   Fr0   r2   )roundr3   r   r   r4   r5   r   r6   r)   r)   r*   r;      s   z'RandomRotation90.compute_transformationr<   c                 C   r=   r>   rC   rI   r)   r)   r*   rJ      rK   z RandomRotation90.apply_transformrL   c                 C   rM   rN   rQ   rS   r)   r)   r*   rT      rU   z"RandomRotation90.inverse_transformrV   rW   )rX   rY   rZ   r[   r
   r\   rG   tupler_   r   r^   r`   r]   r    r   dictr   r;   r   rJ   rT   ra   r)   r)   r'   r*   rb      s`    3
*



rb   N)typingr   r   r   r   r   r   kornia.augmentationr   r!   &kornia.augmentation._2d.geometric.baser	   kornia.constantsr
   kornia.corer   r   kornia.geometry.transformr   !kornia.geometry.transform.affwarpr   r   kornia.utils.miscr   r   rb   r)   r)   r)   r*   <module>   s    h