a
    d                  	   @   sz  d dl Z d dlZd dlmZmZ d dlZd dlm  mZ	 d dlm
Z
mZ d dlmZ d dlmZ d dlmZ g dZG dd	 d	e jZej
ej
d
ddZej
ej
d
ddZej
ej
eej
ej
f dddZdoej
ej
eeej
ej
f dddZdpej
eej
dddZej
ej
dddZej
ej
dddZej
ej
ddd Zej
ej
dd!d"Zej
ej
d#d$d%Zej
ej
d&d'd(Z dej!fej
eeej
d)d*d+Z"dqej
eej
d-d.d/Z#ej!fej
eej
d0d1d2Z$ej!fej
eej
d0d3d4Z%dej!fej
eeej
d5d6d7Z&dej!fej
eeej
d5d8d9Z'ej!fej
eej
d:d;d<Z(drej
e)e)eej
d=d>d?Z*dsej
e)e)eej
d=d@dAZ+dtej
e)e)e)eej
dBdCdDZ,duej
e)e)e)eej
dBdEdFZ-ej
ej
dGdHdIZ.ej
ee)e)f ee)e)f ej
dJdKdLZ/dve)e)eeej0 eej1 ej
dNdOdPZ2dwe)e)e)eeej0 eej1 ej
dQdRdSZ3ej
ee)e)f ee)e)f ej
dJdTdUZ4ej
ee)e)e)f ee)e)e)f ej
dJdVdWZ5e
e
e
dXdYdZZ6e
ee
e
f d[d\d]Z7e
e
d^d_d`Z8e
e
ee
e
f dXdadbZ9e
e
dcdddeZ:e
e
ee
e
f dXdfdgZ;e
e
ee
e
f dXdhdiZ<e
e
ee
e
f dXdjdkZ=e
e
ee
e
f dldmdnZ>dS )x    N)OptionalTuple)Tensortensor)piKORNIA_CHECK_SHAPE)_torch_inverse_cast)$rad2degdeg2radpol2cartcart2polconvert_points_from_homogeneousconvert_points_to_homogeneous"convert_affinematrix_to_homography$convert_affinematrix_to_homography3dangle_axis_to_rotation_matrixangle_axis_to_quaternionrotation_matrix_to_angle_axisrotation_matrix_to_quaternionquaternion_to_angle_axisquaternion_to_rotation_matrixquaternion_log_to_expquaternion_exp_to_logdenormalize_pixel_coordinatesnormalize_pixel_coordinatesnormalize_quaterniondenormalize_pixel_coordinates3dnormalize_pixel_coordinates3dangle_to_rotation_matrixnormalize_homographydenormalize_homographynormalize_homography3dnormal_transform_pixelnormal_transform_pixel3dworldtocam_to_camtoworld_Rtcamtoworld_to_worldtocam_RtRt_to_matrix4x4matrix4x4_to_Rt!camtoworld_graphics_to_vision_4x4!camtoworld_vision_to_graphics_4x4 camtoworld_graphics_to_vision_Rt camtoworld_vision_to_graphics_RtARKitQTVecs_to_ColmapQTVecsc                   @   s   e Zd ZdZdZdS )QuaternionCoeffOrderZxyzwwxyzN)__name__
__module____qualname__XYZWWXYZ r5   r5   d/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/kornia/geometry/conversions.pyr.   5   s   r.   )r   returnc                 C   s:   t | tjstdt|  d|  t| j| j S )a  Function that converts angles from radians to degrees.

    Args:
        tensor: Tensor of arbitrary shape.

    Returns:
        Tensor with same shape as input.

    Example:
        >>> input = torch.tensor(3.1415926535)
        >>> rad2deg(input)
        tensor(180.)
    &Input type is not a torch.Tensor. Got      f@	
isinstancetorchr   	TypeErrortyper   todevicedtyper   r5   r5   r6   r
   :   s    r
   c                 C   s:   t | tjstdt|  | t| j| j d S )a  Function that converts angles from degrees to radians.

    Args:
        tensor: Tensor of arbitrary shape.

    Returns:
        tensor with same shape as input.

    Examples:
        >>> input = torch.tensor(180.)
        >>> deg2rad(input)
        tensor(3.1416)
    r8   r9   r:   rB   r5   r5   r6   r   N   s    r   )rhophir7   c                 C   sX   t | tjt |tj@ s4tdt|  dt| | t| }| t| }||fS )a  Function that converts polar coordinates to cartesian coordinates.

    Args:
        rho: Tensor of arbitrary shape.
        phi: Tensor of same arbitrary shape.

    Returns:
        - x: Tensor with same shape as input.
        - y: Tensor with same shape as input.

    Example:
        >>> rho = torch.rand(1, 3, 3)
        >>> phi = torch.rand(1, 3, 3)
        >>> x, y = pol2cart(rho, phi)
    r8   , )r;   r<   r   r=   r>   cossin)rC   rD   xyr5   r5   r6   r   b   s
    r   :0yE>)rH   rI   epsr7   c                 C   sb   t | tjt |tj@ s4tdt|  dt| t| d |d  | }t|| }||fS )a  Function that converts cartesian coordinates to polar coordinates.

    Args:
        x: Tensor of arbitrary shape.
        y: Tensor of same arbitrary shape.
        eps: To avoid division by zero.

    Returns:
        - rho: Tensor with same shape as input.
        - phi: Tensor with same shape as input.

    Example:
        >>> x = torch.rand(1, 3, 3)
        >>> y = torch.rand(1, 3, 3)
        >>> rho, phi = cart2pol(x, y)
    r8   rE      )r;   r<   r   r=   r>   sqrtatan2)rH   rI   rK   rC   rD   r5   r5   r6   r   z   s
    r   )pointsrK   r7   c                 C   s   t | tjstdt|  t| jdk r<td| j | dddf }t||k}t	|d||  t
|}|| dddf  S )a  Function that converts points from homogeneous to Euclidean space.

    Args:
        points: the points to be transformed of shape :math:`(B, N, D)`.
        eps: to avoid division by zero.

    Returns:
        the points in Euclidean space :math:`(B, N, D-1)`.

    Examples:
        >>> input = torch.tensor([[0., 0., 1.]])
        >>> convert_points_from_homogeneous(input)
        tensor([[0., 0.]])
    r8   rL   (Input must be at least a 2D tensor. Got .N      ?)r;   r<   r   r=   r>   lenshape
ValueErrorabswhere	ones_like)rO   rK   Zz_vecmaskZscaler5   r5   r6   r      s    r   )rO   r7   c                 C   sT   t | tjstdt|  t| jdk r<td| j tjj	
| ddgddS )az  Function that converts points from Euclidean to homogeneous space.

    Args:
        points: the points to be transformed with shape :math:`(*, N, D)`.

    Returns:
        the points in homogeneous coordinates :math:`(*, N, D+1)`.

    Examples:
        >>> input = torch.tensor([[0., 0.]])
        >>> convert_points_to_homogeneous(input)
        tensor([[0., 0., 1.]])
    r8   rL   rP   r      constantrR   )r;   r<   r   r=   r>   rS   rT   rU   nn
functionalpad)rO   r5   r5   r6   r      s
    r   )Ar7   c                 C   s.   t jjj| g dddd}|d  d7  < |S )N)r   r   r   rZ   r[           )value).rQ   rQ   rR   )r<   r\   r]   r^   )r_   Hr5   r5   r6   (_convert_affinematrix_to_homography_impl   s    rc   c                 C   sV   t | tjstdt|  t| jdkr>| jdd dksNtd| j t| S )a  Function that converts batch of affine matrices.

    Args:
        A: the affine matrix with shape :math:`(B,2,3)`.

    Returns:
         the homography matrix with shape of :math:`(B,3,3)`.

    Examples:
        >>> A = torch.tensor([[[1., 0., 0.],
        ...                    [0., 1., 0.]]])
        >>> convert_affinematrix_to_homography(A)
        tensor([[[1., 0., 0.],
                 [0., 1., 0.],
                 [0., 0., 1.]]])
    r8      N)rL   rd   z)Input matrix must be a Bx2x3 tensor. Got 	r;   r<   r   r=   r>   rS   rT   rU   rc   r_   r5   r5   r6   r      s
     r   c                 C   sV   t | tjstdt|  t| jdkr>| jdd dksNtd| j t| S )a.  Function that converts batch of 3d affine matrices.

    Args:
        A: the affine matrix with shape :math:`(B,3,4)`.

    Returns:
         the homography matrix with shape of :math:`(B,4,4)`.

    Examples:
        >>> A = torch.tensor([[[1., 0., 0., 0.],
        ...                    [0., 1., 0., 0.],
        ...                    [0., 0., 1., 0.]]])
        >>> convert_affinematrix_to_homography3d(A)
        tensor([[[1., 0., 0., 0.],
                 [0., 1., 0., 0.],
                 [0., 0., 1., 0.],
                 [0., 0., 0., 1.]]])
    r8   rd   re   N)rd      z)Input matrix must be a Bx3x4 tensor. Got rf   rg   r5   r5   r6   r      s
     r   )
angle_axisr7   c                 C   s$  t | tjstdt|  | jd dks<td| j ddd}dd	 }tj| d
d}t||	d
d}tj
|d
d}|| |}|| }d}||kdd
d
|j}||}	| |}
| jd }td| j| }|d
dd|d
d
}|	| |
|  |dddddf< |S )a  Convert 3d vector of axis-angle rotation to 3x3 rotation matrix.

    Args:
        angle_axis: tensor of 3d vector of axis-angle rotations in radians with shape :math:`(N, 3)`.

    Returns:
        tensor of rotation matrices of shape :math:`(N, 3, 3)`.

    Example:
        >>> input = torch.tensor([[0., 0., 0.]])
        >>> angle_axis_to_rotation_matrix(input)
        tensor([[[1., 0., 0.],
                 [0., 1., 0.],
                 [0., 0., 1.]]])

        >>> input = torch.tensor([[1.5708, 0., 0.]])
        >>> angle_axis_to_rotation_matrix(input)
        tensor([[[ 1.0000e+00,  0.0000e+00,  0.0000e+00],
                 [ 0.0000e+00, -3.6200e-06, -1.0000e+00],
                 [ 0.0000e+00,  1.0000e+00, -3.6200e-06]]])
    r8   rQ   rd   z(Input size must be a (*, 3) tensor. Got ư>c              
   S   sB  d}t |}| ||  }t j|ddd\}}}t |}	t |}
|	|| ||	   }||
 || ||	   }| |
 || ||	   }|| ||	  ||
  }|	|| ||	   }||
 || ||	   }||
 || ||	   }| |
 || ||	   }|	|| ||	   }t j|||||||||g	dd}|dddS )NrR   rd   rZ   dimrQ   )r<   rM   chunkrF   rG   catview)ri   theta2rK   k_onethetar/   ZwxZwyZwz	cos_theta	sin_thetaZr00Zr10Zr20Zr01Zr11Zr21Zr02Zr12Zr22rotation_matrixr5   r5   r6   _compute_rotation_matrix"  s"    


 z?angle_axis_to_rotation_matrix.<locals>._compute_rotation_matrixc              
   S   sT   t j| ddd\}}}t |}t j|| |||| | ||g	dd}|dddS )Nrd   rZ   rk   rQ   )r<   rm   rX   rn   ro   )ri   rxZryZrzrq   ru   r5   r5   r6   _compute_rotation_matrix_taylor9  s    
&zFangle_axis_to_rotation_matrix.<locals>._compute_rotation_matrix_taylorrZ   rk   rL   r   .N)rj   )r;   r<   r   r=   r>   rT   rU   	unsqueezematmul	transposesqueezero   r?   r@   Ztype_asZeyerepeat)ri   rv   rx   Z_angle_axisrp   Zrotation_matrix_normalZrotation_matrix_taylorrK   rY   Zmask_posZmask_negZ
batch_sizeru   r5   r5   r6   r     s(    



"r   )ru   r7   c                 C   s\   t | tjstdt|  | jdd dks@td| j t| tj	d}t
|tj	dS )a  Convert 3x3 rotation matrix to Rodrigues vector in radians.

    Args:
        rotation_matrix: rotation matrix of shape :math:`(N, 3, 3)`.

    Returns:
        Rodrigues vector transformation of shape :math:`(N, 3)`.

    Example:
        >>> input = torch.tensor([[1., 0., 0.],
        ...                       [0., 1., 0.],
        ...                       [0., 0., 1.]])
        >>> rotation_matrix_to_angle_axis(input)
        tensor([0., 0., 0.])

        >>> input = torch.tensor([[1., 0., 0.],
        ...                       [0., 0., -1.],
        ...                       [0., 1., 0.]])
        >>> rotation_matrix_to_angle_axis(input)
        tensor([1.5708, 0.0000, 0.0000])
    r8   re   Nrd   rd   +Input size must be a (*, 3, 3) tensor. Got order)r;   r<   r   r=   r>   rT   rU   r   r.   r4   r   )ru   
quaternionr5   r5   r6   r   X  s    r   )ru   rK   r   r7   c                    s  t | tjstdt|  | jdd dks@td| j tj sn
j	t
j vrntdt
j  
t
jkrtd tjtjtjdd	d
| jg | jdd dR  }tj|ddd\		 	  
f
dd} 	
fdd} 	
fdd} 	
fdd}t	k| | }tk	k@ | |}	tdk| |	}
|
S )a  Convert 3x3 rotation matrix to 4d quaternion vector.

    The quaternion vector has components in (w, x, y, z) or (x, y, z, w) format.

    .. note::
        The (x, y, z, w) order is going to be deprecated in favor of efficiency.

    Args:
        rotation_matrix: the rotation matrix to convert with shape :math:`(*, 3, 3)`.
        eps: small value to avoid zero division.
        order: quaternion coefficient order. Note: 'xyzw' will be deprecated in favor of 'wxyz'.

    Return:
        the rotation in quaternion with shape :math:`(*, 4)`.

    Example:
        >>> input = torch.tensor([[1., 0., 0.],
        ...                       [0., 1., 0.],
        ...                       [0., 0., 1.]])
        >>> rotation_matrix_to_quaternion(input, eps=torch.finfo(input.dtype).eps,
        ...                               order=QuaternionCoeffOrder.WXYZ)
        tensor([1., 0., 0., 0.])
    r8   re   Nr~   r   order must be one of `XYZW` quaternion coefficient order is deprecated and will be removed after > 0.6. Please use `QuaternionCoeffOrder.WXYZ` instead.)	numeratordenominatorr7   c                 S   s    t | jj}| t j||d S )Nmin)r<   ZfinforA   Ztinyclamp)r   r   rK   r5   r5   r6   safe_zero_division  s    z9rotation_matrix_to_quaternion.<locals>.safe_zero_division	   rQ   chunksrl   c                     s~   t 	d   d } d|  } | } | } | }tjkrht j||||fddS t j||||fddS NrR          @g      ?rQ   rk   r<   rM   r.   r3   rn   sqZqwZqxZqyZqz)
rK   m01m02m10m12m20m21r   r   tracer5   r6   trace_positive_cond  s    
z:rotation_matrix_to_quaternion.<locals>.trace_positive_condc                     s   t d  	   d }  | }d|  } | } | }
tjkrpt j||||fddS t j||||fddS r   r   r   rK   m00r   r   r   m11r   r   r   m22r   r   r5   r6   cond_1  s    
z-rotation_matrix_to_quaternion.<locals>.cond_1c                     s   t d  	   d }  | } | }d|  } | }
tjkrpt j||||fddS t j||||fddS r   r   r   r   r5   r6   cond_2  s    
z-rotation_matrix_to_quaternion.<locals>.cond_2c                     s   t d	     d }  | } | } | }d|  }
tjkrpt j||||fddS t j||||fddS r   r   r   r   r5   r6   cond_3  s    
z-rotation_matrix_to_quaternion.<locals>.cond_3r`   )r;   r<   r   r=   r>   rT   rU   jitis_scriptingnamer.   __members__keysr3   warningswarnro   rm   rW   )ru   rK   r   Zrotation_matrix_vecr   r   r   r   Zwhere_2Zwhere_1r   r5   )rK   r   r   r   r   r   r   r   r   r   r   r   r   r6   r   w  s.    

