o
    oiO                     @   s   d dl Z d dlmZmZmZ d dlZd dlmZmZm	Z	 d dl
mZ d dlmZ d dlmZ d dlmZ G dd	 d	ZG d
d deZG dd deZG dd deZ	d!dedededejdedefddZdedededefddZdedefdd ZdS )"    N)DictListTuple)DeviceTensortensor)PinholeCamera)cameras_for_ids)torch_meshgrid)_torch_inverse_castc                   @   sz  e Zd ZU dZeed< eed< eed< eed< eed< eed< ded	ed
edede	j
ddfddZedefddZedefddZedefddZedefddZdefddZdededefddZG dd  d Zded!eeef ddfd"d#Zdedeeef fd$d%ZG d&d' d'Zed(ed)ed*ed+ed,eeef ddfd-d.Zed,eeef deeef fd/d0ZdS )1
RaySampleraF  Class to manage spatial ray sampling.

    Args:
        min_depth: sampled rays minimal depth from cameras: float
        max_depth: sampled rays maximal depth from cameras: float
        ndc: convert ray parameters to normalized device coordinates: bool
        device: device for ray tensors: Union[str, torch.device]

    _origins_directions_directions_cam_origins_cam_camera_ids
_points_2d	min_depth	max_depthndcdevicedtypereturnNc                 C   s"   || _ || _|| _|| _|| _d S N)
_min_depth
_max_depth_ndc_device_dtypeselfr   r   r   r   r    r!   H/home/ubuntu/.local/lib/python3.10/site-packages/kornia/nerf/samplers.py__init__0   s
   
zRaySampler.__init__c                 C      | j S r   )r   r    r!   r!   r"   origins7      zRaySampler.originsc                 C   r$   r   )r   r%   r!   r!   r"   
directions;   r'   zRaySampler.directionsc                 C   r$   r   r   r%   r!   r!   r"   
camera_ids?   r'   zRaySampler.camera_idsc                 C   r$   r   r   r%   r!   r!   r"   	points_2dC   r'   zRaySampler.points_2dc                 C   s   | j d u rdS | j jd S )Nr   )r&   shaper%   r!   r!   r"   __len__G   s   
zRaySampler.__len__camerasr,   c                 C   sr   |j }|j}|j}|j}|d |d  |d  }|d |d  |d  }t|}	tj|||	gdd}
|
ddS )N.r   .N.   dim   )fxfycxcytorch	ones_likestackreshape)r    r/   r,   r8   r9   r:   r;   directions_xdirections_ydirections_zdirections_camr!   r!   r"   _calc_ray_directions_camL   s   
z#RaySampler._calc_ray_directions_camc                   @   sR   e Zd ZdZdedee ddfddZedefdd	Z	edee fd
dZ
dS )zRaySampler.Points2DaA  A class to hold ray 2d pixel coordinates and a camera id for each.

        Args:
            points_2d: tensor with ray pixel coordinates (the coordinates in the image plane that correspond to the
              ray):math:`(B, 2)`
            camera_ids: list of camera ids for each pixel coordinates: List[int]

        r,   r*   r   Nc                 C   s   || _ || _d S r   )r   r   )r    r,   r*   r!   r!   r"   r#   c   s   
