CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ai-forever

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: ai-forever/sber-swap
Path: blob/main/utils/inference/masks.py
Views: 792
1
import numpy as np
2
import cv2
3
4
5
def expand_eyebrows(lmrks, eyebrows_expand_mod=1.0):
6
7
lmrks = np.array( lmrks.copy(), dtype=np.int32 )
8
9
# Top of the eye arrays
10
bot_l = lmrks[[35, 41, 40, 42, 39]]
11
bot_r = lmrks[[89, 95, 94, 96, 93]]
12
13
# Eyebrow arrays
14
top_l = lmrks[[43, 48, 49, 51, 50]]
15
top_r = lmrks[[102, 103, 104, 105, 101]]
16
17
# Adjust eyebrow arrays
18
lmrks[[43, 48, 49, 51, 50]] = top_l + eyebrows_expand_mod * 0.5 * (top_l - bot_l)
19
lmrks[[102, 103, 104, 105, 101]] = top_r + eyebrows_expand_mod * 0.5 * (top_r - bot_r)
20
return lmrks
21
22
23
def get_mask(image: np.ndarray, landmarks: np.ndarray) -> np.ndarray:
24
"""
25
Get face mask of image size using given landmarks of person
26
"""
27
28
img_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
29
mask = np.zeros_like(img_gray)
30
31
points = np.array(landmarks, np.int32)
32
convexhull = cv2.convexHull(points)
33
cv2.fillConvexPoly(mask, convexhull, 255)
34
35
return mask
36
37
38
def face_mask_static(image: np.ndarray, landmarks: np.ndarray, landmarks_tgt: np.ndarray, params = None) -> np.ndarray:
39
"""
40
Get the final mask, using landmarks and applying blur
41
"""
42
if params is None:
43
44
left = np.sum((landmarks[1][0]-landmarks_tgt[1][0], landmarks[2][0]-landmarks_tgt[2][0], landmarks[13][0]-landmarks_tgt[13][0]))
45
right = np.sum((landmarks_tgt[17][0]-landmarks[17][0], landmarks_tgt[18][0]-landmarks[18][0], landmarks_tgt[29][0]-landmarks[29][0]))
46
47
offset = max(left, right)
48
49
if offset > 6:
50
erode = 15
51
sigmaX = 15
52
sigmaY = 10
53
elif offset > 3:
54
erode = 10
55
sigmaX = 10
56
sigmaY = 8
57
elif offset < -3:
58
erode = -5
59
sigmaX = 5
60
sigmaY = 10
61
else:
62
erode = 5
63
sigmaX = 5
64
sigmaY = 5
65
66
else:
67
erode = params[0]
68
sigmaX = params[1]
69
sigmaY = params[2]
70
71
if erode == 15:
72
eyebrows_expand_mod=2.7
73
elif erode == -5:
74
eyebrows_expand_mod=0.5
75
else:
76
eyebrows_expand_mod=2.0
77
landmarks = expand_eyebrows(landmarks, eyebrows_expand_mod=eyebrows_expand_mod)
78
79
mask = get_mask(image, landmarks)
80
mask = erode_and_blur(mask, erode, sigmaX, sigmaY, True)
81
82
if params is None:
83
return mask/255, [erode, sigmaX, sigmaY]
84
85
return mask/255
86
87
88
def erode_and_blur(mask_input, erode, sigmaX, sigmaY, fade_to_border = True):
89
mask = np.copy(mask_input)
90
91
if erode > 0:
92
kernel = np.ones((erode, erode), 'uint8')
93
mask = cv2.erode(mask, kernel, iterations=1)
94
95
else:
96
kernel = np.ones((-erode, -erode), 'uint8')
97
mask = cv2.dilate(mask, kernel, iterations=1)
98
99
if fade_to_border:
100
clip_size = sigmaY * 2
101
mask[:clip_size,:] = 0
102
mask[-clip_size:,:] = 0
103
mask[:,:clip_size] = 0
104
mask[:,-clip_size:] = 0
105
106
mask = cv2.GaussianBlur(mask, (0, 0), sigmaX = sigmaX, sigmaY = sigmaY)
107
108
return mask
109
110