"
"
"
"
r   -q=)r   rK   r7   c                 C   sN   t | tjstdt|  | jd dks<td| j tj| dd|dS )a	  Normalize a quaternion.

    The quaternion should be in (x, y, z, w) or (w, x, y, z) format.

    Args:
        quaternion: a tensor containing a quaternion to be normalized.
          The tensor can be of shape :math:`(*, 4)`.
        eps: small value to avoid division by zero.

    Return:
        the normalized quaternion of shape :math:`(*, 4)`.

    Example:
        >>> quaternion = torch.tensor((1., 0., 1., 0.))
        >>> normalize_quaternion(quaternion)
        tensor([0.7071, 0.0000, 0.7071, 0.0000])
    r8   rQ   rh   ,Input must be a tensor of shape (*, 4). Got r   )prl   rK   )	r;   r<   r   r=   r>   rT   rU   F	normalize)r   rK   r5   r5   r6   r     s
    r   )r   r   r7   c                 C   s  t | tjstdt|  | jd dks<td| j tj sj|j	t
j vrjtdt
j  |t
jkr~td t| }|t
jkrtj|ddd\}}}}ntj|ddd\}}}}d| }d| }d| }	|| }
|| }|	| }|| }|| }|	| }|| }|	| }|	| }td	}tj|||  || || || |||  ||
 || ||
 |||  f	dd
