o
    oiIC                     @   s  d Z ddlmZmZmZ ddlZddlmZmZm	Z	m
Z
mZmZ ddl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 d3dededeeef fddZd3dededefddZdededefddZd4dededee defddZ	d5dededee ded def
ddZdededefd d!Z d"ededefd#d$Z!d%ed&ed'edefd(d)Z"d*ed+ed,edefd-d.Z#d/ed0edefd1d2Z$dS )6zKModule containing the functionalities for computing the Fundamental Matrix.    )LiteralOptionalTupleN)Tensorconcatenate	ones_likestackwherezeros)KORNIA_CHECK_SAME_SHAPEKORNIA_CHECK_SHAPE)convert_points_from_homogeneousconvert_points_to_homogeneous)transform_points)solve_cubic)_torch_svd_castsafe_inverse_with_mask:0yE>pointsepsreturnc              
   C   s   t | jdkrt| j| jd dkrt| jtj| ddd}| | jdddjdd}ttd	||  }t|t	|}}t
||| |d
  ||| |d  |||g	dd}|ddd}t|| }||fS )a  Normalize points (isotropic).

    Computes the transformation matrix such that the two principal moments of the set of points
    are equal to unity, forming an approximately symmetric circular cloud of points of radius 1
    about the origin. Reference: Hartley/Zisserman 4.4.4 pag.107

    This operation is an essential step before applying the DLT algorithm in order to consider
    the result as optimal.

    Args:
       points: Tensor containing the points to be normalized with shape :math:`(B, N, 2)`.
       eps: epsilon value to avoid numerical instabilities.

    Returns:
       tuple containing the normalized points in the shape :math:`(B, N, 2)` and the transformation matrix
       in the shape :math:`(B, 3, 3)`.

             T)dimkeepdim)r   pr   g       @).r   r   ).r   r   )lenshapeAssertionErrortorchmeannormsqrttensorr   
zeros_liker   viewr   )r   r   x_meanscaleonesr
   	transformpoints_norm r.   X/home/ubuntu/.local/lib/python3.10/site-packages/kornia/geometry/epipolar/fundamental.pynormalize_points    s   

*
r0   Mc                 C   sJ   t | jdk rt| j| dddddf }t| |k| ||  | S )a  Normalize a given transformation matrix.

    The function trakes the transformation matrix and normalize so that the value in
    the last row and column is one.

    Args:
        M: The transformation to be normalized of any shape with a minimum size of 2x2.
        eps: small value to avoid unstabilities during the backpropagation.

    Returns:
        the normalized transformation matrix with same shape as the input.

    r   .r   N)r   r    r!   r	   abs)r1   r   norm_valr.   r.   r/   normalize_transformationI   s   
r4   points1points2c               
   C   s:  t | g d t |g d | jd }t| \}}t|\}}tj|ddd\}}tj|ddd\}	}
t|}t|	| |	| |	|
| |
| |
|||g	d}t|\}}}|d ddd}|d ddd}t	|d	f|j
|jd
}tj|}tj|}||dddf< td|t|d  | |dddf< td|t|d  | |dddf< ||dddf< t|}t	|dddf|j
|jd
}tj|dddk tj|dddkB }|}t|}||ddf jdd||  ||ddf jdd }t|tjd|j
|jd
 }d||  ||< || ||  ||< |d|ddd}|d|ddd}|| ||ddddf  || ||ddddf   ||< t	ddtjd}d|d< d|||f< d|| |f< || dd|jd dd}|| dd|jd dd}t|ddt|| |||< t|S )ay  Compute the fundamental matrix using the 7-point algorithm.

    Args:
        points1: A set of points in the first image with a tensor shape :math:`(B, N, 2)`.
        points2: A set of points in the second image with a tensor shape :math:`(B, N, 2)`.

    Returns:
        the computed fundamental matrix with shape :math:`(B, 3*m, 3), Valid values of m are 1, 2 or 3`

    )B72r   r   r   r   chunks).   r   ).      devicedtypeNzbii->br   r                 ?)rA   T)r   r   )r   r    r0   r"   chunkr   r   r   r(   r
   r@   rA   linalgdeteinsumr   r   count_nonzero	unsqueezeiscloser&   expandboolmatmul	transposer4   ) r5   r6   
