o
    oi,                     @   s   d dl mZmZ d dlZd dlmZ d dlmZm	Z	m
Z
mZ d dlmZmZmZmZ d dlmZmZ d dlmZ d dlmZ d d	lmZmZ ddejdedeejejf fddZ		ddejdejdejdeej dedejfddZdS )    )OptionalTupleN)qr)arange	ones_likewherezeros)KORNIA_CHECKKORNIA_CHECK_IS_TENSORKORNIA_CHECK_SAME_SHAPEKORNIA_CHECK_SHAPE)convert_points_to_homogeneous normalize_points_with_intrinsics)transform_points)eye_like)_torch_linalg_svdvals_torch_svd_cast:0yE>pointsepsreturnc           	      C   s  t | g d tj| ddd}| | jdddjdd}| jd }tj| jd tj| jd	}t|||  }t	|d | }t
|tj| jd	}|d
d
||f |d
d
d
f  |d
d
||f< |d
d
||f |d
d
d
f  |d
d
d|f   |d
d
||f< t|| }||fS )a\  Normalize points.

    Args:
       points : Tensor containing the points to be normalized with shape :math:`(B, N, D)`.
       eps : Small value to avoid division by zero error.

    Returns:
       Tuple containing the normalized points in the shape :math:`(B, N, D)` and the transformation matrix
       in the shape :math:`(B, D+1, D+1)`.

    )BND   T)dimkeepdim   )r   pr   dtypedeviceNr   )r   torchmeannormshapetensorfloat64r#   sqrtr   r   int64r   )	r   r   x_meanscaleD_intD_float	transformidxspoints_norm r3   S/home/ubuntu/.local/lib/python3.10/site-packages/kornia/geometry/calibration/pnp.py_mean_isotropic_scale_normalize   s   
0D
r5   -C6?world_points
img_points
intrinsicsweightssvd_epsc           #      C   s  t jt jf}t|  t| t| tt|t t| j|v  t|j|v  t|j|v  t| g d t|g d t|g d t	| dddddf |dddddf  t| j
d dk |durkt| | j
dd \}}t| \}}	t|}
t |
ddd	f |k rtd
| dt|}t||}t|\}}t |}t|d| df| j| jd}||dddddddf< ||dddddddf< |d	 |dddf  |dddddddf< |d	 |dddf  |dddddddf< |dur,|j
||fkrtd|j
 d|d	ddd|d| d}|| }t|\}}}|d }||dd}td|}||ddddddf< t ||	}t ||ddddddf }t |ddddddf }t|}t|dk |d	 |}||ddddf  }t j|dddddf ddd}d| ddddf }|| }t|ddddddf \}}td|}t  || } t || }!t j!|!|ddddddf gd	d}"|"S )a9  Attempt to solve the Perspective-n-Point (PnP) problem using Direct Linear Transform (DLT).

    Given a batch (where batch size is :math:`B`) of :math:`N` 3D points
    (where :math:`N \geq 6`) in the world space, a batch of :math:`N`
    corresponding 2D points in the image space and a batch of
    intrinsic matrices, this function tries to estimate a batch of
    world to camera transformation matrices.

    This implementation needs at least 6 points (i.e. :math:`N \geq 6`) to
    provide solutions.

    This function cannot be used if all the 3D world points (of any element
    of the batch) lie on a line or if all the 3D world points (of any element
    of the batch) lie on a plane. This function attempts to check for these
    conditions and throws an AssertionError if found. Do note that this check
    is sensitive to the value of the svd_eps parameter.

    Another bad condition occurs when the camera and the points lie on a
    twisted cubic. However, this function does not check for this condition.

    Args:
        world_points : A tensor with shape :math:`(B, N, 3)` representing
          the points in the world space.
        img_points : A tensor with shape :math:`(B, N, 2)` representing
          the points in the image space.
        intrinsics : A tensor with shape :math:`(B, 3, 3)` representing
          the intrinsic matrices.
        weights : A tensor with shape :math:`(B, N)` representing the
            weights for each point. If None, all points are considered to be equally important.
        svd_eps : A small float value to avoid numerical precision issues.

    Returns:
        A tensor with shape :math:`(B, 3, 4)` representing the estimated world to
        camera transformation matrices (also known as the extrinsic matrices).

    Example:
        >>> world_points = torch.tensor([[
        ...     [ 5. , -5. ,  0. ], [ 0. ,  0. ,  1.5],
        ...     [ 2.5,  3. ,  6. ], [ 9. , -2. ,  3. ],
        ...     [-4. ,  5. ,  2. ], [-5. ,  5. ,  1. ],
        ... ]], dtype=torch.float64)
        >>>
        >>> img_points = torch.tensor([[
        ...     [1409.1504, -800.936 ], [ 407.0207, -182.1229],
        ...     [ 392.7021,  177.9428], [1016.838 ,   -2.9416],
        ...     [ -63.1116,  142.9204], [-219.3874,   99.666 ],
        ... ]], dtype=torch.float64)
        >>>
        >>> intrinsics = torch.tensor([[
        ...     [ 500.,    0.,  250.],
        ...     [   0.,  500.,  250.],
        ...     [   0.,    0.,    1.],
        ... ]], dtype=torch.float64)
        >>>
        >>> print(world_points.shape, img_points.shape, intrinsics.shape)
        torch.Size([1, 6, 3]) torch.Size([1, 6, 2]) torch.Size([1, 3, 3])
        >>>
        >>> pred_world_to_cam = kornia.geometry.solve_pnp_dlt(world_points, img_points, intrinsics)
        >>>
        >>> print(pred_world_to_cam.shape)
        torch.Size([1, 3, 4])
        >>>
        >>> pred_world_to_cam
        tensor([[[ 0.9392, -0.3432, -0.0130,  1.6734],
                 [ 0.3390,  0.9324, -0.1254, -4.3634],
                 [ 0.0552,  0.1134,  0.9920,  3.7785]]], dtype=torch.float64)

    )r   r   3)r   r   2)r   r<   r<   Nr   r      r   r   zQThe last singular value of one/more of the elements of the batch is smaller than z. This function cannot be used if all world_points (of any element of the batch) lie on a line or if all world_points (of any element of the batch) lie on a plane.   r!         .z&Weights should have shape (B, N). Got .).r      )inputr   r   r    )"r$   float32r)   r
   r	   
isinstancefloatr"   r   r   r'   r5   r   anyAssertionErrorr   r   inverser   r#   	unsqueezerepeatviewr   reshaper   bmmdetr   r   r&   	linalg_qrsigncat)#r7   r8   r9   r:   r;   accepted_dtypesr   r   world_points_normworld_transform_normsworld_points_norm_himg_points_invimg_points_normimg_transform_norminv_img_transform_normsystemweights_expanded_vsolutionsolution_4x4intermediaterP   onessign_fixnorm_col
mul_factortemporthorightmaskcol_sign_fixrot_matpred_world_to_camr3   r3   r4   solve_pnp_dlt=   st   T.

00
"
" ""
(ro   )r   )Nr6   )typingr   r   r$   torch.linalgr   rQ   kornia.corer   r   r   r   kornia.core.checkr	   r
   r   r   kornia.geometry.conversionsr   r   kornia.geometry.linalgr   kornia.utilsr   kornia.utils.helpersr   r   TensorrG   r5   ro   r3   r3   r3   r4   <module>   s2   &"