ddd}t| jdkrtj|dd
}|S )a  Convert a quaternion to a rotation matrix.

    The quaternion should be in (x, y, z, w) or (w, x, y, z) format.

    Args:
        quaternion: a tensor containing a quaternion to be converted.
          The tensor can be of shape :math:`(*, 4)`.
        order: quaternion coefficient order. Note: 'xyzw' will be deprecated in favor of 'wxyz'.

    Return:
        the rotation matrix of shape :math:`(*, 3, 3)`.

    Example:
        >>> quaternion = torch.tensor((0., 0., 0., 1.))
        >>> quaternion_to_rotation_matrix(quaternion, order=QuaternionCoeffOrder.WXYZ)
        tensor([[-1.,  0.,  0.],
                [ 0., -1.,  0.],
                [ 0.,  0.,  1.]])
    r8   rQ   rh   r   r   r   r   r   rR   rk   rd   rZ   r   )r;   r<   r   r=   r>   rT   rU   r   r   r   r.   r   r   r3   r   r   r   rm   r   stackro   rS   r|   )r   r   Zquaternion_normrH   rI   zwZtxtytzZtwxZtwyZtwzZtxxZtxyZtxzZtyyZtyzZtzzZoneZmatrixr5   r5   r6   r     s\    






r   c              	   C   s  t | stdt|  | jd dks:td| j t j sh|jt	j
 vrhtdt	j
  |t	jkr|td t g }t g }t g }t g }|t	jkr| d }| d }| d	 }| d
 }n | d }| d }| d	 }| d
 }|| ||  ||  }t |}dt |dk t | | t || }|| }	dt | }
