a
    d[g                     @   s  d dl mZmZ d dlZd dlmZmZ d dlmZm	Z	 d dl
mZ G dd dZG dd	 d	eZd!ejeejdddZd"ejeejdddZejejejdddZejejdddZejejejdddZejejejejdddZd#ejejeejddd ZdS )$    )IterableOptionalN)convert_points_from_homogeneousconvert_points_to_homogeneous)inverse_transformationtransform_points)_torch_inverse_castc                   @   sN  e Zd ZdZejejejejddddZeeej e	dddZ
eejee	d	d
dZeejee	d	ddZeejdddZeejdddZeedddZeejdddZeejdddZeejdddZeejdddZeejdddZejd dddZeejdd d!Zejd dd"d!Zeejdd#d$Zejd dd%d$Zeejdd&d'Zeejdd(d)Zeejdd*d+Zeejdd,d-Zd dd.d/Zejdd0d1Z d dd2d3Z!d dd4d5Z"ejejd6d7d8Z#ejejd9d:d;Z$e%d@e&ej' e&ej( d=d>d?Z)dS )APinholeCameraad  Class that represents a Pinhole Camera model.

    Args:
        intrinsics: tensor with shape :math:`(B, 4, 4)`
          containing the full 4x4 camera calibration matrix.
        extrinsics: tensor with shape :math:`(B, 4, 4)`
          containing the full 4x4 rotation-translation matrix.
        height: tensor with shape :math:`(B)` containing the image height.
        width: tensor with shape :math:`(B)` containing the image width.

    .. note::
        We assume that the class attributes are in batch form in order to take
        advantage of PyTorch parallelism to boost computing performance.
    N)
intrinsics
extrinsicsheightwidthreturnc                 C   s^   |  ||||g | |d | |d | |d | |d || _|| _|| _|| _d S )Nr
   r   r   r   )_check_valid_check_valid_params_check_valid_shaper   r   _intrinsics_extrinsics)selfr
   r   r   r    r   g/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/kornia/geometry/camera/pinhole.py__init__   s    zPinholeCamera.__init__)	data_iterr   c                 C   s   t dd | D stddS )Nc                 s   s   | ]}|j d  V  qdS )r   N)shape).0datar   r   r   	<genexpr>+       z-PinholeCamera._check_valid.<locals>.<genexpr>zArguments shapes must matchT)all
ValueError)r   r   r   r   r   )   s    zPinholeCamera._check_valid)r   	data_namer   c                 C   s6   t | jdvr2| jdd  dkr2td|| jdS )N)      r"   r"   zIArgument {} shape must be in the following shape Bx4x4 or BxNx4x4. Got {}Tlenr   r   formatr   r    r   r   r   r   /   s     z!PinholeCamera._check_valid_paramsc                 C   s$   t | jdks td|| jdS )N   z:Argument {} shape must be in the following shape B. Got {}Tr%   r(   r   r   r   r   8   s
    z PinholeCamera._check_valid_shaper   c                 C   s   |  | jdst| jS )ziThe full 4x4 intrinsics matrix.

        Returns:
            tensor of shape :math:`(B, 4, 4)`.
        r
   )r   r   AssertionErrorr   r   r   r   r
   @   s    zPinholeCamera.intrinsicsc                 C   s   |  | jdst| jS )ziThe full 4x4 extrinsics matrix.

        Returns:
            tensor of shape :math:`(B, 4, 4)`.
        r   )r   r   r+   r,   r   r   r   r   K   s    zPinholeCamera.extrinsicsc                 C   s   | j jd S )zhReturn the batch size of the storage.

        Returns:
            scalar with the batch size.
        r   )r
   r   r,   r   r   r   
batch_sizeV   s    zPinholeCamera.batch_sizec                 C   s
   | j d S )zoReturn the focal length in the x-direction.

        Returns:
            tensor of shape :math:`(B)`.
        .r   r   r
   r,   r   r   r   fx_   s    zPinholeCamera.fxc                 C   s
   | j d S )zoReturn the focal length in the y-direction.

        Returns:
            tensor of shape :math:`(B)`.
        .r)   r)   r/   r,   r   r   r   fyh   s    zPinholeCamera.fyc                 C   s
   | j d S )zsReturn the x-coordinate of the principal point.

        Returns:
            tensor of shape :math:`(B)`.
        .r      r/   r,   r   r   r   cxq   s    zPinholeCamera.cxc                 C   s
   | j d S )zsReturn the y-coordinate of the principal point.

        Returns:
            tensor of shape :math:`(B)`.
        .r)   r4   r/   r,   r   r   r   cyz   s    zPinholeCamera.cyc                 C   s
   | j d S )zvReturn the x-coordinate of the translation vector.

        Returns:
            tensor of shape :math:`(B)`.
        .r   r   r,   r   r   r   tx   s    zPinholeCamera.txc                 C   s   || j d< | S )zDSet the x-coordinate of the translation vector with the given value.r8   r:   r   valuer   r   r   r;      s    