batch_sizepoints1_norm
transform1points2_norm
transform2x1y1x2y2r+   X_vf1f2coeffsf1_detf2_detrootsfmatrixvalid_root_mask_lambda_mu_s_s_non_zero_maskf1_expandedf2_expandedmat_ind
trans1_exp
trans2_expr.   r.   r/   
run_7point_   s\   
,(($
*  rm   weightsc              
   C   s  t | g d t |g d t| | | jd dk rt| j|dur9t |ddg |jd | jd ks9t|jt| \}}t|\}}tj|ddd	\}}tj|ddd	\}	}
t|}tj|	| |	| |	|
| |
| |
|||g	dd
}|du r|	dd| }nt
|}|	dd| | }t|\}}}|d ddd}t|\}}}tjg d|j|jd}|t
|| |	dd  }|	dd||  }t|S )a3  Compute the fundamental matrix using the DLT formulation.

    The linear system is solved by using the Weighted Least Squares Solution for the 8 Points algorithm.

    Args:
        points1: A set of points in the first image with a tensor shape :math:`(B, N, 2), N>=8`.
        points2: A set of points in the second image with a tensor shape :math:`(B, N, 2), N>=8`.
        weights: Tensor containing the weights per point correspondence with a shape of :math:`(B, N)`.

    Returns:
        the computed fundamental matrix with shape :math:`(B, 3, 3)`.

    )r7   Nr9   r   r=   Nr7   ro   r   r   r:   r   rD   ).r   r   )rC   rC   rB   r?   )r   r   r    r!   r0   r"   rE   r   catrO   
diag_embedr   r(   r&   r@   rA   r4   )r5   r6   rn   rQ   rR   rS   rT   rU   rV   rW   rX   r+   rY   w_diagrZ   VF_matUS	rank_maskF_projectedF_estr.   r.   r/   
run_8point   s4   


0
rz   8POINTmethod)r{   7POINTc                 C   sF   |  dkrt| |}|S |  dkrt| ||}|S td| d)a  Find the fundamental matrix.

    Args:
        points1: A set of points in the first image with a tensor shape :math:`(B, N, 2), N>=8`.
        points2: A set of points in the second image with a tensor shape :math:`(B, N, 2), N>=8`.
        weights: Tensor containing the weights per point correspondence with a shape of :math:`(B, N)`.
        method: The method to use for computing the fundamental matrix. Supported methods are "7POINT" and "8POINT".

    Returns:
        the computed fundamental matrix with shape :math:`(B, 3*m, 3)`, where `m` number of fundamental matrix.

    Raises:
        ValueError: If an invalid method is provided.

    r}   r{   zInvalid method: z.. Supported methods are '7POINT' and '8POINT'.)upperrm   rz   
ValueError)r5   r6   rn   r|   resultr.   r.   r/   find_fundamental   s   
r   rt   c                 C   s   t | g d | jd dkrt| }n| jd dkr| }nt| jt |g d tj|ddd}tj|| ddd\}}}|| ||  }t|d	kd
t| t	|}tj
|| || || gdd}tj|dddS )a4  Compute the corresponding epipolar line for a given set of points.

    Args:
        points: tensor containing the set of points to project in the shape of :math:`(*, N, 2)` or :math:`(*, N, 3)`.
        F_mat: the fundamental to use for projection the points in the shape of :math:`(*, 3, 3)`.

    Returns:
        a tensor with shape :math:`(*, N, 3)` containing a vector of the epipolar
        lines corresponding to the points to the other image. Each line is described as
        :math:`ax + by + c = 0` and encoding the vectors as :math:`(a, b, c)`.

    )*ro   DIMr   r   r   r   3r   rD   )dim0dim1r:   rB   rC   r   )r   r    r   r!   r"   rO   rE   r	   r%   r   rp   )r   rt   points_habcnuliner.   r.   r/   compute_correspond_epilines  s   

  r   linesc                 C   s   t | g d t |g d |jd dkrt|}n|jd dkr$|}nt|j| tjg d| j| jdddd }tj	j