t |dk|	|
}t | dddf }|d  || 7  < |d  || 7  < |d	  || 7  < |S )a  Convert quaternion vector to angle axis of rotation in radians.

    The quaternion should be in (x, y, z, w) or (w, x, y, z) format.

    Adapted from ceres C++ library: ceres-solver/include/ceres/rotation.h

    Args:
        quaternion: tensor with quaternions.
        order: quaternion coefficient order. Note: 'xyzw' will be deprecated in favor of 'wxyz'.

    Return:
        tensor with angle axis of rotation.

    Shape:
        - Input: :math:`(*, 4)` where `*` means, any number of dimensions
        - Output: :math:`(*, 3)`

    Example:
        >>> quaternion = torch.tensor((1., 0., 0., 0.))
        >>> quaternion_to_angle_axis(quaternion)
        tensor([3.1416, 0.0000, 0.0000])
    r8   rQ   rh   z.Input must be a tensor of shape Nx4 or 4. Got r   r   ).r   ).rZ   ).rL   ).rd   r   r`   .Nrd   )r<   	is_tensorr=   r>   rT   rU   r   r   r   r.   r   r   r3   r   r   r   rM   rW   rN   rX   Z
zeros_like)r   r   Zq1Zq2Zq3rs   Zsin_squared_thetart   Z	two_thetak_posk_negkri   r5   r5   r6   r   M  sJ    









r   )r   rK   r   r7   c                 C   s   t | tjstdt|  | jd dks<td| j tj sj|j	t
j vrjtdt
j  |t
jkr~td tj| dddd	j|d
}| t| | }t|}tg }|t
jkrtj||fdd}ntj||fdd}|S )a  Apply exponential map to log quaternion.

    The quaternion should be in (x, y, z, w) or (w, x, y, z) format.

    Args:
        quaternion: a tensor containing a quaternion to be converted.
          The tensor can be of shape :math:`(*, 3)`.
        eps: a small number for clamping.
        order: quaternion coefficient order. Note: 'xyzw' will be deprecated in favor of 'wxyz'.

    Return:
        the quaternion exponential map of shape :math:`(*, 4)`.

    Example:
        >>> quaternion = torch.tensor((0., 0., 0.))
        >>> quaternion_log_to_exp(quaternion, eps=torch.finfo(quaternion.dtype).eps,
        ...                       order=QuaternionCoeffOrder.WXYZ)
        tensor([1., 0., 0., 0.])
    r8   rQ   rd   z,Input must be a tensor of shape (*, 3). Got r   r   rL   Tr   rl   Zkeepdimr   rk   )r;   r<   r   r=   r>   rT   rU   r   r   r   r.   r   r   r3   r   r   normr   rG   rF   r   rn   )r   rK   r   norm_qquaternion_vectorquaternion_scalarZquaternion_expr5   r5   r6   r     s&    




r   c                 C   s  t | tjstdt|  | jd dks<td| j tj sj|j	t
j vrjtdt
j  |t
jkr~td tg }tg }|t
jkr| ddd	f }| dd	df }n | ddd
f }| dd
df }tj|ddddj|d}|ttj|ddd | }|S )a  Apply the log map to a quaternion.

    The quaternion should be in (x, y, z, w) format.

    Args:
        quaternion: a tensor containing a quaternion to be converted.
          The tensor can be of shape :math:`(*, 4)`.
        eps: a small number for clamping.
        order: quaternion coefficient order. Note: 'xyzw' will be deprecated in favor of 'wxyz'.

    Return:
        the quaternion log map of shape :math:`(*, 3)`.

    Example:
        >>> quaternion = torch.tensor((1., 0., 0., 0.))
        >>> quaternion_exp_to_log(quaternion, eps=torch.finfo(quaternion.dtype).eps,
        ...                       order=QuaternionCoeffOrder.WXYZ)
        tensor([0., 0., 0.])
    r8   rQ   rh   r   r   r   .r   rd   rZ   rL   Tr   r         rR   )r   max)r;   r<   r   r=   r>   rT   rU   r   r   r   r.   r   r   r3   r   r   r   r   r   acos)r   rK   r   r   r   r   Zquaternion_logr5   r5   r6   r     s,    




r   )ri   r   r7   c                 C   s  t | stdt|  | jd dks:td| j t j sh|jt	j
 vrhtdt	j
  |t	jkr|td | ddd	f }| dd	d
f }| dd
df }|| ||  ||  }t |}|d }|dk}t |}	d|	 }
t || }t |||
}t |t ||	}t jg | jdd dR | j| jd}|t	jkr|| |ddd	f< || |dd	d
f< || |dd
df< ||dddf< nL|| |dd	d
f< || |dd
df< || |dddf< ||ddd	f< |S )a  Convert an angle axis to a quaternion.

    The quaternion vector has components in (x, y, z, w) or (w, x, y, z) format.

    Adapted from ceres C++ library: ceres-solver/include/ceres/rotation.h

    Args:
        angle_axis: tensor with angle axis in radians.
        order: quaternion coefficient order. Note: 'xyzw' will be deprecated in favor of 'wxyz'.

    Return:
        tensor with quaternion.

    Shape:
        - Input: :math:`(*, 3)` where `*` means, any number of dimensions
        - Output: :math:`(*, 4)`

    Example:
        >>> angle_axis = torch.tensor((0., 1., 0.))
        >>> angle_axis_to_quaternion(angle_axis, order=QuaternionCoeffOrder.WXYZ)
        tensor([0.8776, 0.0000, 0.4794, 0.0000])
    r8   rQ   rd   z.Input must be a tensor of shape Nx3 or 3. Got r   r   .r   rZ   rL   g      ?r`   Nrh   )sizerA   r@   )r<   r   r=   r>   rT   rU   r   r   r   r.   r   r   r3   r   r   rM   rX   rG   rW   rF   zerosrA   r@   )ri   r   Za0Za1Za2Ztheta_squaredrr   Z