c                 C   s
   | j d S )zvReturn the y-coordinate of the translation vector.

        Returns:
            tensor of shape :math:`(B)`.
        .r)   r9   r:   r,   r   r   r   ty   s    zPinholeCamera.tyc                 C   s   || j d< | S )DSet the y-coordinate of the translation vector with the given value.r>   r:   r<   r   r   r   r?      s    
c                 C   s
   | j d S )zwReturns the z-coordinate of the translation vector.

        Returns:
            tensor of shape :math:`(B)`.
        .r4   r9   r:   r,   r   r   r   tz   s    zPinholeCamera.tzc                 C   s   || j d< | S )r@   rA   r:   r<   r   r   r   rB      s    
c                 C   s   | j dddddf S )zuReturn the 3x4 rotation-translation matrix.

        Returns:
            tensor of shape :math:`(B, 3, 4)`.
        .Nr!   r"   r:   r,   r   r   r   	rt_matrix   s    zPinholeCamera.rt_matrixc                 C   s   | j dddddf S )zReturn the 3x3 camera matrix containing the intrinsics.

        Returns:
            tensor of shape :math:`(B, 3, 3)`.
        .Nr!   r/   r,   r   r   r   camera_matrix   s    zPinholeCamera.camera_matrixc                 C   s   | j dddddf S )z}Return the 3x3 rotation matrix from the extrinsics.

        Returns:
            tensor of shape :math:`(B, 3, 3)`.
        .Nr!   r:   r,   r   r   r   rotation_matrix   s    zPinholeCamera.rotation_matrixc                 C   s   | j dddddf S )z|Return the translation vector from the extrinsics.

        Returns:
            tensor of shape :math:`(B, 3, 1)`.
        .Nr!   r9   r:   r,   r   r   r   translation_vector   s    z PinholeCamera.translation_vectorc                 C   s6   | j  }| j }| j }| j }t||||S )z2Return a deep copy of the current object instance.)r   cloner   r
   r   r	   )r   r   r   r
   r   r   r   r   rG      s
    



zPinholeCamera.clonec                 C   s
   | j  S )zzReturn the inverse of the 4x4 instrisics matrix.

        Returns:
            tensor of shape :math:`(B, 4, 4)`.
        )r
   Zinverser,   r   r   r   intrinsics_inverse   s    z PinholeCamera.intrinsics_inversec                 C   sv   | j  }|d  |9  < |d  |9  < |d  |9  < |d  |9  < || j  }|| j  }t|| j||S )a.  Scale the pinhole model.

        Args:
            scale_factor: a tensor with the scale factor. It has
              to be broadcastable with class members. The expected shape is
              :math:`(B)` or :math:`(1)`.

        Returns:
            the camera model with scaled parameters.
        r.   r1   r3   r6   )r
   rG   r   r   r	   r   )r   scale_factorr
   r   r   r   r   r   scale   s    
