U
    ÿî¹`Õ2  ã                   @   s¨   d Z ddlZddlZddlZddlZddlZddlZddlm	Z	 ddl
mZ dd„ Zdd„ Zdd	„ Zddd„Zddd„Zdd„ Zddd„Zdd„ Zddd„Zdd„ ZdS )zp
Script for benchmarking the 3DMatch test dataset.

Author: Zan Gojcic, Shengyu Huang
Last modified: 30.11.2020
é    N)Údefaultdictc                    sŠ   t  |  dd¡|¡‰ t j‡ fdd„tˆ jd ƒD ƒdd d¡}t j|dddd	}t  |¡}t  	t
jg¡}d
| | |j¡ |j¡ }|S )aÊ  
    Torch batch implementation of the rotation error between the estimated and the ground truth rotatiom matrix. 
    Rotation error is defined as r_e = rccos(rac{Trace(\mathbf{R}_{ij}^{T}\mathbf{R}_{ij}^{\mathrm{GT}) - 1}{2})

    Args: 
        R1 (torch tensor): Estimated rotation matrices [b,3,3]
        R2 (torch tensor): Ground truth rotation matrices [b,3,3]

    Returns:
        ae (torch tensor): Rotation error in angular degreees [b,1]

    é   é   c              	      s0   g | ](}t  ˆ |d d …d d …f ¡d d ‘qS )Nr   r   )ÚtorchÚtrace)Ú.0Ú_©ZR_© ú+/workspace/OverlapPredator/lib/benchmark.pyÚ
<listcomp>   s     z"rotation_error.<locals>.<listcomp>r   ©ÚdiméÿÿÿÿN)Úoutg     €f@)r   ÚmatmulÚ	transposeÚstackÚrangeÚshapeÚ	unsqueezeÚclampÚacosÚTensorÚmathÚpiÚtoÚdeviceÚtypeÚdtype)ÚR1ÚR2ÚeZaer   r
   r	   r   Úrotation_error   s    ,
r#   c                 C   s   t j| | ddS )aÇ  
    Torch batch implementation of the rotation error between the estimated and the ground truth rotatiom matrix. 
    Rotation error is defined as r_e = rccos(rac{Trace(\mathbf{R}_{ij}^{T}\mathbf{R}_{ij}^{\mathrm{GT}) - 1}{2})

    Args: 
        t1 (torch tensor): Estimated translation vectors [b,3,1]
        t2 (torch tensor): Ground truth translation vectors [b,3,1]

    Returns:
        te (torch tensor): translation error in meters [b,1]

    )r   r   r   )r   Únorm)Út1Út2r
   r
   r   Útranslation_error'   s    r'   c                 C   st   | dd…df }| dd…dd…f }t  |¡}tj||dd… gdd}| dd¡| | dd¡ |d  }| ¡ S )a  
    Computer the transformation error as an approximation of the RMSE of corresponding points.
    More informaiton at http://redwood-data.org/indoor/registration.html
    
    Args:
    trans (numpy array): transformation matrices [n,4,4]
    info (numpy array): covariance matrices of the gt transformation paramaters [n,4,4]

    Returns:
    p (float): transformation error
    Né   r   r   ©Úaxisé   )r   r   )ÚnqZmat2quatÚnpÚconcatenateÚreshapeÚitem)ÚtransÚinfoÚtÚrÚqZerÚpr
   r
   r   ÚcomputeTransformationErr6   s    
$r7   é   c           	   
   C   s"  t | ƒ}| ¡ }|dd|d … }g }tt|ƒƒD ] }| ||  d¡dd… ¡ q6g }tt|ƒƒD ]8}| || d  ¡ || d  ¡ || d  ¡ g¡ qhg }tt|ƒƒD ],}|d dkr²| ||  d¡d|… ¡ q²tj|tj	d 
d	||¡}t |¡}||fW  5 Q R £ S Q R X dS )
a.  
    Function that reads a trajectory saved in the 3DMatch/Redwood format to a numpy array. 
    Format specification can be found at http://redwood-data.org/indoor/fileformat.html
    
    Args:
    filename (str): path to the '.txt' file containing the trajectory data
    dim (int): dimension of the transformation matrix (4x4 for 3D data)

    Returns:
    final_keys (dict): indices of pairs with more than 30% overlap (only this ones are included in the gt file)
    traj (numpy array): gt pairwise transformation matrices for n pairs[n,dim, dim] 
    r   Nr   ú	r(   r   é   ©r   r   )ÚopenÚ	readlinesr   ÚlenÚappendÚsplitÚstripr-   ÚasarrayÚfloatr/   )	Úfilenamer   ÚfÚlinesÚkeysZ	temp_keysÚiZ
final_keysÚtrajr
   r
   r   Úread_trajectoryK   s     6
rJ   r+   c              	   C   sÒ   t | ƒ}| ¡ }W 5 Q R X t|ƒd }t|ƒd| ks<t‚g }d}t|ƒD ]b}dd„ ||d   ¡  ¡ D ƒ\}}	}tjdd„ ||d d |d d … D ƒdd}
| 	|
¡ qLtj
|tjd d	||¡}||fS )
a~  
    Function that reads the trajectory information saved in the 3DMatch/Redwood format to a numpy array.
    Information file contains the variance-covariance matrix of the transformation paramaters. 
    Format specification can be found at http://redwood-data.org/indoor/fileformat.html
    
    Args:
    filename (str): path to the '.txt' file containing the trajectory information data
    dim (int): dimension of the transformation matrix (4x4 for 3D data)

    Returns:
    n_frame (int): number of fragments in the scene
    cov_matrix (numpy array): covariance matrix of the transformation matrices for n pairs[n,dim, dim] 
    é   r   c                 S   s   g | ]}t |ƒ‘qS r
   )Úint©r   r0   r
   r
   r   r   Š   s     z(read_trajectory_info.<locals>.<listcomp>c                 S   s"   g | ]}t j|d d dd¡‘qS )r9   )Úsepr   r   )r-   Ú
fromstringr/   rM   r
   r
   r   r   Œ   s     r   r)   r;   r   )r<   r=   r>   ÚAssertionErrorr   rA   r@   r-   r.   r?   rB   rC   r/   )rD   r   ÚfidÚcontentsÚn_pairsZ	info_listZn_framerH   Z
frame_idx0Z
frame_idx1Zinfo_matrixZ
cov_matrixr
   r
   r   Úread_trajectory_infos   s    
$$ ÿrT   c                 C   s|   t  t| ƒddf¡}t| ƒD ]Z\}}|d d |d< t  ||kjdd¡d }||dd…dd…f ||dd…dd…f< q|S )a  
    Extract only those transformation matrices from the ground truth trajectory that are also in the estimated trajectory.
    
    Args:
    est_pairs (numpy array): indices of point cloud pairs with enough estimated overlap [m, 3]
    gt_pairs (numpy array): indices of gt overlaping point cloud pairs [n,3]
    gt_traj (numpy array): 3d array of the gt transformation parameters [n,4,4]

    Returns:
    ext_traj (numpy array): gt transformation parameters for the point cloud pairs from est_pairs [m,4,4] 
    r8   r   r   r   r)   N)r-   Úzerosr>   Ú	enumerateÚwhereÚall)Ú	est_pairsÚgt_pairsÚgt_trajZext_trajZest_idxÚpairÚgt_idxr
   r
   r   Ú extract_corresponding_trajectors“   s    *r^   c              
      sž   t |dƒŠ}t| jd ƒD ]t}|| d r| |dd…dd…f  ¡ ‰ | d tt|| ƒ¡d ¡ | d ‡ fdd„t|ƒD ƒ¡¡ | d¡ qW 5 Q R X dS )	aÙ  
    Writes the trajectory into a '.txt' file in 3DMatch/Redwood format. 
    Format specification can be found at http://redwood-data.org/indoor/fileformat.html

    Args:
    traj (numpy array): trajectory for n pairs[n,dim, dim] 
    metadata (numpy array): file containing metadata about fragment numbers [n,3]
    filename (str): path where to save the '.txt' file containing trajectory data
    dim (int): dimension of the transformation matrix (4x4 for 3D data)
    Úwr   r   Nr9   Ú
c                 3   s$   | ]}d   tdjˆ | ƒ¡V  qdS )r9   z{0:.12f}N)ÚjoinÚmapÚformat)r   rH   ©r6   r
   r   Ú	<genexpr>»   s     z#write_trajectory.<locals>.<genexpr>)r<   r   r   ÚtolistÚwritera   rb   Ústr)rI   ÚmetadatarD   r   rE   Úidxr
   rd   r   Úwrite_trajectory©   s    "rk   c                 C   sä   t  | ¡}t  |¡}|d |d  }}|d |d  }}|jd |krbtj |jd ¡d |… }	ntj |jd |¡}	|jd |kr tj |jd ¡d |… }
ntj |jd |¡}
||	 ||	  }}||
 ||
  }}||||fS )NÚcoordsÚfeatsr   )r   Úloadr   r-   ÚrandomÚpermutationÚchoice)Úsrc_pathÚtgt_pathZn_pointsÚsrcÚtgtÚsrc_pcdZsrc_embeddingÚtgt_pcdZtgt_embeddingZsrc_permuteZtgt_permuter
   r
   r   Ú
read_pairs¿   s    

rx   çš™™™™™É?c              	   C   s”  |d }t j| | ft jd}g }t|jd ƒD ]<}	t||	df ƒ}
t||	df ƒ}||
 dkr.|	||
|f< q.t  |dk¡}d}d}t|jd ƒD ]Î}	t||	df ƒ}
t||	df ƒ}||	dd…dd…f }||
|f dkrT|d7 }||
|f }tt j ||dd…dd…f ¡| ||dd…dd…f ƒ}||krH|d7 }| 	d¡ n
| 	d¡ q| 	d¡ q|dkrr|d7 }|d | }|d | }|||fS )aa  
    Evaluates the performance of the registration algorithm according to the evaluation protocol defined
    by the 3DMatch/Redwood datasets. The evaluation protocol can be found at http://redwood-data.org/indoor/registration.html
    
    Args:
    num_fragment (int): path to the '.txt' file containing the trajectory information data
    result (numpy array): estimated transformation matrices [n,4,4]
    result_pairs (numpy array): indices of the point cloud for which the transformation matrix was estimated (m,3)
    gt_pairs (numpy array): indices of the ground truth overlapping point cloud pairs (n,3)
    gt (numpy array): ground truth transformation matrices [n,4,4]
    gt_cov (numpy array): covariance matrix of the ground truth transfromation parameters [n,6,6]
    err2 (float): threshold for the RMSE of the gt correspondences (default: 0.2m)

    Returns:
    precision (float): mean registration precision over the scene (not so important because it can be increased see papers)
    recall (float): mean registration recall over the scene (deciding parameter for the performance of the algorithm)
    r   r;   r   r   Ng    €„.Ag      ð?)
r-   rU   rL   r   r   Úsumr7   ÚlinalgÚinvr?   )Znum_fragmentÚresultZresult_pairsrZ   ÚgtZgt_infoÚerr2Zgt_maskÚflagsrj   rH   ÚjZn_gtÚgoodZn_resÚposer]   r6   Ú	precisionÚrecallr
   r
   r   Úevaluate_registrationÕ   s:    :

r†   c                    s¾  t t ˆ ¡ƒ}‡ fdd„|D ƒ}ttƒ}ttƒ}g g g g f\}}}}	g }
ddddddd	d
g}t| › ddƒ>}| d¡ t|ƒD ]†\}}ttj	 
|d¡ƒ\}}d}|D ],}tt|d ƒt|d ƒ ƒ}||dk7 }qª|
 |¡ ttj	 
|d¡ƒ\}}ttj	 
| || d¡ƒ\}}t||||||ƒ\}}}t|||ƒ}tt |d d …dd…dd…f ¡t |d d …dd…dd…f ¡ƒ ¡  ¡ t |¡dk }tt |d d …dd…dd…f ¡t |d d …dd…dd…f ¡ƒ ¡  ¡ t |¡dk }|d  t |¡¡ |d  t |¡¡ |d  t |¡¡ |d  t |¡¡ |d  t |¡¡ |d  t |¡¡ |d  t |¡¡ |d  t |¡¡ | | d¡ ¡ ¡ | | d¡ ¡ ¡ | |¡ |	 |¡ | d  || ||t |¡t |¡|¡¡ t !| › d|| › d|¡ q‚t |
¡t |¡  "¡ t "|
¡ }| d  t |¡t #|¡¡¡ | d  |¡¡ | d  t |d ¡t #|d ¡¡¡ | d   t |d ¡t #|d ¡¡¡ W 5 Q R X | $¡  d S )!Nc                    s   g | ]}t j ˆ |¡‘qS r
   )ÚosÚpathra   )r   Úele©Ú	gt_folderr
   r   r     s     zbenchmark.<locals>.<listcomp>ZKitchenzHome 1zHome 2zHotel 1zHotel 2zHotel 3ZStudyzMIT Labz/resultr_   u1   Scene	Â¦ prec.	Â¦ rec.	Â¦ re	Â¦ te	Â¦ samples	Â¦
zgt.logr   r   zgt.infozest.logr(   r8   ÚmeanÚmedianÚminÚmaxr   u6   {}	Â¦ {:.3f}	Â¦ {:.3f}	Â¦ {:.3f}	Â¦ {:.3f}	Â¦ {:3d}Â¦
ú/z	/flag.npyz"Mean precision: {:.3f}: +- {:.3f}
zWeighted precision: {:.3f}
z#Mean median RRE: {:.3f}: +- {:.3f}
z#Mean median RTE: {:.3F}: +- {:.3f}
)%Úsortedr‡   Úlistdirr   Úlistr<   rg   rV   rJ   rˆ   ra   ÚabsrL   r?   rT   r†   r^   r#   r   Ú
from_numpyÚcpuÚnumpyr-   Úarrayr'   rŒ   r   rŽ   r   Úextendr/   rf   rc   Úsaverz   ÚstdÚclose)Z
est_folderr‹   ZscenesÚscene_namesZre_per_sceneZte_per_sceneZre_allZte_allr„   r…   Zn_validsZshort_namesrE   rj   ZscenerZ   r[   Zn_validr‰   ÚdiffZn_fragmentsZgt_traj_covrY   Úest_trajZtemp_precisionZtemp_recallZc_flagZext_gt_trajÚreÚteZweighted_precisionr
   rŠ   r   Ú	benchmark  sT    

XX

*"&0r¢   )r8   )r+   )r8   )ry   )Ú__doc__r—   r-   r‡   ÚsysÚglobr   r   Úcollectionsr   Znibabel.quaternionsZquaternionsr,   r#   r'   r7   rJ   rT   r^   rk   rx   r†   r¢   r
   r
   r
   r   Ú<module>   s   (
(
 

: