a
    dC                     @   sz   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mZmZ dd Zddd	ZG d
d deZdS )    N)	normalize)init_detection_model)init_parsing_model)
img2tensorimwritec                 C   s   dd }g }| D ]V}||d |}||d |}||d |}||d |}	|| |	|  }
| |
 q|t|}| | |fS )Nc                 S   s    | dk rdS | |kr|S | S d S )Nr    )vallengthr   r   o/var/www/html/stable-diffusion-webui/venv/lib/python3.9/site-packages/facexlib/utils/face_restoration_helper.pyget_location   s
    z&get_largest_face.<locals>.get_locationr            )appendindexmax)	det_faceshwr   Z
face_areasdet_faceleftrighttopZbottomZ	face_arealargest_idxr   r   r
   get_largest_face   s    r   c           	      C   s   |d urt |}nt |d |d g}g }| D ]L}t |d |d  d |d |d  d g}t j|| }|| q2|t|}| | |fS )Nr   r   r   r   )nparraylinalgnormr   r   min)	r   r   r   centerZcenter_distr   Zface_centerdist
center_idxr   r   r
   get_center_face"   s    .r#   c                	   @   sb   e Zd ZdZddd	Zd
d Zdd ZdddZdddZdddZ	dd Z
d ddZdd ZdS )!FaceRestoreHelperz6Helper for the face restoration pipeline (base class).   r   r   retinaface_resnet50pngFNc                 C   s  || _ || _|| _| jd dkr.| jd dks6J dt|| jd  t|| jd  f| _| j rtddgddgddgg| _n*td	d
gddgddgddgddgg| _| j|d  | _| jd dkr| jd d df  || jd d  d 7  < | jd dkr2| jd d df  || jd d  d 7  < || _|| _	| j	du rPd| _ g | _
g | _g | _g | _g | _g | _g | _|	d u rttj rdnd| _n|	| _t|d| j|
d| _|| _td| j|
d| _d S )Nr   r   zcrop ration only supports >=1      i?  i  is  gZwgh@gCVzNm@gqs@g.1n@g%
p@gAOs@gH0[(i@g46w@gW[ls@g<;k2w@g      @r   TFcudacpu)Zhalfdevicemodel_rootpathZparsenet)Z
model_namer-   r.   )template_3pointsupscale_factor
crop_ratioint	face_sizer   r   face_templatesave_extpad_blurall_landmarks_5r   affine_matricesinverse_affine_matricescropped_facesrestored_facespad_input_imgstorchr-   r+   Zis_availabler   face_det	use_parser   
face_parse)selfr0   r3   r1   Z	det_modelr5   r/   r6   r?   r-   r.   r   r   r
   __init__3   s@    $& ,,
zFaceRestoreHelper.__init__c                 C   s
   || _ d S N)r0   )rA   r0   r   r   r
   set_upscale_factori   s    z$FaceRestoreHelper.set_upscale_factorc                 C   s~   t |trt|}t|dkr.|d d }t|jdkrLt|tj	}n(|jd dkrt|ddddddf }|| _
dS )	z*img can be image path or cv2 loaded image.   i     r      Nr   r   )
isinstancestrcv2Zimreadr   r   lenshapeZcvtColorZCOLOR_GRAY2BGR	input_img)rA   imgr   r   r
   
read_imagel   s    

zFaceRestoreHelper.read_image{Gz?c           #         s  |d u rd}| j }nT| j jdd \}}	t||	| }t|| t|	|  }}	tj| j |	|ftjd}t " | j	
|d| }
W d    n1 s0    Y  |
D ] tj d  d   d  d	  g}|d ur||k rq| jrt fd
dtdddD }n t fddtdddD }| j| | j dd  qt| jdkrddS |r| j j\}}	}t| j||	\| _}| j| g| _n6|r| j j\}}	}t| j||	\| _}| j| g| _| jrg | _| jD ]}|dd d f }|dd d f }|| d }|dd d f |dd d f  d }|| }|| }|t|ddg  }|tj|  }d}|ttj| d | tj| d | 9 }t|ddg }||d  }t|| | || | || | || | g}tj| d }ttt|d d}ttt|d d df ttt|d d df ttt|d d df ttt|d d df f}t|d  | dt|d  | dt|d | j jd  | dt|d | j jd  | dg}t|dkrt | j |d |d f|d |d fdfd}|d d df  |d 7  < |d d df  |d 7  < |j\}}	}tj!d |d |	d df \}}}t"dt#t$||d  t$|	d | |d   dt#t$||d  t$|d | |d   } t|| }!|!d dkr|!d7 }!tj%|d|!|!fd}"|&d}||"| t'| d d dd 7 }|tj(|dd| t'| dd 7 }t'|dd }| j| n| jt)| j  qt| jS )!Nr   r   r   interpolationg
ףp=
?            c                    s    g | ]} |  |d   gqS r   r   .0iZbboxr   r
   
<listcomp>       z:FaceRestoreHelper.get_face_landmarks_5.<locals>.<listcomp>   c                    s    g | ]} |  |d   gqS rW   r   rX   r[   r   r
   r\      r]            ?r   rG   g      ?g       @g?g?)r   r   reflectg      ?)Zksizefloat32g      @g        )r   r   ZaxisrF   )*rM   rL   r   r2   rJ   resizeINTER_LANCZOS4r=   no_gradr>   Zdetect_facesr   r   r   r/   r   ranger7   r   r   rK   r   r#   r6   r<   Zflipudhypotr   stackZrintfloorceilpadZogridmaximumZminimumrc   Z	boxFilterastypeZclipZmediancopy)#rA   Zonly_keep_largestZonly_center_facere   Z