zRaySampler.Points2D.__init__c                 C   r$   r   r+   r%   r!   r!   r"   r,   g   r'   zRaySampler.Points2D.points_2dc                 C   r$   r   r)   r%   r!   r!   r"   r*   k   r'   zRaySampler.Points2D.camera_ids)__name__
__module____qualname____doc__r   r   intr#   propertyr,   r*   r!   r!   r!   r"   Points2DY   s    	rK   points_2d_camerac              	   C   s  g }g }g }g }g }g }|  D ]}	|	jjdd \}
}tj|
d| d| j| jd| j }| j|dd|df< t	||	j
}||	jddd|}||dd|ddf dd ||d|dddf |dd|ddf  dd || ||	j ||d | j  |t|	j
|dddddd ||	jdd  qt|| _t|| _t|| _t|| _t|| _| jr| |\| _| _t|| _dS )	a,  Calculate ray parameters: origins, directions.

        Also stored are camera ids for each ray, and its pixel coordinates.

        Args:
            cameras: scene cameras: PinholeCamera
            points_2d_camera: a dictionary that groups Point2D objects by total number of casted rays

        N   r7   r   r   r3   .r4   r   )valuesr   r-   r<   onesr   r   r   r   r	   r*   	unprojectrepeatappendr?   rD   r   permutesqueezerI   catr   r   r   r   r   r   !transform_ray_params_world_to_ndc)r    r/   rL   r&   r(   rC   origins_camr*   r,   objnum_cams_groupnum_points_per_cam_groupdepthscams	points_3dr!   r!   r"   _calc_ray_paramso   sF   $,&zRaySampler._calc_ray_paramsc                 C   s,  t || j}|j}|j}|j}|j}d| |d  }d| |d  }| jd | jd  }	| jd | jd  }
||	 }||
 }dd| j | jd   }tj	|||gdd	}t
|j}|| jd
  jdd	}|d |d  }|d |d  }|| | }|| | }d| }tj	|||gdd	}|}|}||fS )zTransform ray parameters to normalized coordinate device (camera) system (NDC).

        Args:
        cameras: scene cameras: PinholeCamera

        g       @      ?r0   ).rM   r2   r3   rM   r4   r5   r1   )r	   r   r8   r9   widthheightr   r   r<   r>   r   rotation_matrixr   rU   )r    r/   r]   r8   r9   widthsheights	fx_widths
fy_heightsoxozoyozorigins_ndc_xorigins_ndc_yorigins_ndc_zorigins_ndcRt_invdirections_rotated_worlddxdzdydzdirections_ndc_xdirections_ndc_ydirections_ndc_zdirections_ndcorigins_ndc_worlddirections_ndc_worldr!   r!   r"   rW      s0   
z,RaySampler.transform_ray_params_world_to_ndcc                   @   s   e Zd ZdZdddZdS )zRaySampler.Points2D_FlatTensorszJClass to hold x/y pixel coordinates for each ray, and its scene camera id.r   Nc                 C   s   |  |  g | _ d S r   r)   r%   r!   r!   r"   r#      s   
z(RaySampler.Points2D_FlatTensors.__init__)r   N)rE   rF   rG   rH   r#   r!   r!   r!   r"   Points2D_FlatTensors   s    rx   nxy	camera_idpoints2d_as_flat_tensorsc                 C   s   | |vrt  || < | ||  _| ||  _nt||  j| f||  _t||  j| f||  _||  j| dS )zAdd x/y pixel coordinates for all rays casted by a scene camera to dictionary of pixel coordinates
        grouped by total number of rays.
        N)	r   rx   flatten_x_yr<   rV   r   rS   )ry   rz   r{   r|   r}   r!   r!   r"   -_add_points2d_as_flat_tensors_to_num_ray_dict   s   z8RaySampler._add_points2d_as_flat_tensors_to_num_ray_dictc                 C   sZ   i }|   D ]$\}}t|j}t|j|jfdd|dd}t	
||j||< q|S )aN  Build a dictionary of ray pixel points, by total number of rays as key.

        The dictionary groups rays by the total amount of rays, which allows the case of casting different number
        of rays from each scene camera.

        Args:
            points2d_as_flat_tensors: dictionary of pixel coordinates grouped by total number of rays:
              Dict[int, Points2D_FlatTensors]

        Returns:
            dictionary of Points2D objects that holds information on pixel 2d coordinates of each ray and the camera
              id it was casted by: Dict[int, Points2D]

        r3   r   r4   rM   )itemslenr   r<   r>   r   r   rT   r?   r   rK   )r}   num_ray_dict_of_points2dry   points2d_as_flat_tensornum_camsr,   r!   r!   r"   _build_num_ray_dict_of_points2d   s   

z*RaySampler._build_num_ray_dict_of_points2d)rE   rF   rG   rH   r   __annotations__floatboolr   r<   r   r#   rJ   r&   r(   r*   r,   rI   r.   r   rD   rK   r   r_   r   rW   rx   staticmethodr   r   r!   r!   r!   r"   r      sV   
 