half_thetarY   Zonesr   r   r   r   r   r5   r5   r6   r     sH    




r   )pixel_coordinatesheightwidthrK   r7   c                 C   sz   | j d dkrtd| j ttj|| j| jdtj|| j| jdg}tjd| j| jd|d | }||  d S )aR  Normalize pixel coordinates between -1 and 1.

    Normalized, -1 if on extreme left, 1 if on extreme right (x = w-1).

    Args:
        pixel_coordinates: the grid with pixel coordinates. Shape can be :math:`(*, 2)`.
        width: the maximum width in the x-axis.
        height: the maximum height in the y-axis.
        eps: safe division by zero.

    Return:
        the normalized pixel coordinates with shape :math:`(*, 2)`.

    Examples:
        >>> coords = torch.tensor([[50., 100.]])
        >>> normalize_pixel_coordinates(coords, 100, 50)
        tensor([[1.0408, 1.0202]])
    rQ   rL   7Input pixel_coordinates must be of shape (*, 2). Got {}r@   rA   r   rZ   )	rT   rU   formatr<   r   r   r@   rA   r   r   r   r   rK   Zhwfactorr5   r5   r6   r   a  s    r   c                 C   sv   | j d dkrtd| j tt|t|g| j| j}td|d 	| }td| | d  S )aM  Denormalize pixel coordinates.

    The input is assumed to be -1 if on extreme left, 1 if on extreme right (x = w-1).

    Args:
        pixel_coordinates: the normalized grid coordinates. Shape can be :math:`(*, 2)`.
        width: the maximum width in the x-axis.
        height: the maximum height in the y-axis.
        eps: safe division by zero.

    Return:
        the denormalized pixel coordinates with shape :math:`(*, 2)`.

    Examples:
        >>> coords = torch.tensor([[-1., -1.]])
        >>> denormalize_pixel_coordinates(coords, 100, 50)
        tensor([[0., 0.]])
    rQ   rL   r   r   rZ   rR   
