o
    iD.                     @   sz  d dl T d dlZd dlmZ d dlZd dlZd dlmZ d dl	m  m
Z d dlZd dlZddlmZ ddlmZmZ dOd	ejd
ejdeeejf dededejfddZdOd	ejd
ejdeeejf dededejfddZdOd	ejd
ejdeeejf dededejfddZdPdedededejdejdejfddZdejdededejfdd Zd!ejfd"d#Z d$ejfd%d&Z!dQd(ejd)ejdefd*d+Z"d,ejfd-d.Z#d/ejfd0d1Z$d2ejfd3d4Z%dRd/ejd6ejd!ejd7e&eef fd8d9Z'dSd<ejd6ejd=e(d> d?edef
d@dAZ)dTdejd6ej*dCe(dD dEedejf
dFdGZ+dUd<ejdKejd,ejdEedLedededejfdMdNZ,dS )V    )*N)
namedtuple   )timeit)solve_optimal_focal_shiftsolve_optimal_shiftFHz>xwdimkeepdimepsreturnc                 C   sH   |d u r| j ||dS || j}| | j ||d|j ||d| S )Nr   r   )meantodtypeaddr	   r
   r   r   r    r   4/data/cameron/moge_repo/moge/utils/geometry_torch.pyweighted_mean   s   &r   c                 C   sV   |d u r|  | j||d S || j}t|  | ||||d | S )Nr   r   r   r   )r   
reciprocalr   r   r   r   r   r   r   r   harmonic_mean   s   &r   c                 C   sN   |d u r|  | j|d S || j}t|  | ||||d S )Nr   r   )r   logr   expr   r   r   r   r   r   r   geometric_mean    s    r   widthheightaspect_ratior   devicec           
      C   s   |du r| | }|d|d  d  }dd|d  d  }t j| | d  |  || d  |  | ||d}t j| |d  | ||d  | |||d}t j||dd\}}t j||gdd	}	|	S )
zUV with left-top corner as (-width / diagonal, -height / diagonal) and right-bottom corner as (width / diagonal, height / diagonal)Nr            ?r   r"   xyindexingr   )torchlinspacemeshgridstack)
r   r    r!   r   r"   Zspan_xZspan_yuvuvr   r   r   normalized_view_plane_uv(   s   ..r1   inputkernel_sizesigmac                 C   s   t t j| d d |d d | j| jdd  d|d   }||  }|d d d f |d d d f  dd||}tj| |d |d |d |d fdd} tj	| || j
d d} | S )Nr#   r   r%   	replicatemode)groups)r*   r   aranger   r"   sumreshapeFpadconv2dshape)r2   r3   r4   kernelr   r   r   gaussian_blur_2d7   s   @,(rA   focalc                 C   s   dt d|   S )Nr#   r$   r*   atan)rB   r   r   r   focal_to_fov@      rE   fovc                 C   s   dt | d  S )Nr$   r#   )r*   tan)rG   r   r   r   fov_to_focalD   rF   rI   -q=v1v2c                 C   s0   t t j| |ddjdd| | | jddS )Nr)   r   )r*   atan2crossnormr:   )rK   rL   r   r   r   r   angle_diff_vec3H   s   0rP   
intrinsicsc                 C   s4   | d }| d }dt d|  dt d|  fS )z
    Returns field of view in radians from normalized intrinsics matrix.
    ### Parameters:
    - intrinsics: torch.Tensor of shape (..., 3, 3)

    ### Returns:
    - fov_x: torch.Tensor of shape (...)
    - fov_y: torch.Tensor of shape (...)
    ).r   r   ).r   r   r#   r$   rC   )rQ   Zfocal_xZfocal_yr   r   r   intrinsics_to_fovK   s   
$rR   pointsc                 C   s.  | j dd \}}|d |d  d }t||| j| jd}|| ddd f  dd}tj| dd df || dd df  gdddd	}|d	d| }t	|d
t
d|  |d	d|d   d}|d\}	}
| d |
d  }t|| |	 d }t|| |	 d }||||
fS )Nr)   r#   r$   r%   .r   gư>).N).r#   ).NN)r?   r1   r   r"   flattenr*   r-   	expand_as	transposeinverseeyer   squeezeunbindrD   )rS   r    r   diagonalr0   bAMsolutionrB   shiftdepthfov_xZfov_yr   r   r   point_map_to_depth_legacyZ   s   :8rf   r0   c                 C   sB   t | jd | jd | j| jd}| |  |   d }|S )NrV   rT   )r   r    r"   r   rJ   )r1   r?   r"   r   r:   squarer   )r0   Z	normed_uvrB   r   r   r   view_plane_uv_to_focalm   s    rh   @   rj   maskdownsample_sizec                 C   s  | j }| j d | j d }}|d |d  d }| jdg|dd R  } |du r+dn|jdg|dd R  }|durA|dnd}t||| j| jd}tj| dd	d
d|ddddd	d
}	tj|ddd	d
d|dd	dd
dd}
|du rdntj|
tjd
|dd	d
dk}|
  }|	   }|dur|  nd}|du rdn|  }g g }}t| j d D ]S}|du r|| n|| ||  }|du r|n|||  }|j d dk r|d
 |d q|du r