$15


r   c                       sv   e Zd ZdZdededededejddf fd	d
Z	de
de
de
deeejf fddZdede
ddfddZ  ZS )RandomRaySamplera>  Class to manage random ray spatial sampling.

    Args:
        min_depth: sampled rays minimal depth from cameras: float
        max_depth: sampled rays maximal depth from cameras: float
        ndc: convert to normalized device coordinates: bool
        device: device for ray tensors: Union[str, torch.device]

    r   r   r   r   r   r   Nc                       t  ||||| d S r   superr#   r   	__class__r!   r"   r#        zRandomRaySampler.__init__re   rd   num_img_raysc                 C   s   |  }i }tt| | | D ].\}\}}}ttj|| j| jd| }	ttj|| j| jd| }
t	
||
|	|| qt	|S )aC  Randomly sample pixel points in 2d.

        Args:
            heights: tensor that holds scene camera image heights (can vary between cameras): math: `(B)`.
            widths: tensor that holds scene camera image widths (can vary between cameras): math: `(B)`.
            num_img_rays: tensor that holds the number of rays to randomly cast from each scene camera: math: `(B)`.

        Returns:
            dictionary of Points2D objects that holds information on pixel 2d coordinates of each ray and the camera
              id it was casted by: Dict[int, Points2D]

        rN   )rI   	enumerateziptolistr<   truncrandr   r   r   r   r   )r    re   rd   r   r}   r|   rb   ra   ry   y_randx_randr!   r!   r"   sample_points_2d  s   *

z!RandomRaySampler.sample_points_2dr/   c                 C   sP   |j }||jd krtd| d|jd  | |j|j|}| || dS )a?  Calculate ray parameters: origins, directions.

        Also stored are camera ids for each ray, and its pixel coordinates.

        Args:
            cameras: scene cameras: PinholeCamera
            num_img_rays: tensor that holds the number of rays to randomly cast from each scene camera: int math: `(B)`.

        r   zNumber of cameras zR does not match size of tensor to define number of rays to march from each camera N)