zPinholeCamera.scalec                 C   sh   | j d  |9  < | j d  |9  < | j d  |9  < | j d  |9  < |  j|9  _|  j|9  _| S )a7  Scale the pinhole model in-place.

        Args:
            scale_factor: a tensor with the scale factor. It has
              to be broadcastable with class members. The expected shape is
              :math:`(B)` or :math:`(1)`.

        Returns:
            the camera model with scaled parameters.
        r.   r1   r3   r6   )r
   r   r   )r   rI   r   r   r   scale_   s    zPinholeCamera.scale_)point_3dr   c                 C   s   | j | j }tt||S )a  Project a 3d point in world coordinates onto the 2d camera plane.

        Args:
            point3d: tensor containing the 3d points to be projected
                to the camera plane. The shape of the tensor can be :math:`(*, 3)`.

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

        Example:
            >>> _ = torch.manual_seed(0)
            >>> X = torch.rand(1, 3)
            >>> K = torch.eye(4)[None]
            >>> E = torch.eye(4)[None]
            >>> h = torch.ones(1)
            >>> w = torch.ones(1)
            >>> pinhole = kornia.geometry.camera.PinholeCamera(K, E, h, w)
            >>> pinhole.project(X)
            tensor([[5.6088, 8.6827]])
        )r
   r   r   r   )r   rL   Pr   r   r   project  s    zPinholeCamera.project)point_2ddepthc                 C   s&   | j | j }t|}t|t|| S )a  Unproject a 2d point in 3d.

        Transform coordinates in the pixel frame to the world frame.

        Args:
            point2d: tensor containing the 2d to be projected to
                world coordinates. The shape of the tensor can be :math:`(*, 2)`.
            depth: tensor containing the depth value of each 2d
                points. The tensor shape must be equal to point2d :math:`(*, 1)`.
            normalize: whether to normalize the pointcloud. This
                must be set to `True` when the depth is represented as the Euclidean
                ray length from the camera position.

        Returns:
            tensor of (x, y, z) world coordinates with shape :math:`(*, 3)`.

        Example:
            >>> _ = torch.manual_seed(0)
            >>> x = torch.rand(1, 2)
            >>> depth = torch.ones(1, 1)
            >>> K = torch.eye(4)[None]
            >>> E = torch.eye(4)[None]
            >>> h = torch.ones(1)
            >>> w = torch.ones(1)
            >>> pinhole = kornia.geometry.camera.PinholeCamera(K, E, h, w)
            >>> pinhole.unproject(x, depth)
            tensor([[0.4963, 0.7682, 1.0000]])
        )r
   r   r   r   r   )r   rO   rP   rM   ZP_invr   r   r   	unproject'  s    zPinholeCamera.unprojectr)   devicedtypec                 C   s  t j|
dd||d}|d  |7  < |d  |7  < |d  |7  < |d  |7  < |d  d7  < |d	  d7  < t jd||d|
d
d
}|d  |7  < |d  |7  < |d  |	7  < t j|
||d}|d  |7  < t j|
||d}|d  |7  < | ||||S )Nr"   rR   r.   r1   r3   r6   ).r4   r4         ?).r!   r!   r)   r8   r>   rA   .r   )torchzeroseyerepeat)r   r0   r2   r5   r7   r   r   r;   r?   rB   r-   rS   rT   r
   r   Z
height_tmpZ	width_tmpr   r   r   from_parametersI  s     zPinholeCamera.from_parameters)r)   NN)*__name__
__module____qualname____doc__rW   Tensorr   staticmethodr   boolr   strr   r   propertyr
   r   intr-   r0   r2   r5   r7   r;   setterr?   rB   rC   rD   rE   rF   rG   rH   rJ   rK   rN   rQ   classmethodr   rS   rT   r[   r   r   r   r   r	   
   st   

"   r	   c                   @   sZ   e Zd ZdZee ddddZee d dddZee	d	d
dZ
e	edddZdS )PinholeCamerasListal  Class that represents a list of pinhole cameras.

    The class inherits from :class:`~kornia.PinholeCamera` meaning that
    it will keep the same class properties but with an extra dimension.

    .. note::
        The underlying data tensor will be stacked in the first dimension.
        That's it, given a list of two camera instances, the intrinsics tensor
        will have a shape :math:`(B, N, 4, 4)` where :math:`B` is the batch
        size and :math:`N` is the numbers of cameras (in this case two).

    Args:
        pinholes_list: a python tuple or list containing a set of `PinholeCamera` instances.
    N)pinholes_listr   c                 C   s   |  | d S )N)_initialize_parameters)r   ri   r   r   r   r   ~  s    zPinholeCamerasList.__init__pinholesr   c                 C   s   t |ttfs tdt| g g  }}g g  }}|D ]P}t |tsXtdt|||j ||j	 ||j
 ||j q8tj|dd| _tj|dd| _	tj|dd| _tj|dd| _| S )z5Initialise the class attributes given a cameras list.z(pinhole must of type list or tuple. Got z8Argument pinhole must be from type PinholeCamera. Got {}r)   Zdim)
isinstancelisttuple	TypeErrortyper	   r'   appendr   r   r
   r   rW   stackr   r   )r   rl   r   r   r
   r   pinholer   r   r   rj     s     


z)PinholeCamerasList._initialize_parametersr*   c                 C   s"   d}| j durt| j jd }|S )z0Return the number of pinholes cameras per batch.r9   Nr)   )r
   re   r   )r   num_camerasr   r   r   rv     s    
zPinholeCamerasList.num_cameras)idxr   c                 C   sN   | j d|f }| jd|f }| jdd|f }| jdd|f }t||||S )z<Return a PinholeCamera object with parameters such as Bx4x4..N)r   r   r
   r   r	   )r   rw   r   r   r
   r   r   r   r   get_pinhole  s
    zPinholeCamerasList.get_pinhole)r\   r]   r^   r_   r   r	   r   rj   rd   re   rv   rx   r   r   r   r   rh   n  s   rh   ư>)rl   epsr   c                 C   s   t | jdkr| jd dks&t| jtj| dddf ddd\}}}}tjd| j| jd| }|ddd	| jd	 dd}||dd	d	df< ||dd	dd
f< ||ddddf< ||dddd
f< |S )a,  Function that returns the pinhole matrix from a pinhole model.

    .. note::
        This method is going to be deprecated in version 0.2 in favour of
        :attr:`kornia.PinholeCamera.camera_matrix`.

    Args:
        pinholes: tensor of pinhole models.

    Returns:
        tensor of pinhole matrices.

    Shape:
        - Input: :math:`(N, 12)`
        - Output: :math:`(N, 4, 4)`

    Example:
        >>> rng = torch.manual_seed(0)
        >>> pinhole = torch.rand(1, 12)    # Nx12
        >>> pinhole_matrix(pinhole)  # Nx4x4
        tensor([[[4.9626e-01, 1.0000e-06, 8.8477e-02, 1.0000e-06],
                 [1.0000e-06, 7.6822e-01, 1.3203e-01, 1.0000e-06],
                 [1.0000e-06, 1.0000e-06, 1.0000e+00, 1.0000e-06],
                 [1.0000e-06, 1.0000e-06, 1.0000e-06, 1.0000e+00]]])
    r4   r)      .Nr"   rm   rR   r   r!   
r&   r   r+   rW   chunkrY   rS   rT   viewrZ   )rl   rz   r0   r2   r5   r7   kr   r   r   pinhole_matrix  s    
$r   )ru   rz   r   c                 C   s   t | jdkr| jd dks&t| jtj| dddf ddd\}}}}tjd| j| jd}|ddd	| jd	 dd}d
||  |dd	d	df< d
||  |ddddf< d| ||  |dd	ddf< d| ||  |ddddf< |S )a  Return the inverted pinhole matrix from a pinhole model.

    .. note::
        This method is going to be deprecated in version 0.2 in favour of
        :attr:`kornia.PinholeCamera.intrinsics_inverse()`.

    Args:
        pinholes: tensor with pinhole models.

    Returns:
        tensor of inverted pinhole matrices.

    Shape:
        - Input: :math:`(N, 12)`
        - Output: :math:`(N, 4, 4)`

    Example:
        >>> rng = torch.manual_seed(0)
        >>> pinhole = torch.rand(1, 12)  # Nx12
        >>> inverse_pinhole_matrix(pinhole)  # Nx4x4
        tensor([[[ 2.0151,  0.0000, -0.1783,  0.0000],
                 [ 0.0000,  1.3017, -0.1719,  0.0000],
                 [ 0.0000,  0.0000,  1.0000,  0.0000],
                 [ 0.0000,  0.0000,  0.0000,  1.0000]]])
    r4   r)   r{   .Nr"   rm   rR   r   rU   g      r!   r|   )ru   rz   r0   r2   r5   r7   r   r   r   r   inverse_pinhole_matrix  s    
$r   )rl   rJ   r   c                 C   sp   t | jdkr| jd dks&t| jt |jdkr>t|j|  }| dddf |d |dddf< |S )a  Scale the pinhole matrix for each pinhole model.

    .. note::
        This method is going to be deprecated in version 0.2 in favour of
        :attr:`kornia.PinholeCamera.scale()`.

    Args:
        pinholes: tensor with the pinhole model.
        scale: tensor of scales.

    Returns:
        tensor of scaled pinholes.

    Shape:
        - Input: :math:`(N, 12)` and :math:`(N, 1)`
        - Output: :math:`(N, 12)`

    Example:
        >>> rng = torch.manual_seed(0)
        >>> pinhole_i = torch.rand(1, 12)  # Nx12
        >>> scales = 2.0 * torch.ones(1)   # N
        >>> scale_pinhole(pinhole_i, scales)  # Nx12
        tensor([[0.9925, 1.5364, 0.1770, 0.2641, 0.6148, 1.2682, 0.4901, 0.8964, 0.4556,
                 0.6323, 0.3489, 0.4017]])
    r4   r)   r{   .N   r9   )r&   r   r+   rG   Z	unsqueeze)rl   rJ   Zpinholes_scaledr   r   r   scale_pinhole  s    