rT   rU   r   r<   r   r   r?   r@   rA   r   r   r5   r5   r6   r     s    r   )r   depthr   r   rK   r7   c                 C   st   | j d dkrtd| j tt|t|t|g| j| j}td|d 	| }||  d S )a  Normalize pixel coordinates between -1 and 1.

    Normalized, -1 if on extreme left, 1 if on extreme right (x = w-1).

    Args:
        pixel_coordinates: the grid with pixel coordinates. Shape can be :math:`(*, 3)`.
        depth: the maximum depth in the z-axis.
        height: the maximum height in the y-axis.
        width: the maximum width in the x-axis.
        eps: safe division by zero.

    Return:
        the normalized pixel coordinates.
    rQ   rd   7Input pixel_coordinates must be of shape (*, 3). Got {}r   rZ   r   r   r   r   r   rK   Zdhwr   r5   r5   r6   r     s    "r   c                 C   s~   | j d dkrtd| j tt|t|t|g| j| j}td|d 	| }td| | d  S )a  Denormalize pixel coordinates.

    The input is assumed to be -1 if on extreme left, 1 if on extreme right (x = w-1).

    Args:
        pixel_coordinates: the normalized grid coordinates. Shape can be :math:`(*, 3)`.
        depth: the maximum depth in the x-axis.
        height: the maximum height in the y-axis.
        width: the maximum width in the x-axis.
        eps: safe division by zero.

    Return:
        the denormalized pixel coordinates.
    rQ   rd   r   r   rZ   rR   r   r   r5   r5   r6   r     s    "r   )angler7   c                 C   sJ   t | }t|}t|}tj||| |gddjg | jddR  S )aO  Create a rotation matrix out of angles in degrees.

    Args:
        angle: tensor of angles in degrees, any shape :math:`(*)`.

    Returns:
        tensor of rotation matrices with shape :math:`(*, 2, 2)`.

    Example:
        >>> input = torch.rand(1, 3)  # Nx3
        >>> output = angle_to_rotation_matrix(input)  # Nx3x2x2
    rQ   rk   rL   )r   r<   rF   rG   r   ro   rT   )r   Zang_radZcos_aZsin_ar5   r5   r6   r     s    

r   )dst_pix_trans_src_pix	dsize_src	dsize_dstr7   c                 C   s   t | tjstdt|  t| jdksN| jdd dksNtd| j |\}}|\}}t||	| }t
|}t||	| }	|	| |  }
|
S )a  Normalize a given homography in pixels to [-1, 1].

    Args:
        dst_pix_trans_src_pix: homography/ies from source to destination to be
          normalized. :math:`(B, 3, 3)`
        dsize_src: size of the source image (height, width).
        dsize_dst: size of the destination image (height, width).

    Returns:
        the normalized homography of shape :math:`(B, 3, 3)`.
    r8   rd   re   Nr~   8Input dst_pix_trans_src_pix must be a Bx3x3 tensor. Got r;   r<   r   r=   r>   rS   rT   rU   r#   r?   r	   )r   r   r   src_hsrc_wdst_hdst_wsrc_norm_trans_src_pixsrc_pix_trans_src_normdst_norm_trans_dst_pixdst_norm_trans_src_normr5   r5   r6   r      s     r    +=)r   r   rK   r@   rA   r7   c                 C   s|   t jg dg dg dg||d}|dkr.|n|d }| dkrB|n| d }|d d | |d< |d	 d | |d	< |d
S )a  Compute the normalization matrix from image size in pixels to [-1, 1].

    Args:
        height image height.
        width: image width.
        eps: epsilon to prevent divide-by-zero errors

    Returns:
        normalized transform with shape :math:`(1, 3, 3)`.
    )rR   r`   r   )r`   rR   r   )r`   r`   rR   r   rZ   rR   r   r   r   rZ   rZ   r   r<   r   ry   )r   r   rK   r@   rA   tr_matwidth_denomheight_denomr5   r5   r6   r#     s    "r#   )r   r   r   rK   r@   rA   r7   c           
      C   s   t jg dg dg dg dg||d}|dkr4|n|d }|dkrH|n|d }| dkr\|n| d }	|d d	 | |d< |d
 d	 | |d
