o
    €o™ir#  ã                   @  sÊ   d dl mZ d dlZd dlmZ d dlmZ d dlmZm	Z	 d dl
mZ d dlmZ d dl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 G dd„ deƒZG dd„ deƒZG dd„ dƒZdS )é    )ÚannotationsN)Únn)Ú
functional)ÚModuleÚTensor)ÚPinholeCamera)ÚRay)ÚPositionalEncoder)Úsample_lengthsÚsample_ray_points)ÚIrregularRendererÚRegularRenderer)Útorch_inference_mode)Úcreate_meshgridc                      s.   e Zd ZdZdd‡ fdd„Zddd„Z‡  ZS )ÚMLPaX  Class to represent a multi-layer perceptron.

    The MLP represents a deep NN of fully connected layers.
    The network is build of user defined sub-units, each with a user defined number of layers.

    Skip connections span between the sub-units.
    The model follows: Ben Mildenhall et el. (2020) at https://arxiv.org/abs/2003.08934.
    é   é   é€   Únum_dimsÚintÚ	num_unitsÚnum_unit_layersÚ
num_hiddenÚreturnÚNonec              	     s†   t ƒ  ¡  || _g }t|ƒD ],}|dkr|n|| }t|ƒD ]}|dkr&|n|}	t |	|¡}
| t |
t ¡ ¡¡ qqt 	|¡| _
dS )a  Construct MLP.

        Args:
            num_dims: Number of input dimensions (channels).
            num_units: Number of sub-units.
            num_unit_layers: Number of fully connected layers in each sub-unit.
            num_hidden: Layer hidden dimensions.

        r   N)ÚsuperÚ__init__Ú_num_unit_layersÚranger   ÚLinearÚappendÚ
SequentialÚReLUÚ
ModuleListÚ_mlp)Úselfr   r   r   r   ÚlayersÚiÚnum_unit_inp_dimsÚjÚnum_layer_inp_dimsÚlayer©Ú	__class__© úJ/home/ubuntu/.local/lib/python3.10/site-packages/kornia/nerf/nerf_model.pyr   ,   s   

ýzMLP.__init__Úxr   c                 C  sP   |}|}t | jƒD ]\}}|dkr!|| j dkr!tj||fdd}||ƒ}q	|S )Nr   éÿÿÿÿ©Údim)Ú	enumerater$   r   ÚtorchÚcat)r%   r0   ÚoutÚx_skipr'   r+   r.   r.   r/   ÚforwardA   s   
zMLP.forward)r   r   r   )
r   r   r   r   r   r   r   r   r   r   )r0   r   r   r   ©Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r9   Ú__classcell__r.   r.   r,   r/   r   "   s    	r   c                      s<   e Zd ZdZ							dd‡ fdd„Zddd„Z‡  ZS )Ú	NerfModela-  Class to represent NeRF model.

    Args:
        num_ray_points: Number of points to sample along rays.
        irregular_ray_sampling: Whether to sample ray points irregularly.
        num_pos_freqs: Number of frequencies for positional encoding.
        num_dir_freqs: Number of frequencies for directional encoding.
        num_units: Number of sub-units.
        num_unit_layers: Number of fully connected layers in each sub-unit.
        num_hidden: Layer hidden dimensions.
        log_space_encoding: Whether to apply log spacing for encoding.

    Té
   r   r   r   Únum_ray_pointsr   Úirregular_ray_samplingÚboolÚnum_pos_freqsÚnum_dir_freqsr   r   r   Úlog_space_encodingr   r   c	           	        s  t ƒ  ¡  || _|| _| jrtƒ ntƒ | _td||d| _td||d| _	t
| jj|||ƒ| _t ||¡| _t t || j	j |d ¡t ¡ ¡| _tj|ddd| _tjj | jjj¡ t dg¡ ¡ | jj_t t |d d¡t ¡ ¡| _t g d¢¡ ¡ | jd	 j_d S )
Né   )Ú	log_spacer   é   T)Úbiasçš™™™™™¹?)ç{®Gáz”?rM   rM   r   )r   r   Ú_num_ray_pointsÚ_irregular_ray_samplingr   r   Ú	_rendererr	   Ú_pos_encoderÚ_dir_encoderr   Únum_encoded_dimsr$   r   r   Ú_fc1r!   r"   Ú_fc2Ú_sigmar5   ÚinitÚxavier_uniform_ÚweightÚdataÚtensorÚfloatrK   ÚSigmoidÚ_rgb)	r%   rB   rC   rE   rF   r   r   r   rG   r,   r.   r/   r   Z   s    
ÿ zNerfModel.__init__Úoriginsr   Ú
directionsc                 C  sÚ   |j d }t|| j|j|j| jd}t|||ƒ}|  |¡}|  t	j
|dd¡}|  |¡}|  |¡}|  |¡}	|	t |	¡d  }	t |	¡}	tj||dddd…f  d| jd¡fdd}|  |¡}|  |¡}
|  |
|	|¡}|S )zêForward method.

        Args:
            origins: Ray origins with shape :math:`(B, 3)`.
            directions: Ray directions with shape :math:`(B, 3)`.

        Returns:
            Rendered image pixels :math:`(B, 3)`.

        r   )ÚdeviceÚdtypeÚ	irregularr1   r2   rL   .N)Úshaper
   rN   ra   rb   rO   r   rQ   rR   ÚFÚ	normalizer$   rT   rV   r5   Ú