||dd}|S )	a  Compute the perpendicular to a line, through the point.

    Args:
        lines: tensor containing the set of lines :math:`(*, N, 3)`.
        points:  tensor containing the set of points :math:`(*, N, 2)`.

    Returns:
        a tensor with shape :math:`(*, N, 3)` containing a vector of the epipolar
        perpendicular lines. Each line is described as
        :math:`ax + by + c = 0` and encoding the vectors as :math:`(a, b, c)`.

    )r   ro   r   )r   ro   twor   r   )r   r   r   )rA   r@   r   r   )r   r    r   r!   r"   r&   rA   r@   r(   rF   cross)r   r   r   infinity_pointperpr.   r.   r/   get_perpendicular4  s   

&r   pts1pts2Fmc                 C   s   t |tstdt| t|jdk s|jdd dks&td|j | jd dkr1t| } |jd dkr<t|}t| |}t	||}t
tjj||dd	}|S )
aX  Return closest point on the epipolar line to the correspondence, given the fundamental matrix.

    Args:
        pts1: correspondences from the left images with shape :math:`(*, N, (2|3))`. If they are not homogeneous,
              converted automatically.
        pts2: correspondences from the right images with shape :math:`(*, N, (2|3))`. If they are not homogeneous,
              converted automatically.
        Fm: Fundamental matrices with shape :math:`(*, 3, 3)`. Called Fm to avoid ambiguity with torch.nn.functional.

    Returns:
        point on epipolar line :math:`(*, N, 2)`.

    z#Fm type is not a torch.Tensor. Got r   rD   N)r   r   z#Fm must be a (*, 3, 3) tensor. Got r   r   r   )
isinstancer   	TypeErrortyper   r    r   r   r   r   r   r"   rF   r   )r   r   r   line1in2r   points1_in_2r.   r.   r/   "get_closest_point_on_epipolar_lineN  s   
 

r   E_matK1K2c                 C   s   t | g d t |g d t |g d t| jdd t|jdd   kr5t|jdd ks8t tt|d dd|  t|d  S )a  Get the Fundamental matrix from Essential and camera matrices.

    Uses the method from Hartley/Zisserman 9.6 pag 257 (formula 9.12).

    Args:
        E_mat: The essential matrix with shape of :math:`(*, 3, 3)`.
        K1: The camera matrix from first camera with shape :math:`(*, 3, 3)`.
        K2: The camera matrix from second camera with shape :math:`(*, 3, 3)`.

    Returns:
        The fundamental matrix with shape :math:`(*, 3, 3)`.

    r   NrD   r   r   )r   r   r    r!   r   rO   )r   r   r   r.   r.   r/   fundamental_from_essentialk  s   <$r   P1P2c                 C   sN  t | g d t |g d | jdd |jdd krtdtdtdtfdd}| j}|tjtjfvr@| tj} |tj}| d	d
dddf }|| d	ddddf | d	dd
ddf }| d	ddddf }|d	d
dddf }||d	ddddf |d	dd
ddf }|d	ddddf }	|||||||||}
}}|||||||||}}}|||	|||	|||	}}}tj	|

 dd
|
 dd
|
 dd
|
 dd
|
 dd
|
 dd
|
 dd
|
 dd
|
 dd
g	d
d}|jg | jdd ddR  |S )a6  Get the Fundamental matrix from Projection matrices.

    Args:
        P1: The projection matrix from first camera with shape :math:`(*, 3, 4)`.
        P2: The projection matrix from second camera with shape :math:`(*, 3, 4)`.

    Returns:
         The fundamental matrix with shape :math:`(*, 3, 3)`.

    )r   r   4NrD   xyr   c                 S   s   t | |gddS )NrD   r   )r   )r   r   r.   r.   r/   vstack  s   z,fundamental_from_projections.<locals>.vstack.r   r   r   r   r   r   )r   r    r!   r   rA   r"   float32float64torp   rG   reshaper(   )r   r   r   input_dtypeX1X2X3Y1Y2Y3X1Y1X2Y1X3Y1X1Y2X2Y2X3Y2X1Y3X2Y3X3Y3F_vecr.   r.   r/   fundamental_from_projections  s@   .."""(r   )r   )N)Nr{   )%__doc__typingr   r   r   r"   kornia.corer   r   r   r   r	   r
   kornia.core.checkr   r   kornia.geometry.conversionsr   r   kornia.geometry.linalgr   kornia.geometry.solversr   kornia.utils.helpersr   r   floatr0   r4   rm   rz   r   r   r   r   r   r   r.   r.   r.   r/   <module>   s<     ) ^<
!