o
    ۷iE                  	   @   s  U 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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 ddlmZ ddlmZ d dlmZ e d ee!Z"e  Z#G dd dejj$j%Z&					d+ddZ'	d,ddZ(					d+ddZ)G dd dZ*da+e*e,d < d!ej-e.B d"ej-e.B d#eee/e0f ed$ f fd%d&Z1d'e.d(e.d#eee/e0f ed$ f fd)d*Z2dS )-    N)Image)tqdm)linalg)adaptive_avg_pool2d)TupleUnion   )InceptionV3)_IMAGE_EXTENSIONS)_VIDEO_EXTENSIONS)get_metrics_verbose   )current_platform)disable_print)init_loggerignorec                   @   s&   e Zd ZdddZdd Zdd ZdS )	ImagePathDatasetNc                 C   s   || _ || _d S N)files_or_imgs
transforms)selfr   r    r   K/home/ubuntu/vllm_env/lib/python3.10/site-packages/cache_dit/metrics/fid.py__init__    s   
zImagePathDataset.__init__c                 C   s
   t | jS r   )lenr   )r   r   r   r   __len__$   s   
zImagePathDataset.__len__c                 C   sr   | j | }t|ttjfrt|d}nt|tj	r)t
|t
j}t|}ntd| jd ur7| |}|S )NRGBz3file_or_img must be a file path or an OpenCV image.)r   
isinstancestrpathlibPathr   openconvertnpndarraycv2cvtColorCOLOR_BGR2RGB	fromarray
ValueErrorr   )r   ifile_or_imgimgr   r   r   __getitem__'   s   


zImagePathDataset.__getitem__r   )__name__
__module____qualname__r   r   r-   r   r   r   r   r      s    
r   2      cpuTc              	   C   s  |   |t| krtd t| }t| t d}tjj	j
||dd|d}tt| |f}	d}
t||dD ]S}||}t  ||d }W d   n1 sTw   Y  |dd	ksg|d
d	krmt|dd}|d
d  }||	|
|
|jd  < |
|jd  }
q8|	S )a  Calculates the activations of the pool_3 layer for all images.

    Params:
    -- files_or_imgs : List of image files paths or OpenCV image
    -- model         : Instance of inception model
    -- batch_size    : Batch size of images for the model to process at once.
                       Make sure that the number of samples is a multiple of
                       the batch size, otherwise some samples are ignored. This
                       behavior is retained to match the original FID score
                       implementation.
    -- dims          : Dimensionality of features returned by Inception
    -- device        : Device to run calculations
    -- num_workers   : Number of parallel dataloader workers

    Returns:
    -- A numpy array of dimension (num images, dims) that contains the
       activations of the given tensor when feeding inception with the
       query tensor.
    zQWarning: batch size is bigger than the data size. Setting batch size to data size)r   F)
batch_sizeshuffle	drop_lastnum_workersr   )disableNr   r      )r   r   )output_size)evalr   loggerinfor   TFToTensortorchutilsdata
DataLoaderr#   emptyr   tono_gradsizer   squeezer3   numpyshape)r   modelr4   dimsdevicer7   disable_tqdmdataset
dataloaderpred_arr	start_idxbatchpredr   r   r   get_activations6   s6   

rU   ư>c                 C   s2  t | } t |}t |}t |}| j|jksJ d|j|jks(J d| | }tj||dd\}}t | s]d| }t	| t 
|jd | }	t||	 ||	 }t |rt jt |jddds~t t |j}
td	|
|j}t |}||t | t | d
|  S )a9  Numpy implementation of the Frechet Distance.
    The Frechet distance between two multivariate Gaussians X_1 ~ N(mu_1, C_1)
    and X_2 ~ N(mu_2, C_2) is
            d^2 = ||mu_1 - mu_2||^2 + Tr(C_1 + C_2 - 2*sqrt(C_1*C_2)).

    Stable version by Dougal J. Sutherland.

    Params:
    -- mu1   : Numpy array containing the activations of a layer of the
               inception net (like returned by the function 'get_predictions')
               for generated samples.
    -- mu2   : The sample mean over activations, precalculated on an
               representative data set.
    -- sigma1: The covariance matrix over activations for generated samples.
    -- sigma2: The covariance matrix over activations, precalculated on an
               representative data set.

    Returns:
    --   : The Frechet Distance.
    z5Training and test mean vectors have different lengthsz7Training and test covariances have different dimensionsF)dispzQfid calculation produces singular product; adding %s to diagonal of cov estimatesr   gMbP?)atolzImaginary component {}r   )r#   
atleast_1d
atleast_2drJ   r   sqrtmdotisfiniteallprinteyeiscomplexobjallclosediagonalimagmaxabsr)   formatrealtrace)mu1sigma1mu2sigma2epsdiffcovmean_msgoffsetm
tr_covmeanr   r   r   calculate_frechet_distance{   s,   





&rv   c           
      C   s8   t | ||||||}tj|dd}tj|dd}	||	fS )a  Calculation of the statistics used by the FID.
    Params:
    -- files_or_imgs : List of image files paths or OpenCV image
    -- model         : Instance of inception model
    -- batch_size    : Batch size of images for the model to process at once.
                       Make sure that the number of samples is a multiple of
                       the batch size, otherwise some samples are ignored. This
                       behavior is retained to match the original FID score
                       implementation.
    -- dims          : Dimensionality of features returned by Inception
    -- device        : Device to run calculations
    -- num_workers   : Number of parallel dataloader workers

    Returns:
    -- mu    : The mean over samples of the activations of the pool_3 layer of
               the inception model.
    -- sigma : The covariance matrix of the activations of the pool_3 layer of
               the inception model.
    r   )axisF)rowvar)rU   r#   meancov)
