a
    
d                     @   sr   d dl Z d dlZddlmZ ddgddgdd	gd
dgddggZdZG dd deZdddZ	dd Z
dddZdS )    N   ) get_similarity_transform_for_cv2gXjK>@gQ` I@g 	bP@g-I@g״9H@g$Q@gsO@@g_dW@g_m]O@gPW@`   p   c                       s   e Zd Z fddZ  ZS )FaceWarpExceptionc                    s   d tt| S )NzIn File {}:{})format__file__super__str__)self	__class__ ]/var/www/html/stable-diffusion-webui/repositories/CodeFormer/facelib/detection/align_trans.pyr      s    zFaceWarpException.__str__)__name__
__module____qualname__r   __classcell__r   r   r   r   r      s   r           r   r   Fc           
      C   s  t t}t t}|r8t|| }||d 7 }||7 }| r`| d |d kr`| d |d kr`|S |dkr|dkr| du r||S td|d|  krdksn td|dks|d dks|d dkr| du r|d|d  t j } | t |7 } |d | d k r|d | d k s"td	|dkrZ|| d }||d 7 }|t 	|t j7 }t | t |d  }|d |d  |d |d  krtd
|d t j
|d  }|| }|}|t | }	| }|	S )a  
    Function:
    ----------
        get reference 5 key points according to crop settings:
        0. Set default crop_size:
            if default_square:
                crop_size = (112, 112)
            else:
                crop_size = (96, 112)
        1. Pad the crop_size by inner_padding_factor in each side;
        2. Resize crop_size into (output_size - outer_padding*2),
            pad into output_size with outer_padding;
        3. Output reference_5point;
    Parameters:
    ----------
        @output_size: (w, h) or None
            size of aligned face image
        @inner_padding_factor: (w_factor, h_factor)
            padding factor for inner (w, h)
        @outer_padding: (w_pad, h_pad)
            each row is a pair of coordinates (x, y)
        @default_square: True or False
            if True:
                default crop_size = (112, 112)
            else:
                default crop_size = (96, 112);
        !!! make sure, if output_size is not None:
                (output_size - outer_padding)
                = some_scale * (default crop_size * (1.0 +
                inner_padding_factor))
    Returns:
    ----------
        @reference_5point: 5x2 np.array
            each row is a pair of transformed coordinates (x, y)
       r   r   r   Nz1No paddings to do, output_size must be None or {}g      ?z&Not (0 <= inner_padding_factor <= 1.0)zMNot (outer_padding[0] < output_size[0] and outer_padding[1] < output_size[1])z_Must have (output_size - outer_padding)= some_scale * (crop_size * (1.0 + inner_padding_factor))nparrayREFERENCE_FACIAL_POINTSDEFAULT_CROP_SIZEmaxr   r   astypeint32roundfloat32)
output_sizeinner_padding_factorouter_paddingdefault_squareZtmp_5ptsZtmp_crop_sizeZ	size_diffZsize_bf_outer_padscale_factorZreference_5pointr   r   r   get_reference_facial_points   sD    %

$($
"r&   c                 C   s   t g dg dg}| jd }t |df| j}t | |g}t ||g}t j||\}}}	}
|	dkrt |d |d |d g|d	 |d
 |d gg}n2|	dkrt |d |d dg|d	 |d
 dgg}|S )a  
    Function:
    ----------
        get affine transform matrix 'tfm' from src_pts to dst_pts
    Parameters:
    ----------
        @src_pts: Kx2 np.array
            source points matrix, each row is a pair of coordinates (x, y)
        @dst_pts: Kx2 np.array
            destination points matrix, each row is a pair of coordinates (x, y)
    Returns:
    ----------
        @tfm: 2x3 np.array
            transform matrix from src_pts to dst_pts
    )r   r   r   )r   r   r   r   r      r   )r   r   )r   r   )r   r   )r   r   )r   r   r   )r   r    shapeonesdtypehstacklinalglstsq)src_ptsZdst_ptstfmn_ptsr)   Zsrc_pts_Zdst_pts_Aresranksr   r   r   get_affine_transform_matrixp   s    
4*r5   	smilarityc                 C   sB  |du rD|d dkr&|d dkr&t }nd}d}d}|}t||||}t|}	|	j}
t|
dk slt|
d	krttd
|
d d	kr|	j}	t|}|j}t|dk st|d	krtd|d d	kr|j}|j|	jkrtd|dkrt	
|dd |	dd }n |dkrt||	}n
t||	}t	| ||d |d f}|S )a4  
    Function:
    ----------
        apply affine transform 'trans' to uv
    Parameters:
    ----------
        @src_img: 3x3 np.array
            input image
        @facial_pts: could be
            1)a list of K coordinates (x,y)
        or
            2) Kx2 or 2xK np.array
            each row or col is a pair of coordinates (x, y)
        @reference_pts: could be
            1) a list of K coordinates (x,y)
        or
            2) Kx2 or 2xK np.array
            each row or col is a pair of coordinates (x, y)
        or
            3) None
            if None, use default reference facial points
        @crop_size: (w, h)
            output face image size
        @align_type: transform type, could be one of
            1) 'similarity': use similarity transform
            2) 'cv2_affine': use the first 3 points to do affine transform,
                    by calling cv2.getAffineTransform()
            3) 'affine': use all points to do affine transform
    Returns:
    ----------
        @face_img: output face image with size (w, h) = @crop_size
    Nr   r   r   r   Fr   r'   r   z2reference_pts.shape must be (K,2) or (2,K) and K>2z/facial_pts.shape must be (K,2) or (2,K) and K>2z5facial_pts and reference_pts must have the same shapeZ
cv2_affineaffine)r   r&   r   r    r(   r   minr   Tcv2getAffineTransformr5   r   
warpAffine)src_imgZ
facial_ptsZreference_pts	crop_sizeZ
align_typer$   r"   r#   r!   Zref_ptsZref_pts_shpr.   Zsrc_pts_shpr/   Zface_imgr   r   r   warp_and_crop_face   s>    "




r?   )Nr   r   F)Nr   r6   )r:   numpyr   Zmatlab_cp2tformr   r   r   	Exceptionr   r&   r5   r?   r   r   r   r   <module>   s   
]!