< |d d	 |	 |d< |dS )a+  Compute the normalization matrix from image size in pixels to [-1, 1].

    Args:
        depth: image depth.
        height: image height.
        width: image width.
        eps: epsilon to prevent divide-by-zero errors

    Returns:
        normalized transform with shape :math:`(1, 4, 4)`.
    )rR   r`   r`   r   )r`   rR   r`   r   )r`   r`   rR   r   )r`   r`   r`   rR   r   rZ   rR   r   r   r   )rL   rL   r   r   )
r   r   r   rK   r@   rA   r   r   r   Zdepth_denomr5   r5   r6   r$   <  s    r$   c                 C   s   t | tjstdt|  t| jdksN| jdd dksNtd| j |\}}|\}}t||	| }t||	| }t
|}	|	| |  }
|
S )a  De-normalize a given homography in pixels from [-1, 1] to actual height and width.

    Args:
        dst_pix_trans_src_pix: homography/ies from source to destination to be
          denormalized. :math:`(B, 3, 3)`
        dsize_src: size of the source image (height, width).
        dsize_dst: size of the destination image (height, width).

    Returns:
        the denormalized homography of shape :math:`(B, 3, 3)`.
    r8   rd   re   Nr~   r   r   )r   r   r   r   r   r   r   r   r   Zdst_denorm_trans_dst_pixr   r5   r5   r6   r!   a  s     r!   c                 C   s   t | tjstdt|  t| jdksN| jdd dksNtd| j |\}}}|\}}}t|||	| }	t
|	}
t|||	| }|| |
  }|S )a  Normalize a given homography in pixels to [-1, 1].

    Args:
        dst_pix_trans_src_pix: homography/ies from source to destination to be
          normalized. :math:`(B, 4, 4)`
        dsize_src: size of the source image (depth, height, width).
        dsize_src: size of the destination image (depth, height, width).

    Returns:
        the normalized homography.

    Shape:
        Output: :math:`(B, 4, 4)`
    r8   rd   re   N)rh   rh   r   )r;   r<   r   r=   r>   rS   rT   rU   r$   r?   r	   )r   r   r   Zsrc_dr   r   Zdst_dr   r   r   r   r   r   r5   r5   r6   r"     s     

r"   )Rtr7   c                 C   s6   t | g d t |g d tj| |gdd}t|S )a  Combines 3x3 rotation matrix R and 1x3 translation vector t into 4x4 extrinsics.

    Args:
        R: Rotation matrix, :math:`(B, 3, 3).`
        t: Translation matrix :math:`(B, 3, 1)`.

    Returns:
        the extrinsics :math:`(B, 4, 4)`.

    Example:
        >>> R, t = torch.eye(3)[None], torch.ones(3).reshape(1, 3, 1)
        >>> Rt_to_matrix4x4(R, t)
        tensor([[[1., 0., 0., 1.],
                 [0., 1., 0., 1.],
                 [0., 0., 1., 1.],
                 [0., 0., 0., 1.]]])
    B3r   r   r   1rL   rk   )r   r<   rn   r   )r   r   ZRtr5   r5   r6   r'     s    r'   )
extrinsicsr7   c                 C   sL   t | g d | ddddddf | ddddddf  }}||fS )a  Converts 4x4 extrinsics into 3x3 rotation matrix R and 1x3 translation vector ts.

    Args:
        extrinsics: pose matrix :math:`(B, 4, 4)`.

    Returns:
        R: Rotation matrix, :math:`(B, 3, 3).`
        t: Translation matrix :math:`(B, 3, 1)`.

    Example:
        >>> ext = torch.eye(4)[None]
        >>> matrix4x4_to_Rt(ext)
        (tensor([[[1., 0., 0.],
                 [0., 1., 0.],
                 [0., 0., 1.]]]), tensor([[[0.],
                 [0.],
                 [0.]]]))
    r   4r   Nrd   r   )r   r   r   r5   r5   r6   r(     s    6r(   )extrinsics_graphicsr7   c                 C   sB   t | g d tg dg dg dg dgg| j| jd}| | S )a  Converts graphics coordinate frame (e.g. OpenGL) to vision coordinate frame (e.g. OpenCV.), , i.e. flips y
    and z axis. Graphics convention: [+x, +y, +z] == [right, up, backwards]. Vision convention: [+x, +y, +z] ==

    [right, down, forwards]

    Args:
        extrinsics: pose matrix :math:`(B, 4, 4)`.

    Returns:
        extrinsics: pose matrix :math:`(B, 4, 4)`.

    Example:
        >>> ext = torch.eye(4)[None]
        >>> camtoworld_graphics_to_vision_4x4(ext)
        tensor([[[ 1.,  0.,  0.,  0.],
                 [ 0., -1.,  0.,  0.],
                 [ 0.,  0., -1.,  0.],
                 [ 0.,  0.,  0.,  1.]]])
    r   rZ   r   r   r   r   rQ   r   r   r   r   rQ   r   r   r   r   rR   rA   r@   )r   r   rA   r@   )r   	invert_yzr5   r5   r6   r)     s    r)   c                 C   s2   t | g d t |g d tt| |}t|S )a  Converts graphics coordinate frame (e.g. OpenGL) to vision coordinate frame (e.g. OpenCV.), , i.e. flips y
    and z axis. Graphics convention: [+x, +y, +z] == [right, up, backwards]. Vision convention: [+x, +y, +z] ==

    [right, down, forwards]

    Args:
        R: Rotation matrix, :math:`(B, 3, 3).`
        t: Translation matrix :math:`(B, 3, 1)`.

    Returns:
        R: Rotation matrix, :math:`(B, 3, 3).`
        t: Translation matrix :math:`(B, 3, 1)`.

    Example:
        >>> R, t = torch.eye(3)[None], torch.ones(3).reshape(1, 3, 1)
        >>> camtoworld_graphics_to_vision_Rt(R, t)
        (tensor([[[ 1.,  0.,  0.],
                 [ 0., -1.,  0.],
                 [ 0.,  0., -1.]]]), tensor([[[1.],
                 [1.],
                 [1.]]]))
    r   r   )r   r)   r'   r(   r   r   Zmat4x4r5   r5   r6   r+     s    r+   )extrinsics_visionr7   c                 C   sD   t | g d tjg dg dg dg dgg| j| jd}| | S )a{  Converts vision coordinate frame (e.g. OpenCV) to graphics coordinate frame (e.g. OpenGK.), i.e. flips y and
    z axis Graphics convention: [+x, +y, +z] == [right, up, backwards]. Vision convention: [+x, +y, +z] == [right,
    down, forwards]

    Args:
        extrinsics: pose matrix :math:`(B, 4, 4)`.

    Returns:
        extrinsics: pose matrix :math:`(B, 4, 4)`.

    Example:
        >>> ext = torch.eye(4)[None]
        >>> camtoworld_vision_to_graphics_4x4(ext)
        tensor([[[ 1.,  0.,  0.,  0.],
                 [ 0., -1.,  0.,  0.],
                 [ 0.,  0., -1.,  0.],
                 [ 0.,  0.,  0.,  1.]]])
    r   r   r   r   r   r   )r   r<   r   rA   r@   )r   r   r5   r5   r6   r*     s    r*   c                 C   s2   t | g d t |g d tt| |}t|S )a  Converts graphics coordinate frame (e.g. OpenGL) to vision coordinate frame (e.g. OpenCV.), , i.e. flips y
    and z axis. Graphics convention: [+x, +y, +z] == [right, up, backwards]. Vision convention: [+x, +y, +z] ==

    [right, down, forwards]

    Args:
        R: Rotation matrix, :math:`(B, 3, 3).`
        t: Translation matrix :math:`(B, 3, 1)`.

    Returns:
        R: Rotation matrix, :math:`(B, 3, 3).`
        t: Translation matrix :math:`(B, 3, 1)`.

    Example:
        >>> R, t = torch.eye(3)[None], torch.ones(3).reshape(1, 3, 1)
        >>> camtoworld_vision_to_graphics_Rt(R, t)
        (tensor([[[ 1.,  0.,  0.],
                 [ 0., -1.,  0.],
                 [ 0.,  0., -1.]]]), tensor([[[1.],
                 [1.],
                 [1.]]]))
    r   r   )r   r*   r'   r(   r   r5   r5   r6   r,   -  s    r,   c                 C   s:   t | g d t |g d | dd}| | }||fS )a  Converts camtoworld, i.e. projection from camera coordinate system to world coordinate system, to worldtocam
    frame i.e. projection from world to the camera coordinate system (used in Colmap).
    See
    long-url: https://colmap.github.io/format.html#output-format

    Args:
        R: Rotation matrix, :math:`(B, 3, 3).`
        t: Translation matrix :math:`(B, 3, 1)`.

    Returns:
        Rinv: Rotation matrix, :math:`(B, 3, 3).`
        tinv: Translation matrix :math:`(B, 3, 1)`.

    Example:
        >>> R, t = torch.eye(3)[None], torch.ones(3).reshape(1, 3, 1)
        >>> camtoworld_to_worldtocam_Rt(R, t)
        (tensor([[[1., 0., 0.],
                 [0., 1., 0.],
                 [0., 0., 1.]]]), tensor([[[-1.],
                 [-1.],
                 [-1.]]]))
    r   r   rZ   rL   r   r{   r   r   ZR_invZnew_tr5   r5   r6   r&   J  s
    
r&   c                 C   s:   t | g d t |g d | dd}| | }||fS )a  Converts worldtocam frame i.e. projection from world to the camera coordinate system (used in Colmap) to
    camtoworld, i.e. projection from camera coordinate system to world coordinate system.

    Args:
        R: Rotation matrix, :math:`(B, 3, 3).`
        t: Translation matrix :math:`(B, 3, 1)`.

    Returns:
        Rinv: Rotation matrix, :math:`(B, 3, 3).`
        tinv: Translation matrix :math:`(B, 3, 1)`.

    Example:
        >>> R, t = torch.eye(3)[None], torch.ones(3).reshape(1, 3, 1)
        >>> worldtocam_to_camtoworld_Rt(R, t)
        (tensor([[[1., 0., 0.],
                 [0., 1., 0.],
                 [0., 0., 1.]]]), tensor([[[-1.],
                 [-1.],
                 [-1.]]]))
    r   r   rZ   rL   r   r   r5   r5   r6   r%   j  s
    
r%   )qvectvecr7   c                 C   sR   t | tjd}t||\}}t||\}}|ddd}t| tjd}||fS )a  Converts output of Apple ARKit screen pose (in quaternion representation) to the camera-to-world
    transformation, expected by Colmap, also in quaternion representation.

    Args:
        qvec: ARKit rotation quaternion :math:`(B, 4)`, [x, y, z, w] format.
        tvec: translation vector :math:`(B, 3, 1)`, [x, y, z]

    Returns:
        qvec: Colmap rotation quaternion :math:`(B, 4)`, [w, x, y, z] format.
        tvec: translation vector :math:`(B, 3, 1)`, [x, y, z]

    Example:
        >>> q, t = torch.tensor([0, 1, 0, 1.])[None], torch.ones(3).reshape(1, 3, 1)
        >>> ARKitQTVecs_to_ColmapQTVecs(q, t)
        (tensor([[0.7071, 0.0000, 0.7071, 0.0000]]), tensor([[[-1.0000],
                 [-1.0000],
                 [ 1.0000]]]))
    r   rQ   rd   rZ   )r   r.   r4   r+   r&   Zreshaper   
contiguous)r   r   ZRcgZRcvZTcvZR_colmapZt_colmapZq_colmapr5   r5   r6   r-     s    r-   )rJ   )rJ   )r   )rJ   )rJ   )rJ   )rJ   )r   NN)r   NN)?enumr   typingr   r   r<   Ztorch.nn.functionalr\   r]   r   r   r   Zkornia.constantsr   Zkornia.testingr   Zkornia.utils.helpersr	   __all__Enumr.   r
   r   r   floatr   r   r   rc   r   r   r   r   r3   r   r   r   r   r   r   r   intr   r   r   r   r   r    r@   rA   r#   r$   r!   r"   r'   r(   r)   r+   r*   r,   r&   r%   r-   r5   r5   r5   r6   <module>   s   ("&!R d TM9BP 
( 
$   &   !   &#$ 