
    3j                       S SK Jr  S SKJr  S SKrS SKJs  Jr  S SK	J
r
  S SKJr  S SKJrJr  S SKJr  / SQrS=S	 jrS=S
 jrS>S jrS?S@S jjrS?SAS jjrSBS jrSCS jrSCS jrSCS jrSDS jr\" SSS9SDS j5       rSES jr\" SSS9SES j5       rS?SFS jjr SGSHS jjr!SIS jr"SIS jr#\" SSS9SIS j5       r$S?SHS  jjr%S?SHS! jjr&SDS" jr'\" S#SS9SDS$ j5       r(          SJS% jr)        SKS& jr* S?         SLS' jjr+ S?         SLS( jjr, S?           SMS) jjr- S?           SMS* jjr.SNS+ jr/        SOS, jr0   SP           SQS- jjr1   SP             SRS. jjr2        SOS/ jr3        SSS0 jr4STS1 jr5SUS2 jr6SVS3 jr7SWS4 jr8SXS5 jr9SYS6 jr:SZS7 jr;SYS8 jr<SYS9 jr=SYS: jr>S[S; jr?S\S< jr@g)]    )annotations)OptionalN)pi)
deprecated)KORNIA_CHECKKORNIA_CHECK_SHAPE)_torch_inverse_cast)-ARKitQTVecs_to_ColmapQTVecsRt_to_matrix4x4angle_axis_to_quaternionangle_axis_to_rotation_matrixangle_to_rotation_matrixaxis_angle_to_quaternionaxis_angle_to_rotation_matrix!camtoworld_graphics_to_vision_4x4 camtoworld_graphics_to_vision_Rtcamtoworld_to_worldtocam_Rt!camtoworld_vision_to_graphics_4x4 camtoworld_vision_to_graphics_Rtcart2pol"convert_affinematrix_to_homography$convert_affinematrix_to_homography3dconvert_points_from_homogeneousconvert_points_to_homogeneousdeg2raddenormalize_homographydenormalize_pixel_coordinatesdenormalize_pixel_coordinates3d"denormalize_points_with_intrinsicseuler_from_quaternionmatrix4x4_to_Rtnormal_transform_pixelnormal_transform_pixel3dnormalize_homographynormalize_homography3dnormalize_pixel_coordinatesnormalize_pixel_coordinates3d normalize_points_with_intrinsicsnormalize_quaternionpol2cartquaternion_exp_to_logquaternion_from_eulerquaternion_log_to_expquaternion_to_angle_axisquaternion_to_axis_anglequaternion_to_rotation_matrixrad2degrotation_matrix_to_angle_axisrotation_matrix_to_axis_anglerotation_matrix_to_quaternionvector_to_skew_symmetric_matrixworldtocam_to_camtoworld_Rtc                    [        U [        R                  5      (       d  [        S[	        U 5       35      eSU -  [
        R                  " U R                  5      R	                  U R                  5      -  $ )zConvert angles from radians to degrees.

Args:
    tensor: torch.Tensor of arbitrary shape.

Returns:
    torch.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torchTensor	TypeErrortyper   todevicedtypetensors    U/home/wildlama/miniconda3/lib/python3.13/site-packages/kornia/geometry/conversions.pyr1   r1   O   sW     fell++@fOPP6>BEE&--055fllCCC    c                    [        U [        R                  5      (       d  [        S[	        U 5       35      eU [
        R                  " U R                  5      R	                  U R                  5      -  S-  $ )zConvert angles from degrees to radians.

Args:
    tensor: torch.Tensor of arbitrary shape.

Returns:
    tensor with same shape as input.

Examples:
    >>> input = torch.tensor(180.)
    >>> deg2rad(input)
    tensor(3.1416)

r8   r9   r:   rC   s    rE   r   r   d   sX     fell++@fOPPBEE&--(--fll;;eCCrF   c                &   [        U [        R                  5      [        U[        R                  5      -  (       d#  [        S[	        U 5       S[	        U5       35      eU [        R
                  " U5      -  nU [        R                  " U5      -  nX#4$ )ao  Convert polar coordinates to cartesian coordinates.

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

Returns:
    - x: torch.Tensor with same shape as input.
    - y: torch.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)rhophixys       rE   r*   r*   y   so    " sELL)JsELL,II@c2dSVi[YZZeiinAeiinA4KrF   c                2   [        U [        R                  5      [        U[        R                  5      -  (       d#  [        S[	        U 5       S[	        U5       35      e[        R
                  " U S-  US-  -   U-   5      n[        R                  " X5      nX44$ )a  Convert cartesian coordinates to polar coordinates.

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

Returns:
    - rho: torch.Tensor with same shape as input.
    - phi: torch.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   rI      )r;   r<   r=   r>   r?   sqrtatan2)rN   rO   epsrL   rM   s        rE   r   r      sx    $ q%,,'*Q*EE@a	DQRG9UVV
**QTAqD[3&
'C
++a
C8OrF   c                   [        U [        R                  5      (       d  [        S[	        U 5       35      e[        U R                  5      S:  a  [        SU R                   35      eU SSS24   n[        R                  " U5      U:  n[        R                  " USX!-   -  [        R                  " U5      5      nX@SSS24   -  $ )ad  Convert 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   rQ   (Input must be at least a 2D tensor. Got .N      ?)r;   r<   r=   r>   r?   lenshape
ValueErrorabswhere	ones_like)pointsrT   z_vecmaskscales        rE   r   r      s      fell++@fOPP
6<<1CFLL>RSS !bc*E
 5)C/DKKcU[15??53IJE#ss(###rF   c                   [        U [        R                  5      (       d  [        S[	        U 5       35      e[        U R                  5      S:  a  [        SU R                   35      e[        R                  " U SS/SS5      $ )aH  Convert 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   rQ   rV   r      constantrX   )
r;   r<   r=   r>   r?   rY   rZ   r[   Fpad)r_   s    rE   r   r      sm     fell++@fOPP
6<<1CFLL>RSS55!QS11rF   c                R    [         R                  " U / SQSSS9nUS==   S-  ss'   U$ )N)r   r   r   rd   re           )value).rW   rW   rX   )rf   rg   )AHs     rE   (_convert_affinematrix_to_homography_implrm      s)    eeA|ZsCAkNcNHrF   c                   [        U [        R                  5      (       d  [        S[	        U 5       35      e[        U R                  5      S:X  a  U R                  SS S:X  d  [        SU R                   35      e[        U 5      $ )a  Convert 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)rQ   ro   z)Input matrix must be a Bx2x3 tensor. Got 	r;   r<   r=   r>   r?   rY   rZ   r[   rm   rk   s    rE   r   r      so    $ a&&@a	JKKLA!''"#,&"8DQWWINOO3A66rF   c                   [        U [        R                  5      (       d  [        S[	        U 5       35      e[        U R                  5      S:X  a  U R                  SS S:X  d  [        SU R                   35      e[        U 5      $ )a  Convert 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   ro   rp   N)ro      z)Input matrix must be a Bx3x4 tensor. Got rq   rr   s    rE   r   r     so    ( a&&@a	JKKLA!''"#,&"8DQWWINOO3A66rF   c                |   [        U [        R                  5      (       d  [        S[	        U 5       35      eU R
                  S   S:X  d  [        SU R
                   35      eS
SS jjnSS jnX -  R                  SS9nU" X5      nU" U 5      nUS:  R                  SS	S	5      n[        R                  " XdU5      nU$ )a  Convert 3d vector of axis-angle rotation to 3x3 rotation matrix.

Args:
    axis_angle: 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.]])
    >>> axis_angle_to_rotation_matrix(input)  # doctest: +ELLIPSIS
    tensor([[[1., ...0., 0.],
             [0., 1., ...0.],
             [...0., 0., 1.]]])

    >>> input = torch.tensor([[1.5708, 0., 0.]])
    >>> axis_angle_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   rW   ro   z(Input size must be a (*, 3) tensor. Got ư>c           	     x   [         R                  " UR                  SS95      nXR                  S5      U-   -  nUR	                  SS9u  pVn[         R
                  " U5      n[         R                  " U5      n	SU-
  n
XV-  nXW-  nXg-  nXU-  U
-  -   nX-  Xy-  -
  nXi-  X-  -   nXy-  X-  -   nXU-  U
-  -   nU* U	-  X-  -   nU* U	-  X-  -   nXY-  X-  -   nXU-  U
-  -   n[         R                  " [         R                  " XU/SS9[         R                  " UUU/SS9[         R                  " UUU/SS9/SS9nU$ )N-q=minrW   rd   dimrX   )r<   rR   clamp	unsqueezeunbindrJ   rK   stack)
axis_angletheta2rT   thetawxyzwxwywz	cos_theta	sin_thetaone_minus_coswxwywxwzwywzr00r01r02r10r11r12r20r21r22rots                           rE   _compute_rotation_matrix?axis_angle_to_rotation_matrix.<locals>._compute_rotation_matrix@  sm   

6<<E<23__R0367[[Q['
IIe$	IIe$	iwwwr'M11"R^3nt33nt33r'M11cIo 44cIo 44nt33r'M11kkSsO4S#sO4S#sO4
 
 
rF   c                    U R                  S5      u  pn[        R                  " U5      n[        R                  " UU* UUUU* U* UU/	SS9R	                  SSS5      nU$ )NrW   r{   ro   )r   r<   r^   r   view)r   rxryrzk_oner   s         rE   _compute_rotation_matrix_taylorFaxis_angle_to_rotation_matrix.<locals>._compute_rotation_matrix_taylord  sv    &&r*
#kk
 
 $r1a. 	 
rF   r{   rd   )rv   )r   torch.Tensorr   r   rT   floatreturnr   r   r   r   r   )
r;   r<   r=   r>   r?   rZ   r[   sumr   r]   )r   r   r   r   
rot_normal
rot_taylorra   rotation_matrixs           rE   r   r   #  s    . j%,,//@jAQ@RSTTB1$CJDTDTCUVWW"H* %**r*2F)*=J0<JTMAq)Dkk$J?OrF   r   z0.7.0)replace_withversionc                    [        U 5      $ N)r   r   s    rE   r   r     s    (44rF   c                    [        U [        R                  5      (       d  [        S[	        U 5       35      eU R
                  SS S:X  d  [        SU R
                   35      e[        U 5      n[        U5      $ )az  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_axis_angle(input)
    tensor([0., 0., 0.])

    >>> input = torch.tensor([[1., 0., 0.],
    ...                       [0., 0., -1.],
    ...                       [0., 1., 0.]])
    >>> rotation_matrix_to_axis_angle(input)
    tensor([1.5708, 0.0000, 0.0000])

r8   rp   Nro   ro   +Input size must be a (*, 3, 3) tensor. Got )	r;   r<   r=   r>   r?   rZ   r[   r4   r/   )r   
quaternions     rE   r3   r3     sr    . ou||44@oAV@WXYY  %/FG\G\F]^__<_MJ#J//rF   r3   c                    [        U 5      $ r   )r3   )r   s    rE   r2   r2     s    (99rF   c                  ^^
^^^^^^^^^^ [        U [        R                  5      (       d  [        S[	        U 5       35      eU R
                  SS S:X  d  [        SU R
                   35      eSS jmU R                  " / U R
                  SS QSP76 n[        R                  " USSS	9u	  m
mmmmmmmmT
T-   T-   mSUUUUUUUUU4	S
 jjnSUU
UUUUUUUUU4S jjnSUU
UUUUUUUUU4S jjnSUU
UUUUUUUUU4S jjn[        R                  " TT:  U" 5       U" 5       5      n[        R                  " T
T:  T
T:  -  U" 5       U5      n[        R                  " TS:  U" 5       U5      n	U	$ )a8  Convert 3x3 rotation matrix to 4d quaternion vector.

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

Args:
    rotation_matrix: the rotation matrix to convert with shape :math:`(*, 3, 3)`.
    eps: small value to avoid zero division.

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)
    tensor([1., 0., 0., 0.])

r8   rp   Nr   r   c                    [         R                  " U R                  5      R                  nU [         R                  " XS9-  $ )Nry   )r<   finforB   tinyr}   )	numeratordenominatorrT   s      rE   safe_zero_division9rotation_matrix_to_quaternion.<locals>.safe_zero_division  s.    [[1665;;{<<<rF   	   rW   )chunksr|   c                    >	 [         R                  " TS-   T-   5      S-  n SU -  nT" TT	-
  U 5      nT" TT
-
  U 5      nT" TT-
  U 5      n[         R                  " XX44SS9$ NrX          @g      ?rW   r{   r<   rR   cat)sqqwqxqyqzrT   m01m02m10m12m20m21r   traces        rE   trace_positive_cond:rotation_matrix_to_quaternion.<locals>.trace_positive_cond  sn    ZZc)*S0BYc	2.c	2.c	2.yy"")r22rF   c                    > [         R                  " ST-   T
-
  T-
  T-   5      S-  n T" TT-
  U 5      nSU -  nT" TT	-   U 5      nT" TT-   U 5      n[         R                  " XX44SS9$ r   r   r   r   r   r   r   rT   m00r   r   r   m11r   r   r   m22r   s        rE   cond_1-rotation_matrix_to_quaternion.<locals>.cond_1  sw    ZZc	C#-34s:c	2.BYc	2.c	2.yy"")r22rF   c                    > [         R                  " ST
-   T-
  T-
  T-   5      S-  n T" TT-
  U 5      nT" TT	-   U 5      nSU -  nT" TT-   U 5      n[         R                  " XX44SS9$ r   r   r   s        rE   cond_2-rotation_matrix_to_quaternion.<locals>.cond_2  sw    ZZc	C#-34s:c	2.c	2.BYc	2.yy"")r22rF   c                    > [         R                  " ST-   T-
  T
-
  T-   5      S-  n T" T	T-
  U 5      nT" TT-   U 5      nT" TT-   U 5      nSU -  n[         R                  " XX44SS9$ r   r   r   s        rE   cond_3-rotation_matrix_to_quaternion.<locals>.cond_3  sw    ZZc	C#-34s:c	2.c	2.c	2.BYyy"")r22rF   ri   )r   r   r   r   r   r   )r   r   )
r;   r<   r=   r>   r?   rZ   r[   reshapechunkr]   )r   rT   rotation_matrix_vecr   r   r   r   where_2where_1r   r   r   r   r   r   r   r   r   r   r   r   s    `        @@@@@@@@@@@rE   r4   r4     sX   ( ou||44@oAV@WXYY  %/FG\G\F]^__= )8(?(?(_AVAVWZXZA[(_]^(_27++>QZ[ac2d/Cc3S#sC)c/E3 33 3 33 3 33 3 3 kk#)VXvx8Gkk39s3VXwGG${{53;8K8MwWJrF   c                    [        U [        R                  5      (       d  [        S[	        U 5       35      eU R
                  S   S:X  d  [        SU R
                   35      e[        R                  " U SSUS9$ )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   rW   rt   ,Input must be a tensor of shape (*, 4). Got r   )pr|   rT   )	r;   r<   r=   r>   r?   rZ   r[   rf   	normalize)r   rT   s     rE   r)   r)     sp    & j%,,//@jAQ@RSTTB1$G
HXHXGYZ[[;;zSbc::rF   c                p   [        U [        R                  5      (       d  [        S[	        U 5       35      eU R
                  S   S:X  d  [        SU R
                   35      e[        U 5      nUS   nUS   nUS   nUS   nS	U-  nS	U-  nS	U-  nXb-  n	Xr-  n
X-  nXc-  nXs-  nX-  nXt-  nX-  nX-  n[        R                  " S
5      n[        R                  " UUU-   -
  X-
  X-   X-   UUU-   -
  UU	-
  X-
  UU	-   UX-   -
  4	SS9n/ [        U R
                  SS 5      QSPSPnUR                  U5      nU$ )a  Convert a quaternion to a rotation matrix.

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

Args:
    quaternion: a tensor containing a quaternion to be converted.
      The tensor can be of shape :math:`(*, 4)`.

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

Example:
    >>> quaternion = torch.tensor((0., 0., 0., 1.))
    >>> quaternion_to_rotation_matrix(quaternion)
    tensor([[-1.,  0.,  0.],
            [ 0., -1.,  0.],
            [ 0.,  0.,  1.]])

r8   rW   rt   r   .r   .rd   .rQ   .ro   r   rX   r{   Nro   )r;   r<   r=   r>   r?   rZ   r[   r)   rD   r   listr   )r   quaternion_normwrN   rO   ztxtytztwxtwytwztxxtxytxztyytyztzzonematrix_flatoutput_shapematrixs                         rE   r0   r0     s   ( j%,,//@jAQ@RSTTB1$G
HXHXGYZ[[ %9$DO 	AAAA QwBQwBQwBCCCCCCCCCS)C %39III39#II#I39
	
 !K  8T***3B/07!7Q7L  .FMrF   c           	     |   [        U [        R                  5      (       d  [        S[	        U 5       35      eU R
                  S   S:X  d  [        SU R
                   35      e[        R                  " / 5      n[        R                  " / 5      n[        R                  " / 5      n[        R                  " / 5      nU S   nU S   nU S   nU S   nX-  X"-  -   X3-  -   n[        R                  " U5      nS	[        R                  " US
:  [        R                  " U* U* 5      [        R                  " Xd5      5      -  nXv-  nS	[        R                  " U5      -  n	[        R                  " US
:  X5      n
[        R                  " U 5      SSS24   nUS==   X-  -  ss'   US==   X*-  -  ss'   US==   X:-  -  ss'   U$ )a
  Convert quaternion vector to axis angle of rotation in radians.

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

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

Args:
    quaternion: tensor with quaternions.

Return:
    tensor with axis angle 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_axis_angle(quaternion)
    tensor([0., 0., 0.])

r8   rW   rt   z.Input must be a tensor of shape Nx4 or 4. Got r   r   r   r   r   ri   .Nro   )r;   r<   r=   r>   r?   rZ   r[   rD   rR   r]   rS   r^   
zeros_like)r   q1q2q3r   sin_squared_thetar   	two_thetak_posk_negkr   s               rE   r/   r/   b  s   . j%,,//@jAQ@RSTTB1$I*JZJZI[\]] ||B'B||B'B||B'B#ll2.I6"I	F	B	F	B	F	B&(g&7"'&A#jj):;I!EKKCiZ)<ekk)>_% I $/E	 ::Ekk"3c"95HA$//
;C!GDJv"& v"& v"& rF   r/   c                    [        U 5      $ r   )r/   )r   s    rE   r.   r.         #J//rF   c                   [        U [        R                  5      (       d  [        S[	        U 5       35      eU R
                  S   S:X  d  [        SU R
                   35      e[        R                  " U SSSS9R                  US9nU [        R                  " U5      -  U-  n[        R                  " U5      n[        R                  " / 5      n[        R                  " XC4SS	9nU$ )
a  Apply exponential map to log quaternion.

The quaternion should be in (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.

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)
    tensor([1., 0., 0., 0.])

r8   rW   ro   z,Input must be a tensor of shape (*, 3). Got rQ   Tr   r|   keepdimry   r{   )r;   r<   r=   r>   r?   rZ   r[   normr}   rK   rJ   rD   r   )r   rT   norm_qquaternion_vectorquaternion_scalarquaternion_exps         rE   r-   r-     s    & j%,,//@jAQ@RSTTB1$G
HXHXGYZ[[ !::jA2tLRRWZR[F '1599V3D&Dv&M&+ii&7 $)<<#3NYY 1E2NNrF   c           	        [        U [        R                  5      (       d  [        S[	        U 5       35      eU R
                  S   S:X  d  [        SU R
                   35      e[        R                  " / 5      n[        R                  " / 5      nU SSS24   nU SSS24   n[        R                  " USSS	S
9R                  US9nU[        R                  " [        R                  " USSS95      -  U-  nU$ )a  Apply the log map to a quaternion.

The quaternion should be in (w, x, y, z) 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.

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)
    tensor([0., 0., 0.])

r8   rW   rt   r   .r   rd   rQ   Tr  ry         rX   rz   max)r;   r<   r=   r>   r?   rZ   r[   rD   r  r}   acos)r   rT   r  r  r  quaternion_logs         rE   r+   r+     s    & j%,,//@jAQ@RSTTB1$G
HXHXGYZ[[ ',ll2&6&+ll2&6"3!8,"3!8, !::&71"dSYY^aYbF 	EJJu{{3D$TW'XYY\bb  rF   c                   [        U [        R                  5      (       d  [        S[	        U 5       35      eU R
                  S   S:X  d  [        SU R
                   35      eU SSS24   nU SSS24   nU SSS24   nX-  X"-  -   X3-  -   n[        R                  " U5      nUS	-  nUS
:  n[        R                  " U5      nS	U-  n	[        R                  " U5      U-  n
[        R                  " XzU	5      n[        R                  " U[        R                  " U5      U5      n[        R                  " / U R
                  SS QSP7U R                  U R                  S9nX-  USSS24'   X+-  USSS24'   X;-  USSS24'   XSSS24'   U$ )a  Convert an axis angle to a quaternion.

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

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

Args:
    axis_angle: tensor with axis angle in radians.

Return:
    tensor with quaternion.

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

Example:
    >>> axis_angle = torch.tensor((0., 1., 0.))
    >>> axis_angle_to_quaternion(axis_angle)
    tensor([0.8776, 0.0000, 0.4794, 0.0000])

r8   rW   ro   z.Input must be a tensor of shape Nx3 or 3. Got .r   rd   rQ         ?ri   Nrt   )sizerB   rA   )r;   r<   r=   r>   r?   rZ   r[   rR   r^   rK   r]   rJ   zerosrB   rA   )r   a0a1a2theta_squaredr   
half_thetara   onesr  r  r	  r   r   s                 rE   r   r     s   . j%,,//@jAQ@RSTTB1$I*JZJZI[\]] "#qs(+B!#qs(+B!#qs(+B"$'BG"3bg"=M**]3E$s{J&,D4D*E))J/%7Ekk$u5Akk$		*(=tDA${{(z$(a(
0@0@IZIZ J 6JsAaCx6JsAaCx6JsAaCxsAaCxrF   r   c                    [        U 5      $ r   )r   r   s    rE   r   r   /  r  rF   c                   [        U R                  UR                  :H  5        [        UR                  UR                  :H  5        [        UR                  UR                  :H  5        X"-  nSX-  X#-  -   -  nSSX-  U-   -  -
  nUR                  U5      nSX-  X1-  -
  -  nUR                  SSS9nUR	                  5       n	SX-  X-  -   -  n
SSXCU-  -   -  -
  nU
R                  U5      nXyU4$ )aX  Convert a quaternion coefficients to Euler angles.

Returned angles are in radians in XYZ convention.

Args:
    w: quaternion :math:`q_w` coefficient.
    x: quaternion :math:`q_x` coefficient.
    y: quaternion :math:`q_y` coefficient.
    z: quaternion :math:`q_z` coefficient.

Return:
    A tuple with euler angles`roll`, `pitch`, `yaw`.

r   rX   r  r  )r   rZ   rS   r}   asin)r   rN   rO   r   yy	sinr_cosp	cosr_cosprollsinppitch	siny_cosp	cosy_cospyaws                rE   r    r    7  s    " AGG#$AGG#$AGG#$	
Bququ}%IcQURZ((I??9%D!%!%- D::$C:(DIIKEququ}%IcRa%Z((I
//)
$CrF   c                   [        U R                  UR                  :H  5        [        UR                  UR                  :H  5        U S-  nUS-  nUS-  nUR                  5       nUR                  5       nUR                  5       nUR                  5       n	UR                  5       n
UR                  5       nXh-  U
-  Xy-  U-  -   nXh-  U-  Xy-  U
-  -
  nXx-  U-  Xi-  U
-  -   nXx-  U
-  Xi-  U-  -
  nXX4$ )a  Convert Euler angles to quaternion coefficients.

Euler angles are assumed to be in radians in XYZ convention.

Args:
    roll: the roll euler angle.
    pitch: the pitch euler angle.
    yaw: the yaw euler angle.

Return:
    A tuple with quaternion coefficients in order of `wxyz`.

r  )r   rZ   rJ   rK   )r*  r,  r/  	roll_half
pitch_halfyaw_halfcysycpspcrsrr   r   r   r   s                   rE   r,   r,   ]  s      u{{*+		)*s
IJSyH	B	B		B		B	B	B	2"	$B	2"	$B	2"	$B	2"	$B2>rF   c           	        U R                   S   S:w  a  [        SU R                    35      e[        R                  " [        R                  " X R
                  U R                  S9[        R                  " XR
                  U R                  S9/5      n[        R                  " SU R
                  U R                  S9US-
  R                  U5      -  nXP-  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:`(*, 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]])

rW   rQ   5Input pixel_coordinates must be of shape (*, 2). Got rA   rB   r   rd   )rZ   r[   r<   r   rD   rA   rB   r}   pixel_coordinatesheightwidthrT   hwfactors         rE   r&   r&     s    , r"a'PQbQhQhPijkk {{LL'?'?GXG^G^_LL(@(@HYH_H_`	
B !<<4E4L4LTeTkTkl
QeCjF %))rF   c                   U R                   S   S:w  a  [        SU R                    35      e[        R                  " [        R                  " U5      [        R                  " U5      /5      R                  U R                  5      R                  U R                  5      n[        R                  " S5      US-
  R                  U5      -  n[        R                  " S5      U-  U 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:`(*, 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.]])

rW   rQ   r;  r   rd   rX   	rZ   r[   r<   r   rD   r@   rA   rB   r}   r=  s         rE   r   r     s    , r"a'PQbQhQhPijkk 	U\\%(%,,v*>?@	$$	%	##	$  !<<,Q~~c/BBF<<v%):Q)>??rF   c                   U R                   S   S:w  a  [        SU R                    35      e[        R                  " [        R                  " U5      [        R                  " U5      [        R                  " U5      /5      R                  U R                  5      R                  U R                  5      n[        R                  " S5      US-
  R                  U5      -  nX`-  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.

rW   ro   5Input pixel_coordinates must be of shape (*, 3). Got r   rd   rD  r>  depthr?  r@  rT   dhwrB  s          rE   r'   r'     s    $ r"a'PQbQhQhPijkk 	U\\%(%,,u*=u||F?STU	$$	%	##	$  !<<,as/CCF%))rF   c                   U R                   S   S:w  a  [        SU R                    35      e[        R                  " [        R                  " U5      [        R                  " U5      [        R                  " U5      /5      R                  U R                  5      R                  U R                  5      n[        R                  " S5      US-
  R                  U5      -  n[        R                  " S5      U-  U 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.

rW   ro   rF  r   rd   rX   rD  rG  s          rE   r   r     s    $ r"a'PQbQhQhPijkk 	U\\%(%,,u*=u||F?STU	$$	%	##	$  !<<,as/CCF<<v%):Q)>??rF   c                    [        U 5      n[        R                  " U5      n[        R                  " U5      n[        R                  " X#U* U/SS9R
                  " / U R                  QSPSP76 $ )a0  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

rW   r{   rQ   )r   r<   rJ   rK   r   r   rZ   )angleang_radcos_asin_as       rE   r   r     sa     enG))G,E))G,E;;ufe4"=BBVEKKVQRVTUVVrF   c                   [        U [        R                  5      (       d  [        S[	        U 5       35      e[        U R                  5      S:X  d+  U R                  SS S:X  d  [        SU R                   35      eUu  p4Uu  pV[        X45      R                  U 5      n[        U5      n[        XV5      R                  U 5      n	XU-  -  n
U
$ )ae  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   ro   rp   Nr   8Input dst_pix_trans_src_pix must be a Bx3x3 tensor. Got r;   r<   r=   r>   r?   rY   rZ   r[   r"   r@   r	   )dst_pix_trans_src_pix	dsize_src	dsize_dst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_norms              rE   r$   r$   '  s     +U\\::@F[A\@]^__%++,15J5P5PQSQT5UY_5_STiToToSpqrr LELE ,B%+O+R+RSh+i01GH+A%+O+R+RSh+i -C^tFt,u""rF   c                    [         R                  " / SQ/ SQ/ SQ/X4S9nUS:X  a  UOUS-
  nU S:X  a  UOU S-
  nUS   S-  U-  US'   US	   S-  U-  US	'   UR                  S
5      $ )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
    device: device to place the result on.
    dtype: dtype of the result.

Returns:
    normalized transform with shape :math:`(1, 3, 3)`.

)rX   ri   r  )ri   rX   r  )ri   ri   rX   r<  rd   rX   r   r   r   rd   rd   r   r<   rD   r~   )r?  r@  rT   rA   rB   tr_matwidth_denomheight_denoms           rE   r"   r"   K  s    ( \\+-=OX^lF !&
K!'1#&3,L$<#%3F4L$<#%4F4LArF   c                
   [         R                  " / SQ/ SQ/ SQ/ SQ/UUS9nUS:X  a  UOUS-
  nUS:X  a  UOUS-
  nU S:X  a  UOU S-
  n	US   S	-  U-  US'   US
   S	-  U-  US
'   US   S	-  U	-  US'   UR                  S5      $ )aW  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
    device: device to place the result on.
    dtype: dtype of the result.

Returns:
    normalized transform with shape :math:`(1, 4, 4)`.

)rX   ri   ri   r  )ri   rX   ri   r  )ri   ri   rX   r  )ri   ri   ri   rX   r<  rd   rX   r_  r   r`  )rQ   rQ   r   ra  )
rH  r?  r@  rT   rA   rB   rb  rc  rd  depth_denoms
             rE   r#   r#   k  s    , \\	 57LNbcF !&
K!'1#&3,L %
K$<#%3F4L$<#%4F4L$<#%3F4LArF   c                   [        U [        R                  5      (       d  [        S[	        U 5       35      e[        U R                  5      S:X  d+  U R                  SS S:X  d  [        SU R                   35      eUu  p4Uu  pV[        X45      R                  U 5      n[        XV5      R                  U 5      n[        U5      n	XU-  -  n
U
$ )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   ro   rp   Nr   rQ  rR  )rS  rT  rU  rV  rW  rX  rY  rZ  r\  dst_denorm_trans_dst_pixr]  s              rE   r   r     s     +U\\::@F[A\@]^__%++,15J5P5PQSQT5UY_5_STiToToSpqrr LELE ,B%+O+R+RSh+i+A%+O+R+RSh+i23IJ,D`vHv,w""rF   c                   [        U [        R                  5      (       d  [        S[	        U 5       35      e[        U R                  5      S:X  d+  U R                  SS S:X  d  [        SU R                   35      eUu  p4nUu  pgn[        X4U5      R                  U 5      n	[        U	5      n
[        XgU5      R                  U 5      nXU
-  -  nU$ )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_dst: size of the destination image (depth, height, width).

Returns:
    the normalized homography.

Shape:
    Output: :math:`(B, 4, 4)`

r8   ro   rp   N)rt   rt   rQ  )r;   r<   r=   r>   r?   rY   rZ   r[   r#   r@   r	   )rS  rT  rU  src_drV  rW  dst_drX  rY  rZ  r[  r\  r]  s                rE   r%   r%     s    $ +U\\::@F[A\@]^__%++,15J5P5PQSQT5UY_5_STiToToSpqrr $E%#E%+CERW+X+[+[\q+r01GH+CERW+X+[+[\q+r,B^tFt,u""rF   c                .   [        U SS/5        [        U/ SQ5        USSS2S4   nUSSS2SS24   R                  SSS	9n[        UR                  5      [        U R                  5      :  a!  UR	                  S5      UR	                  S5      p2X-
  U-  nU$ )
ah  Normalize points with intrinsics. Useful for conversion of keypoints to be used with essential matrix.

Args:
    point_2d: tensor containing the 2d points in the image pixel coordinates. The shape of the tensor can be
              :math:`(*, 2)`.
    camera_matrix: tensor containing the intrinsics camera matrix. The tensor shape must be :math:`(*, 3, 3)`.

Returns:
    tensor of (u, v) cam coordinates with shape :math:`(*, 2)`.

Example:
    >>> _ = torch.manual_seed(0)
    >>> X = torch.rand(1, 2)
    >>> K = torch.eye(3)[None]
    >>> normalize_points_with_intrinsics(X, K)
    tensor([[0.4963, 0.7682]])

*2rm  3rp  .NrQ   rp   rW   dim1dim2r   diagonalrY   rZ   r~   )point_2dcamera_matrixcxcyfxfyxys        rE   r(   r(     s    & x#s,}o6 bqb!$Dbqb"1"%..BR.@D
4::X^^,,^^B');d
/T	!BIrF   c                *   [        U SS/5        [        U/ SQ5        USSS2SS24   R                  SSS	9nUSSS2S4   n[        UR                  5      [        U R                  5      :  a!  UR	                  S5      UR	                  S5      p2X-  U-   $ )
at  Normalize points with intrinsics. Useful for conversion of keypoints to be used with essential matrix.

Args:
    point_2d_norm: tensor containing the 2d points in the image pixel coordinates. The shape of the tensor can be
                   :math:`(*, 2)`.
    camera_matrix: tensor containing the intrinsics camera matrix. The tensor shape must be :math:`(*, 3, 3)`.

Returns:
    tensor of (u, v) cam coordinates with shape :math:`(*, 2)`.

Example:
    >>> _ = torch.manual_seed(0)
    >>> X = torch.rand(1, 2)
    >>> K = torch.eye(3)[None]
    >>> denormalize_points_with_intrinsics(X, K)
    tensor([[0.4963, 0.7682]])

rm  rn  ro  .NrQ   rp   rW   rq  rt  )point_2d_normrw  ry  rx  s       rE   r   r     s    & }sCj1}o6
 bqb"1"%..BR.@Dbqb!$D
4::]0011^^B');d$&&rF   c                |    [        U / SQ5        [        U/ SQ5        [        R                  " X/SS9n[        U5      $ )a  Combine 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.]]])

Brp  rp  r  rp  1rQ   r{   )r   r<   r   r   )RtRts      rE   r   r     s5    & q/*q/*	A6q	!B/33rF   c                Z    [        U / SQ5        U SS2SS2SS24   U SS2SS2SS24   p!X4$ )a  Convert 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  Nro   )r   )
extrinsicsr  r  s      rE   r!   r!   6  s@    ( z?3a!RaRi *QABY"7q4KrF   c                    [        U / SQ5        [        R                  " / SQ/ SQ/ SQ/ SQ//U R                  U R                  S9nX-  $ )aO  Convert 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_graphics: 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  rd   r   r   r   r   rW   r   r   r   r   rW   r   r   r   r   rX   rB   rA   r   r<   rD   rB   rA   )extrinsics_graphics	invert_yzs     rE   r   r   O  sI    * *O<
}n	EF!''"))I
 **rF   c                x    [        U / SQ5        [        U/ SQ5        [        [        X5      5      n[        U5      $ )a  Convert 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  mat4x4s      rE   r   r   m  2    0 q/*q/*.q/DEF6""rF   c                    [        U / SQ5        [        R                  " / SQ/ SQ/ SQ/ SQ//U R                  U R                  S9nX-  $ )aL  Convert 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_vision: 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  )extrinsics_visionr  s     rE   r   r     sI    * (/:
}n	EF%% ''I
 ((rF   c                x    [        U / SQ5        [        U/ SQ5        [        [        X5      5      n[        U5      $ )a  Convert 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  s      rE   r   r     r  rF   c                p    [        U / SQ5        [        U/ SQ5        U R                  SS5      nU* U-  nX#4$ )aG  Convert camtoworld to worldtocam frame 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  rd   rQ   r   	transposer  r  R_invnew_ts       rE   r   r     s;    0 q/*q/*KK1E &1*E>rF   c                p    [        U / SQ5        [        U/ SQ5        U R                  SS5      nU* U-  nX#4$ )a  Convert worldtocam frame used in Colmap to camtoworld.

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  rd   rQ   r  r  s       rE   r6   r6     s;    * q/*q/*KK1E &1*E>rF   c                    [        U 5      n[        X!5      u  p4[        X45      u  pVUR                  SSS5      n[	        UR                  5       5      nXv4$ )a  Convert output of Apple ARKit screen pose to the camera-to-world transformation, expected by Colmap.

Both poses in quaternion representation.

Args:
    qvec: ARKit rotation quaternion :math:`(B, 4)`, [w, x, y, z] 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]]]))

rW   ro   rd   )r0   r   r   r   r4   
contiguous)qvectvecRcgRcvTcvR_colmapt_colmapq_colmaps           rE   r
   r
     sW    . (
-C/:HC4S>HAq)H,X-@-@-BCHrF   c           	        U R                   S   S:w  d  [        U R                   5      S:  a  [        SU R                    35      eU S   U S   U S   p2n[        R                  " U5      n[        R
                  " [        R
                  " XC* U/SS9[        R
                  " X4U* /SS9[        R
                  " U* X/SS9/S	S9nU$ )
a  Convert a vector to a skew symmetric matrix.

A vector :math:`(v1, v2, v3)` has a corresponding skew-symmetric matrix, which is of the form:

.. math::
    \begin{bmatrix} 0 & -v3 & v2 \\
    v3 & 0 & -v1 \\
    -v2 & v1 & 0\end{bmatrix}

Args:
    vec: tensor of shape :math:`(B, 3)`.

Returns:
    tensor of shape :math:`(B, 3, 3)`.

Example:
    >>> vec = torch.tensor([1.0, 2.0, 3.0])
    >>> vector_to_skew_symmetric_matrix(vec)
    tensor([[ 0., -3.,  2.],
            [ 3.,  0., -1.],
            [-2.,  1.,  0.]])

rW   ro   rQ   z2Input vector must be of shape (B, 3) or (3,). Got r   r   r   r{   rp   )rZ   rY   r[   r<   r  r   )vecv1v2v3r  skew_symmetric_matrixs         rE   r5   r5   %  s    2 yy}S^a/Mcii[YZZVc&k3v;BBR E!KKKKR(b1KKRC(b1KK"b(b1	

  ! rF   )rD   r   r   r   )rL   r   rM   r   r   !tuple[torch.Tensor, torch.Tensor])g:0yE>)rN   r   rO   r   rT   r   r   r  )r_   r   rT   r   r   r   )r_   r   r   r   )rk   r   r   r   r   )r   r   r   r   )r   r   rT   r   r   r   )rx   )r   r   rT   r   r   r   )r   r   r   r   )
r   r   rN   r   rO   r   r   r   r   z/tuple[torch.Tensor, torch.Tensor, torch.Tensor])r*  r   r,  r   r/  r   r   z=tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor])
r>  r   r?  intr@  r  rT   r   r   r   )r>  r   rH  r  r?  r  r@  r  rT   r   r   r   )rL  r   r   r   )rS  r   rT  tuple[int, int]rU  r  r   r   )g+=NN)r?  r  r@  r  rT   r   rA   Optional[torch.device]rB   Optional[torch.dtype]r   r   )rH  r  r?  r  r@  r  rT   r   rA   r  rB   r  r   r   )rS  r   rT  tuple[int, int, int]rU  r  r   r   )rv  r   rw  r   r   r   )r|  r   rw  r   r   r   )r  r   r  r   r   r   )r  r   r   r  )r  r   r   r   )r  r   r  r   r   r  )r  r   r   r   )r  r   r  r   r   r  )r  r   r   r   )A
__future__r   typingr   r<   torch.nn.functionalnn
functionalrf   kornia.constantsr   kornia.core._compatr   kornia.core.checkr   r   kornia.core.utilsr	   __all__r1   r   r*   r   r   r   rm   r   r   r   r   r3   r2   r4   r)   r0   r/   r.   r-   r+   r   r   r    r,   r&   r   r'   r   r   r$   r"   r#   r   r%   r(   r   r   r!   r   r   r   r   r   r6   r
   r5    rF   rE   <module>r     s  $ #      * > 1.bD*D*24$D2.767:_D 8'J5 K50@ 8'J: K:HV;@EP7t 3WE0 F0$N(^5p 3WE0 F0##$#)5#:F#4#L#
#+#2>#B#V LP%*#%*-0%*9<%*CH%*%*R LP!@#!@-0!@9<!@CH!@!@J X\*#*,/*9<*EH*OT**B X\@#@,/@9<@EH@OT@@@W(!#'!#4C!#P_!#!#N %)#' 
 #	
 ! H %)#'%%% % 
	%
 #% !% %P #' #4C #P_ # #F"#'"#4H"#Ui"#"#JD'@422+<#<)<#<B<>%!rF   