Spaces:
Build error
Build error
import numpy as np | |
import cv2 | |
def expand_eyebrows(lmrks, eyebrows_expand_mod=1.0): | |
lmrks = np.array( lmrks.copy(), dtype=np.int32 ) | |
# Top of the eye arrays | |
bot_l = lmrks[[35, 41, 40, 42, 39]] | |
bot_r = lmrks[[89, 95, 94, 96, 93]] | |
# Eyebrow arrays | |
top_l = lmrks[[43, 48, 49, 51, 50]] | |
top_r = lmrks[[102, 103, 104, 105, 101]] | |
# Adjust eyebrow arrays | |
lmrks[[43, 48, 49, 51, 50]] = top_l + eyebrows_expand_mod * 0.5 * (top_l - bot_l) | |
lmrks[[102, 103, 104, 105, 101]] = top_r + eyebrows_expand_mod * 0.5 * (top_r - bot_r) | |
return lmrks | |
def get_mask(image: np.ndarray, landmarks: np.ndarray) -> np.ndarray: | |
""" | |
Get face mask of image size using given landmarks of person | |
""" | |
img_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) | |
mask = np.zeros_like(img_gray) | |
points = np.array(landmarks, np.int32) | |
convexhull = cv2.convexHull(points) | |
cv2.fillConvexPoly(mask, convexhull, 255) | |
return mask | |
def face_mask_static(image: np.ndarray, landmarks: np.ndarray, landmarks_tgt: np.ndarray, params = None) -> np.ndarray: | |
""" | |
Get the final mask, using landmarks and applying blur | |
""" | |
if params is None: | |
left = np.sum((landmarks[1][0]-landmarks_tgt[1][0], landmarks[2][0]-landmarks_tgt[2][0], landmarks[13][0]-landmarks_tgt[13][0])) | |
right = np.sum((landmarks_tgt[17][0]-landmarks[17][0], landmarks_tgt[18][0]-landmarks[18][0], landmarks_tgt[29][0]-landmarks[29][0])) | |
offset = max(left, right) | |
if offset > 6: | |
erode = 15 | |
sigmaX = 15 | |
sigmaY = 10 | |
elif offset > 3: | |
erode = 10 | |
sigmaX = 10 | |
sigmaY = 8 | |
elif offset < -3: | |
erode = -5 | |
sigmaX = 5 | |
sigmaY = 10 | |
else: | |
erode = 5 | |
sigmaX = 5 | |
sigmaY = 5 | |
else: | |
erode = params[0] | |
sigmaX = params[1] | |
sigmaY = params[2] | |
if erode == 15: | |
eyebrows_expand_mod=2.7 | |
elif erode == -5: | |
eyebrows_expand_mod=0.5 | |
else: | |
eyebrows_expand_mod=2.0 | |
landmarks = expand_eyebrows(landmarks, eyebrows_expand_mod=eyebrows_expand_mod) | |
mask = get_mask(image, landmarks) | |
mask = erode_and_blur(mask, erode, sigmaX, sigmaY, True) | |
if params is None: | |
return mask/255, [erode, sigmaX, sigmaY] | |
return mask/255 | |
def erode_and_blur(mask_input, erode, sigmaX, sigmaY, fade_to_border = True): | |
mask = np.copy(mask_input) | |
if erode > 0: | |
kernel = np.ones((erode, erode), 'uint8') | |
mask = cv2.erode(mask, kernel, iterations=1) | |
else: | |
kernel = np.ones((-erode, -erode), 'uint8') | |
mask = cv2.dilate(mask, kernel, iterations=1) | |
if fade_to_border: | |
clip_size = sigmaY * 2 | |
mask[:clip_size,:] = 0 | |
mask[-clip_size:,:] = 0 | |
mask[:,:clip_size] = 0 | |
mask[:,-clip_size:] = 0 | |
mask = cv2.GaussianBlur(mask, (0, 0), sigmaX = sigmaX, sigmaY = sigmaY) | |
return mask | |