r   rK   r4   rL   rM   r7   rN   actmusigmar   r   r   calculate_activation_statistics   s   	r~   c                	   @   s   e Zd Ze rejndddddfdedededefd	d
Zde	j
eB de	j
eB fddZdedefddZdedefddZdS )FrechetInceptionDistancer3   r2   r   TrL   r7   r4   rN   c                 C   sR   || _ || _|| _|| _|| _tj| j  | _t| jg| j| _	| j	
 | _	d S r   )rL   rM   r7   r4   rN   r	   BLOCK_INDEX_BY_DIM	block_idxrE   rK   r;   )r   rM   rL   r7   r4   rN   r   r   r   r      s   z!FrechetInceptionDistance.__init__
image_true
image_testc                    s2  t |ts
t |trtj|stj|rCtj|sJ tj|s&J |dd tv s1J |dd tv s<J |g}|g}ntj|sKJ tj|sSJ t	
|tfddtD }t	
| t fddtD }dd |D }dd |D }g }g }ttt|t|D ] }|| }|| }	tj|	tj|kr|| ||	 q| }| }t|dkrtd	 d
S td|  td|  n|g}|g}td| j}
t|
t|}
t|| j|
| j| j| j| j\}}t|| j|
| j| j| j| j\}}t||||}|t|fS )z
        Calculates the FID of two file paths
        FID = FrechetInceptionDistance()
        img_fid = FID.compute_fid("img_true.png", "img_test.png")
        img_dir_fid = FID.compute_fid("img_true_dir", "img_test_dir")
        .c                    &   g | ]}  d |D ]}|qqS z*.{}rglobrg   .0extfile)image_true_dirr   r   
<listcomp>      z8FrechetInceptionDistance.compute_fid.<locals>.<listcomp>c                    r   r   r   r   )image_test_dirr   r   r     r   c                 S      g | ]}|  qS r   as_posixr   r   r   r   r   r         c                 S   r   r   r   r   r   r   r   r     r   r   zONo valid Image pairs, please note that Image pairs must have the same basename.NNzimage_true_files: zimage_test_files:    )r   r   ospathisfileexistssplitr
   isdirr   r    sortedrangeminr   basenameappendcopyr<   errordebugr4   r~   rK   rL   rM   r7   rN   rv   )r   r   r   image_true_filesimage_test_filesimage_true_files_selectedimage_test_files_selectedr*   selected_image_trueselected_image_testr4   m1s1m2s2	fid_valuer   )r   r   r   compute_fid   s   





		z$FrechetInceptionDistance.compute_fid
video_true
video_testc                    s"  t j|rt j|r| j||d\}}}nt j|rt j|rt|tfddtD }t| t fddtD }dd |D }dd |D }g }g }	t	t
t|t|D ] }
||
 }||
 }t j|t j|kr|| |	| q`| }|	 }t|dkrtd d	S td
|  td|  g }g }d}t||D ]\}}| j||d\}}}|| || ||7 }qntd|dkrtd d	S t
d| j}t|| j|| j| j| j| j\}}t|| j|| j| j| j| j\}}t||||}||fS )Nr   r   c                    r   r   r   r   )video_true_dirr   r   r   h  r   z>FrechetInceptionDistance.compute_video_fid.<locals>.<listcomp>c                    r   r   r   r   )video_test_dirr   r   r   p  r   c                 S   r   r   r   r   r   r   r   r   v  r   c                 S   r   r   r   r   r   r   r   r   w  r   r   zONo valid Video pairs, please note that Video pairs must have the same basename.r   zvideo_true_files: zvideo_test_files: z0video_true and video_test must be files or dirs.zNo valid frames to comparer   )r   r   r   _fetch_video_framesr   r   r    r   r   r   r   r   r   r   r   r<   r   r   zipextendr)   r4   r~   rK   rL   rM   r7   rN   rv   )r   r   r   video_true_framesvideo_test_framesvalid_framesvideo_true_filesvideo_test_filesvideo_true_files_selectedvideo_test_files_selectedr*   selected_video_trueselected_video_testvideo_true_video_test_video_true_frames_video_test_frames_valid_frames_r4   r   r   r   r   r   r   )r   r   r   compute_video_fidY  s   









		z*FrechetInceptionDistance.compute_video_fidc                 C   s   t |}t |}| r| std g g dfS tt|t jt|t j}d}g }g }t	d|  	 |
 \}	}
|
 \}}|	rL|sMn||
 || |d7 }q<|  |  |dkrmg g dfS |||fS )NzCould not open video filesr   zTotal frames: Tr   )r%   VideoCaptureisOpenedr<   r   r   intgetCAP_PROP_FRAME_COUNTr   readr   release)r   r   r   cap1cap2frame_countr   r   r   ret1frame1ret2frame2r   r   r   r     s6   







z,FrechetInceptionDistance._fetch_video_framesN)r.   r/   r0   r   is_accelerator_availabledevice_typer   boolr   r#   r$   r   r   r   r   r   r   r   r   r      s<    

b
er   fid_instancer   r   returnr   c                 C   T   t d u rt  tt  da W d    n1 sw   Y  t d us$J t | |S N)rN   r   r   r   r   r   )r   r   r   r   r   r     s   r   r   r   c                 C   r   r   r   r   r   r   r   r     s   r   )r1   r2   r3   r   T)rV   )3r   r%   r   warningsrI   r#   PILr   r   scipyr   r@   torchvision.transformsr   r>   torch.nn.functionalr   typingr   r   	inceptionr	   configr
   r   r   	platformsr   rA   r   cache_dit.loggerr   filterwarningsr.   r<   DISABLE_VERBOSErB   Datasetr   rU   rv   r~   r   r   __annotations__r$   r   floatr   r   r   r   r   r   r   <module>   sn   
 

J
@
*  