blur_ratioZeye_dist_thresholdZscalerM   r   r   ZbboxesZeye_distlandmark_r   r"   Z	landmarksZeye_leftZ	eye_rightZeye_avgZ	mouth_avgZ
eye_to_eyeZeye_to_mouthxZ
rect_scaleycZquadqsizeZborderrm   Zpad_imgmaskZblurZblur_imgr   r[   r
   get_face_landmarks_5{   s    
0(" $*2T."
"$z&FaceRestoreHelper.get_face_landmarks_5constantc           
      C   s  | j r:t| jt| jks:J dt| j dt| j t| jD ]\}}tj|| jtjdd }| j	
| |dkrtj}n|dkrtj}n|dkrtj}| j r| j| }n| j}tj||| j|dd	}| j
| |d
urDtj|d }| d|dd| j }	t||	 qDd
S )z1Align and warp faces with face template.
        zMismatched samples: z and )methodr   ry   Z
reflect101rb   )         )Z
borderModeZborderValueNrr   02d.)r6   rK   r<   r7   	enumeraterJ   ZestimateAffinePartial2Dr4   ZLMEDSr8   r   ZBORDER_CONSTANTZBORDER_REFLECT101ZBORDER_REFLECTrM   
warpAffiner3   r:   ospathsplitextr5   r   )
rA   Zsave_cropped_pathZborder_modeidxrq   affine_matrixrM   Zcropped_facer   	save_pathr   r   r
   align_warp_face   s4    
z!FaceRestoreHelper.align_warp_facec                 C   sn   t | jD ]^\}}t|}|| j9 }| j| |dur
tj	|\}}| d|dd}t
|| q
dS )zGet inverse affine matrix.Nrr   r~   z.pth)r   r8   rJ   ZinvertAffineTransformr0   r9   r   r   r   r   r=   save)rA   Zsave_inverse_affine_pathr   r   inverse_affiner   rr   r   r   r   r
   get_inverse_affine
  s    

z$FaceRestoreHelper.get_inverse_affinec                 C   s   | j | d S rC   )r;   r   )rA   facer   r   r
   add_restored_face  s    z#FaceRestoreHelper.add_restored_facec              
   C   sr  | j j\}}}t|| j t|| j  }}|d u rNtj| j ||ftjd}ntj|||ftjd}t| jt| j	ksJ dt
| j| j	D ]~\}}	| jdkrd| j }
nd}
|	d d df  |
7  < t||	||f}| jr|tj|dtjd}t|dd	 d
d
d}t|ddd
d t|d| j}t  | |d }W d    n1 s`0    Y  |jdd   }t|j}g d}t|D ]\}}||||k< qt|dd}t|dd}d}d|d |d d f< d|| d d d f< d|d d d |f< d|d d | d f< |d	 }t||jd d }tj||	||fdd}|d d d d d f }|}ntj| j tj!d}t||	||f}t"|ttd| j td| j ftj#}|d d d d d f | }t$|}t|d d }|d }t"|t||ftj#}|d }t||d |d fd}t|jdkrl|d d d d d f }|d d d d d f }t|jdkr|jd dkr|d d d d dd f }|| d| |d d d d ddf   }tj%||fdd}q|| d| |  }qt&|dkr.|tj'}n|tj#}|d urnt(j)*|d }| d| j+ }t,|| |S )NrQ   z;length of restored_faces and affine_matrices are different.r   r`   r   r   )r%   r%   rc   g     o@T)Zbgr2rgbrc   )r`   r`   r`   )Zinplace)Zdim)r   rF   rF   rF   rF   rF   rF   rF   rF   rF   rF   rF   rF   rF   r   rF   r   r   r   )e   r   r^   
   r   )flags)Zdtype   rG   rd   rE   r   )-rM   rL   r2   r0   rJ   re   rf   rK   r;   r9   zipr   r?   ZINTER_LINEARr   ro   r   r=   Z	unsqueezetor-   rg   r@   ZargmaxZsqueezer,   numpyr   zerosr   ZGaussianBlurZonesr3   rc   ZerodeZuint8sumZconcatenater   Zuint16r   r   r   r5   r   )rA   r   Zupsample_imgr   r   rr   Zh_upZw_upZrestored_facer   Zextra_offsetZinv_restoredZ
face_inputoutrw   ZMASK_COLORMAPr   colorZthresZinv_soft_maskZpasted_faceZinv_maskZinv_mask_erosionZtotal_face_areaZw_edgeZerosion_radiusZinv_mask_centerZ	blur_sizealphar   r   r   r
   paste_faces_to_input_image  s    


.&
 *

z,FaceRestoreHelper.paste_faces_to_input_imagec                 C   s.   g | _ g | _g | _g | _g | _g | _g | _d S rC   )r7   r;   r8   r:   r9   r   r<   )rA   r   r   r
   	clean_allo  s    zFaceRestoreHelper.clean_all)	r%   r&   r'   r(   FFFNN)FFNrP   N)Nry   )N)NN)__name__
__module____qualname____doc__rB   rD   rO   rx   r   r   r   r   r   r   r   r   r
   r$   0   s0            
6     
o
 

Vr$   )r   r   N)rJ   r   r   r   r=   Z!torchvision.transforms.functionalr   Zfacexlib.detectionr   Zfacexlib.parsingr   Zfacexlib.utils.miscr   r   r   r#   objectr$   r   r   r   r
   <module>   s   