&r   rk   c                 C   s.   t | jdkr| jd dks&t| jtdS )a  Compute extrinsic transformation matrices for pinholes.

    Args:
        pinholes: tensor of form [fx fy cx cy h w rx ry rz tx ty tz]
                           of size (N, 12).

    Returns:
        tensor of extrinsic transformation matrices of size (N, 4, 4).
    r4   r)   r{   N)r&   r   r+   NotImplementedError)rl   r   r   r   get_optical_pose_base$  s    

r   )	pinhole_ipinhole_refr   c                 C   sx   t | jdkr| jd dks&t| j| j|jkr<t|jt| }t|}t|t|}tt| t|t|S )a  Homography from reference to ith pinhole.

    .. note::
        The pinhole model is represented in a single vector as follows:

        .. math::
            pinhole = (f_x, f_y, c_x, c_y, height, width,
            r_x, r_y, r_z, t_x, t_y, t_z)

        where:
            :math:`(r_x, r_y, r_z)` is the rotation vector in angle-axis
            convention.

            :math:`(t_x, t_y, t_z)` is the translation vector.

    .. math::

        H_{ref}^{i} = K_{i} * T_{ref}^{i} * K_{ref}^{-1}

    Args:
        pinhole_i: tensor with pinhole model for ith frame.
        pinhole_ref: tensor with pinhole model for reference frame.

    Returns:
        tensors that convert depth points (u, v, d) from pinhole_ref to pinhole_i.

    Shape:
        - Input: :math:`(N, 12)` and :math:`(N, 12)`
        - Output: :math:`(N, 4, 4)`

    Example:
        pinhole_i = torch.rand(1, 12)    # Nx12
        pinhole_ref = torch.rand(1, 12)  # Nx12
        homography_i_H_ref(pinhole_i, pinhole_ref)  # Nx4x4
    r4   r)   r{   )	r&   r   r+   r   rW   matmulr   r   r   )r   r   Zi_pose_baseZref_pose_baseZ
i_pose_refr   r   r   homography_i_H_ref9  s    %

r   )rP   intrinsics_invpixel_coordsr   c                 C   s   t | jdks,| jd dkr,td| jt |jdksJtd|jt |jdksv|jd dkrvtd|jt|dddf |}|| dd	dd S )
a  Transform coordinates in the pixel frame to the camera frame.

    Args:
        depth: the source depth maps. Shape must be Bx1xHxW.
        intrinsics_inv: the inverse intrinsics camera matrix. Shape must be Bx4x4.
        pixel_coords: the grid with (u, v, 1) pixel coordinates. Shape must be BxHxWx3.

    Returns:
        tensor of shape BxHxWx3 with (x, y, z) cam coordinates.
    r"   r)   z5Input depth has to be in the shape of Bx1xHxW. Got {}r!   z<Input intrinsics_inv has to be in the shape of Bx4x4. Got {}z<Input pixel_coords has to be in the shape of BxHxWx3. Got {}Nr   r4   )r&   r   r   r'   r   Zpermute)rP   r   r   Z
cam_coordsr   r   r   	pixel2caml  s    r   -q=)cam_coords_srcdst_proj_srcrz   r   c           
      C   s   t | jdks,| jd dkr,td| jt |jdks\|jdd dkr\td|jt|dddf | }|d }|d	 }|d
 }|||  }|||  }tj||gdd}	|	S )a  Transform coordinates in the camera frame to the pixel frame.

    Args:
        cam_coords: (x, y, z) coordinates defined in the first camera coordinates system. Shape must be BxHxWx3.
        dst_proj_src: the projection matrix between the
          reference and the non reference camera frame. Shape must be Bx4x4.
        eps: small value to avoid division by zero error.

    Returns:
        tensor of shape BxHxWx2 with (u, v) pixel coordinates.
    r"   r!   z>Input cam_coords_src has to be in the shape of BxHxWx3. Got {}r#   Nr$   z:Input dst_proj_src has to be in the shape of Bx4x4. Got {}rV   ).r)   ).r4   r9   rm   )r&   r   r   r'   r   rW   rt   )
r   r   rz   Zpoint_coordsZx_coordZy_coordZz_coordZu_coordZv_coordZpixel_coords_dstr   r   r   	cam2pixel  s    
 r   )ry   )ry   )r   )typingr   r   rW   Zkornia.geometry.conversionsr   r   Zkornia.geometry.linalgr   r   Zkornia.utils.helpersr   r	   rh   r`   floatr   r   r   r   r   r   r   r   r   r   r   <module>   s      f8,,&3"