t||\}}|t| nt|||| }|t| qtj|| j| jd|dd }|du rEtj|| j| jd|dd }||fS ||dd }||fS )a  
    Recover the depth map and FoV from a point map with unknown z shift and focal.

    Note that it assumes:
    - the optical center is at the center of the map
    - the map is undistorted
    - the map is isometric in the x and y directions

    ### Parameters:
    - `points: torch.Tensor` of shape (..., H, W, 3)
    - `downsample_size: Tuple[int, int]` in (height, width), the size of the downsampled map. Downsampling produces approximate solution and is efficient for large maps.

    ### Returns:
    - `focal`: torch.Tensor of shape (...) the estimated focal length, relative to the half diagonal of the map
    - `shift`: torch.Tensor of shape (...) Z-axis shift to translate the point map to camera space
    rT   rV   r#   r$   r)   Nr%   r      r   nearestr6   r"   r   )r?   r;   r1   r   r"   r<   interpolatepermute	unsqueezer\   r   r*   float32cpunumpydetachrangeappendr   floatr   tensor)rS   rk   rB   rl   r?   r    r   r^   r0   Z	points_lrZuv_lrZmask_lrZuv_lr_npZpoints_lr_npZfocal_npZ
mask_lr_npZoptim_shiftZoptim_focaliZpoints_lr_i_npZ
uv_lr_i_npZoptim_shift_iZoptim_focal_ir   r   r   recover_focal_shifts   sB   &(24
 


"
"r|   皙?rm   rd   pooler)minmaxrtolc           
      C   s   | j ^ }}}| dd||} |dd||}|dkr6tjt|| tj |d|d d}|| d|  k}	n'|dkrVtjt|| tj |d|d d }|| d|  k }	ntd| |	jg |||R  }	|	S )Nr)   r   r   r#   )stridepaddingr   zUnsupported pooler: )r?   r;   r<   
max_pool2dr*   whereinf
ValueError)
rd   rk   r~   r   r3   batch_shaper    r   Zpooled_depthoutput_maskr   r   r   theshold_depth_change   s   $&r   r   filter)r   r   r   median
iterationsc              
   C   sL  t jg dg dg dg| jt jd}t|D ]}tjjtj	| dddddd	d
d}|tjjtj	|dddddd	d
d@ }|dkrTt 
|| t 
||t jjd
dj} nG|dkrlt 
|| t 
||t j jd
dj} n/|dkrt 
|| t 
||t jjd
d} n|dkrt 
|| t 
||t jdjddj} |jd
d}q| |fS )N)FTF)TTTro   )r   r   r   r   constantr   )r7   valuerm   r   rV   r)   window_sizer   r   Fr   r   r   r   r   rV   r)   )r*   rz   r"   boolrw   utils3dptsliding_windowr<   r=   r   r   r   valuesr   nannanmeanrW   	nanmedianany)r2   rk   r   r   r@   _Zinput_windowZmask_windowr   r   r   dilate_with_mask   s   &"&&($*r   
   MbP?   normaldampc                 C   s  | j | j}}| jdd  \}	}
|d }tjtjtj| |
 ||
 |||dtj| |	 ||	 |||dddddj||d}| |	 }t
jj||d	d
d|d|| || d d f  }t||jdd| d   }|jd
d|}t
jj|	|
f||d}t|}|dd d df |dd d d dd df  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 }|t
jj||d	dd|d|| || d d d d f  |ddd	d  jdd jd
d}|dd}| }t|D ]D}d|d|| || f  d||d|| || f  | |t
jj||d	d
d jd
d  ||   |d|| || f< q| }|S )NrV   r#   ro   r&   r'   r)   r   r%   r   r   r   .r   )rT   rV   r   rT   gg?g?)r"   r   r?   r*   r-   r,   r+   r   
clamp_min_r   r   r   r   r   rO   rg   r:   Zuv_maprZ   r\   rq   clampclonerw   Zsliding_window_2d)rd   r   rQ   r   r   r   r3   r"   r   r    r   radiusZduvZ	log_depthZlog_depth_diffweightZ
tot_weightr0   ZK_invgradZ	laplacianZlog_depth_refiner   Zdepth_refiner   r   r   refine_depth_with_normal   s(   X2&
2n^r   )NNFr   )NNN)rJ   )NNri   )r}   rm   )r   r   )r   r   rJ   r   )-typingmathcollectionsr   ru   npr*   torch.nnnntorch.nn.functional
functionalr<   torch.typesr   toolsr   Zgeometry_numpyr   r   TensorUnionintSizer   ry   r   r   r   r   r"   r1   rA   rE   rI   rP   rR   rf   rh   Tupler|   Literalr   
BoolTensorr   r   r   r   r   r   <module>   s4    444*	*(:*8