batch_sizer-   
ValueErrorr   rb   ra   r_   )r    r/   r   r   rL   r!   r!   r"   calc_ray_params0  s   
z RandomRaySampler.calc_ray_params)rE   rF   rG   rH   r   r   r   r<   r   r#   r   r   rI   r   rK   r   r   r   __classcell__r!   r!   r   r"   r     s
    (
$r   c                       s`   e Zd ZdZdededededejddf fd	d
Z	de
de
de
deeejf fddZ  ZS )RandomGridRaySamplera  Class to manage random ray spatial sampling.

    Sampling is done on a regular grid of pixels by randomizing
    column and row values, and casting rays for all pixels along the selected ones.

    Args:
        min_depth: sampled rays minimal depth from cameras: float
        max_depth: sampled rays maximal depth from cameras: float
        ndc: convert to normalized device coordinates: bool
        device: device for ray tensors: Union[str, torch.device]

    r   r   r   r   r   r   Nc                    r   r   r   r   r   r!   r"   r#   R  r   zRandomGridRaySampler.__init__re   rd   r   c                 C   s   |  }i }tt| | | D ]M\}\}}}t t|}	tjt || j| j	ddt
t ||	 }
tjt || j| j	ddt
t ||	 }t|
|gdd\}}t|	|	 |||| qt|S )a  Randomly sample pixel points in 2d over a regular row-column grid.

        Args:
            heights: tensor that holds scene camera image heights (can vary between cameras): math: `(B)`.
            widths: tensor that holds scene camera image widths (can vary between cameras): math: `(B)`.
            num_img_rays: tensor that holds the number of rays to randomly cast from each scene camera. Number of rows
              and columns is the square root of this value: int math: `(B)`.

        Returns:
            dictionary of Points2D objects that holds information on pixel 2d coordinates of each ray and the camera
              id it was casted by: Dict[int, Points2D]

        rN   Nijindexing)rI   r   r   r   mathsqrtr<   randpermr   r   minr
   r   r   r   )r    re   rd   r   r}   r|   rb   ra   ry   n_sqrtr   r   y_gridx_gridr!   r!   r"   r   U  s   ***
z%RandomGridRaySampler.sample_points_2d)rE   rF   rG   rH   r   r   r   r<   r   r#   r   r   rI   r   rK   r   r   r!   r!   r   r"   r   D  s    (,r   c                       sv   e Zd ZdZdededededejddf fd	d
Z		dde
de
dedeeejf fddZdeddfddZ  ZS )UniformRaySamplera[  Class to manage uniform ray spatial sampling for all camera scene pixels.

    Args:
        min_depth: sampled rays minimal depth from cameras: float
        max_depth: sampled rays maximal depth from cameras: float
        ndc: convert to normalized device coordinates: bool
        device: device for ray tensors: Union[str, torch.device]

    r   r   r   r   r   r   Nc                    r   r   r   r   r   r!   r"   r#   {  r   zUniformRaySampler.__init__r3   re   rd   sampling_stepc              
   C   s   |  }|  }i }tt| | D ]1\}\}}|| }ttjd||| j| jdtjd||| j| jdgdd\}	}
t	
||
|	|| qt	|S )a=  Uniformly sample pixel points in 2d for all scene camera pixels.

        Args:
            heights: tensor that holds scene camera image heights (can vary between cameras): math: `(B)`.
            widths: tensor that holds scene camera image widths (can vary between cameras): math: `(B)`.
            sampling_step: defines uniform strides between rows and columns: int.

        Returns:
            dictionary of Points2D objects that holds information on pixel 2d coordinates of each ray and the camera
              id it was casted by: Dict[int, Points2D]

        r   rN   r   r   )rI   r   r   r   r
   r<   aranger   r   r   r   r   )r    re   rd   r   r}   r|   rb   ra   ry   r   r   r!   r!   r"   r   ~  s   "


z"UniformRaySampler.sample_points_2dr/   c                 C   s    |  |j|j}| || d S r   )r   rb   ra   r_   )r    r/   rL   r!   r!   r"   r     s   z!UniformRaySampler.calc_ray_params)r3   )rE   rF   rG   rH   r   r   r   r<   r   r#   r   rI   r   r   rK   r   r   r   r   r!   r!   r   r"   r   p  s    (

 r   Fnum_raysnum_ray_pointsr   r   	irregularr   c                 C   st   |dkrt d|stjdd|||d}|| d}|S tjdd|d ||d}tj| ||d| |dd  }|S )	z'Sample points along the length of rays.r3   z+Number of ray points must be greater than 1g        r`   rN   )r   Nr4   )r   r<   linspacerR   r   )r   r   r   r   r   zero_to_onelengthsr!   r!   r"   sample_lengths  s    r   r&   r(   r   c                 C   s0   | ddddf |d |ddddf   }|S )a  Sample points along ray.

    Args:
        origins: tensor containing ray origins in 3d world coordinates. Tensor shape :math:`(*, 3)`.
        directions: tensor containing ray directions in 3d world coordinates. Tensor shape :math:`(*, 3)`.
        lengths: tensor containing sampled distances along each ray. Tensor shape :math:`(*, num_ray_points)`.

    Returns:
        points_3d: Points along rays :math:`(*, num_ray_points, 3)`

    .Nr1   r!   )r&   r(   r   r^   r!   r!   r"   sample_ray_points  s   ,r   r^   c                 C   s,   t jj| | ddddf d dd}|S )zCalculate t values along rays.

    Args:
        points_3d: Points along rays :math:`(*, num_ray_points, 3)`

    Returns:
        t values along rays :math:`(*, num_ray_points)`

    .r   Nr4   r5   )r<   linalgnorm	unsqueeze)r^   t_valsr!   r!   r"   calc_ray_t_vals  s   (
r   )F)r   typingr   r   r   r<   kornia.corer   r   r   kornia.geometry.camerar   kornia.nerf.camera_utilsr	   kornia.utils._compatr
   kornia.utils.helpersr   r   r   r   r   rI   r   r   r   r   r   r!   r!   r!   r"   <module>   sJ    n9,4