randn_likeÚrelur6   ÚexpandrU   r^   rP   )r%   r_   r`   Ú
batch_sizeÚlengthsÚ	points_3dÚpoints_3d_encodedÚdirections_encodedÚyÚdensities_ray_pointsÚrgbs_ray_pointsÚrgbsr.   r.   r/   r9   y   s*   
û




,

zNerfModel.forward)TrA   r   r   r   r   T)rB   r   rC   rD   rE   r   rF   r   r   r   r   r   r   r   rG   rD   r   r   )r_   r   r`   r   r   r   r:   r.   r.   r,   r/   r@   K   s    ÷r@   c                   @  s8   e Zd ZdZddd„Zddd„Zddd„Zddd„ZdS )ÚNerfModelRendererzHRenders a novel synthesis view of a trained NeRF model for given camera.Ú
nerf_modelr@   Ú
image_sizeútuple[int, int]ra   útorch.device | Nonerb   útorch.dtype | Noner   r   c                 C  s,   || _ || _|| _|| _|  ¡ \| _| _dS )zÛConstruct NerfModelRenderer.

        Args:
            nerf_model: NeRF model.
            image_size: image size.
            device: device to run the model on.
            dtype: dtype to run the model on.

        N)Ú_nerf_modelÚ_image_sizeÚ_deviceÚ_dtypeÚ_create_pixels_gridÚ_pixels_gridÚ_ones)r%   rt   ru   ra   rb   r.   r.   r/   r   «   s
   zNerfModelRenderer.__init__útuple[Tensor, Tensor]c                 C  sP   | j \}}t||d| j| jd}| dd¡}tj|jd d|j|j	d}||fS )zãCreate the pixels grid to unproject to plane z=1.

        Args:
            image_size: image size: tuple[int, int]

        Returns:
            - Pixels grid: Tensor (1, H, W, 2)
            - Ones: Tensor (H*W, 1)

        F)Únormalized_coordinatesra   rb   r1   r   r   rJ   )ra   rb   )
rz   r   r{   r|   Úreshaper5   Úonesrd   ra   rb   )r%   ÚheightÚwidthÚpixels_gridrƒ   r.   r.   r/   r}   ¾   s   
ÿz%NerfModelRenderer._create_pixels_gridÚcamerar   r   c                 C  s^   |   |¡}tƒ  |  |j|j¡}W d  ƒ n1 sw   Y  | | jd | jd d¡}|S )zêRender a novel synthesis view of a trained NeRF model for given camera.

        Args:
            camera: camera for image rendering: PinholeCamera.

        Returns:
            Rendered image with shape :math:`(H, W, 3)`.

        Nr   rJ   rH   )Ú_create_raysr   ry   ÚoriginÚ	directionÚviewrz   )r%   r‡   ÚraysÚ	rgb_modelÚ	rgb_imager.   r.   r/   Úrender_viewÓ   s   
ÿzNerfModelRenderer.render_viewr   c                 C  sJ   | j \}}|jddd…df }| || d¡}| | j| j¡}t ||¡S )zwCreate rays for a given camera.

        Args:
            camera: camera for image rendering: PinholeCamera.

        .NrH   r1   rJ   )rz   Ú
extrinsicsÚrepeatÚ	unprojectr~   r   r   Úthrough)r%   r‡   r„   r…   r‰   Údestinationr.   r.   r/   rˆ   è   s
   
zNerfModelRenderer._create_raysN)
rt   r@   ru   rv   ra   rw   rb   rx   r   r   )r   r€   )r‡   r   r   r   )r‡   r   r   r   )r;   r<   r=   r>   r   r}   r   rˆ   r.   r.   r.   r/   rs   ¨   s    


rs   )Ú
__future__r   r5   r   Útorch.nnr   re   Úkornia.corer   r   Úkornia.geometry.camerar   Úkornia.geometry.rayr   Úkornia.nerf.positional_encoderr	   Úkornia.nerf.samplersr
   r   Úkornia.nerf.volume_rendererr   r   Úkornia.utils._compatr   Úkornia.utils.gridr   r   r@   rs   r.   r.   r.   r/   Ú<module>   s   )]