MrSinan commited on
Commit
a8b217a
·
1 Parent(s): 1792b5f

Upload aux_functions.py

Browse files
Files changed (1) hide show
  1. aux_functions.py +684 -0
aux_functions.py ADDED
@@ -0,0 +1,684 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Author: aqeelanwar
2
+ # Created: 27 April,2020, 10:21 PM
3
+ # Email: aqeel.anwar@gatech.edu
4
+
5
+ from configparser import ConfigParser
6
+ import cv2, math, os
7
+ from PIL import Image, ImageDraw
8
+ from tqdm import tqdm
9
+ from read_cfg import read_cfg
10
+ from fit_ellipse import *
11
+ import random
12
+ from create_mask import texture_the_mask, color_the_mask
13
+ from imutils import face_utils
14
+ import requests
15
+ from zipfile import ZipFile
16
+ from tqdm import tqdm
17
+ import bz2, shutil
18
+ import numpy as np
19
+
20
+
21
+ def download_dlib_model():
22
+ print_orderly("Get dlib model", 60)
23
+ dlib_model_link = "http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2"
24
+ print("Downloading dlib model...")
25
+ with requests.get(dlib_model_link, stream=True) as r:
26
+ print("Zip file size: ", np.round(len(r.content) / 1024 / 1024, 2), "MB")
27
+ destination = (
28
+ "dlib_models" + os.path.sep + "shape_predictor_68_face_landmarks.dat.bz2"
29
+ )
30
+ if not os.path.exists(destination.rsplit(os.path.sep, 1)[0]):
31
+ os.mkdir(destination.rsplit(os.path.sep, 1)[0])
32
+ print("Saving dlib model...")
33
+ with open(destination, "wb") as fd:
34
+ for chunk in r.iter_content(chunk_size=32678):
35
+ fd.write(chunk)
36
+ print("Extracting dlib model...")
37
+ with bz2.BZ2File(destination) as fr, open(
38
+ "dlib_models/shape_predictor_68_face_landmarks.dat", "wb"
39
+ ) as fw:
40
+ shutil.copyfileobj(fr, fw)
41
+ print("Saved: ", destination)
42
+ print_orderly("done", 60)
43
+
44
+ os.remove(destination)
45
+
46
+
47
+ def get_line(face_landmark, image, type="eye", debug=False):
48
+ pil_image = Image.fromarray(image)
49
+ d = ImageDraw.Draw(pil_image)
50
+ left_eye = face_landmark["left_eye"]
51
+ right_eye = face_landmark["right_eye"]
52
+ left_eye_mid = np.mean(np.array(left_eye), axis=0)
53
+ right_eye_mid = np.mean(np.array(right_eye), axis=0)
54
+ eye_line_mid = (left_eye_mid + right_eye_mid) / 2
55
+
56
+ if type == "eye":
57
+ left_point = left_eye_mid
58
+ right_point = right_eye_mid
59
+ mid_point = eye_line_mid
60
+
61
+ elif type == "nose_mid":
62
+ nose_length = (
63
+ face_landmark["nose_bridge"][-1][1] - face_landmark["nose_bridge"][0][1]
64
+ )
65
+ left_point = [left_eye_mid[0], left_eye_mid[1] + nose_length / 2]
66
+ right_point = [right_eye_mid[0], right_eye_mid[1] + nose_length / 2]
67
+ # mid_point = (
68
+ # face_landmark["nose_bridge"][-1][1] + face_landmark["nose_bridge"][0][1]
69
+ # ) / 2
70
+
71
+ mid_pointY = (
72
+ face_landmark["nose_bridge"][-1][1] + face_landmark["nose_bridge"][0][1]
73
+ ) / 2
74
+ mid_pointX = (
75
+ face_landmark["nose_bridge"][-1][0] + face_landmark["nose_bridge"][0][0]
76
+ ) / 2
77
+ mid_point = (mid_pointX, mid_pointY)
78
+
79
+ elif type == "nose_tip":
80
+ nose_length = (
81
+ face_landmark["nose_bridge"][-1][1] - face_landmark["nose_bridge"][0][1]
82
+ )
83
+ left_point = [left_eye_mid[0], left_eye_mid[1] + nose_length]
84
+ right_point = [right_eye_mid[0], right_eye_mid[1] + nose_length]
85
+ mid_point = (
86
+ face_landmark["nose_bridge"][-1][1] + face_landmark["nose_bridge"][0][1]
87
+ ) / 2
88
+
89
+ elif type == "bottom_lip":
90
+ bottom_lip = face_landmark["bottom_lip"]
91
+ bottom_lip_mid = np.max(np.array(bottom_lip), axis=0)
92
+ shiftY = bottom_lip_mid[1] - eye_line_mid[1]
93
+ left_point = [left_eye_mid[0], left_eye_mid[1] + shiftY]
94
+ right_point = [right_eye_mid[0], right_eye_mid[1] + shiftY]
95
+ mid_point = bottom_lip_mid
96
+
97
+ elif type == "perp_line":
98
+ bottom_lip = face_landmark["bottom_lip"]
99
+ bottom_lip_mid = np.mean(np.array(bottom_lip), axis=0)
100
+
101
+ left_point = eye_line_mid
102
+ left_point = face_landmark["nose_bridge"][0]
103
+ right_point = bottom_lip_mid
104
+
105
+ mid_point = bottom_lip_mid
106
+
107
+ elif type == "nose_long":
108
+ nose_bridge = face_landmark["nose_bridge"]
109
+ left_point = [nose_bridge[0][0], nose_bridge[0][1]]
110
+ right_point = [nose_bridge[-1][0], nose_bridge[-1][1]]
111
+
112
+ mid_point = left_point
113
+
114
+ # d.line(eye_mid, width=5, fill='red')
115
+ y = [left_point[1], right_point[1]]
116
+ x = [left_point[0], right_point[0]]
117
+ # cv2.imshow('h', image)
118
+ # cv2.waitKey(0)
119
+ eye_line = fit_line(x, y, image)
120
+ d.line(eye_line, width=5, fill="blue")
121
+
122
+ # Perpendicular Line
123
+ # (midX, midY) and (midX - y2 + y1, midY + x2 - x1)
124
+ y = [
125
+ (left_point[1] + right_point[1]) / 2,
126
+ (left_point[1] + right_point[1]) / 2 + right_point[0] - left_point[0],
127
+ ]
128
+ x = [
129
+ (left_point[0] + right_point[0]) / 2,
130
+ (left_point[0] + right_point[0]) / 2 - right_point[1] + left_point[1],
131
+ ]
132
+ perp_line = fit_line(x, y, image)
133
+ if debug:
134
+ d.line(perp_line, width=5, fill="red")
135
+ pil_image.show()
136
+ return eye_line, perp_line, left_point, right_point, mid_point
137
+
138
+
139
+ def get_points_on_chin(line, face_landmark, chin_type="chin"):
140
+ chin = face_landmark[chin_type]
141
+ points_on_chin = []
142
+ for i in range(len(chin) - 1):
143
+ chin_first_point = [chin[i][0], chin[i][1]]
144
+ chin_second_point = [chin[i + 1][0], chin[i + 1][1]]
145
+
146
+ flag, x, y = line_intersection(line, (chin_first_point, chin_second_point))
147
+ if flag:
148
+ points_on_chin.append((x, y))
149
+
150
+ return points_on_chin
151
+
152
+
153
+ def plot_lines(face_line, image, debug=False):
154
+ pil_image = Image.fromarray(image)
155
+ if debug:
156
+ d = ImageDraw.Draw(pil_image)
157
+ d.line(face_line, width=4, fill="white")
158
+ pil_image.show()
159
+
160
+
161
+ def line_intersection(line1, line2):
162
+ # mid = int(len(line1) / 2)
163
+ start = 0
164
+ end = -1
165
+ line1 = ([line1[start][0], line1[start][1]], [line1[end][0], line1[end][1]])
166
+
167
+ xdiff = (line1[0][0] - line1[1][0], line2[0][0] - line2[1][0])
168
+ ydiff = (line1[0][1] - line1[1][1], line2[0][1] - line2[1][1])
169
+ x = []
170
+ y = []
171
+ flag = False
172
+
173
+ def det(a, b):
174
+ return a[0] * b[1] - a[1] * b[0]
175
+
176
+ div = det(xdiff, ydiff)
177
+ if div == 0:
178
+ return flag, x, y
179
+
180
+ d = (det(*line1), det(*line2))
181
+ x = det(d, xdiff) / div
182
+ y = det(d, ydiff) / div
183
+
184
+ segment_minX = min(line2[0][0], line2[1][0])
185
+ segment_maxX = max(line2[0][0], line2[1][0])
186
+
187
+ segment_minY = min(line2[0][1], line2[1][1])
188
+ segment_maxY = max(line2[0][1], line2[1][1])
189
+
190
+ if (
191
+ segment_maxX + 1 >= x >= segment_minX - 1
192
+ and segment_maxY + 1 >= y >= segment_minY - 1
193
+ ):
194
+ flag = True
195
+
196
+ return flag, x, y
197
+
198
+
199
+ def fit_line(x, y, image):
200
+ if x[0] == x[1]:
201
+ x[0] += 0.1
202
+ coefficients = np.polyfit(x, y, 1)
203
+ polynomial = np.poly1d(coefficients)
204
+ x_axis = np.linspace(0, image.shape[1], 50)
205
+ y_axis = polynomial(x_axis)
206
+ eye_line = []
207
+ for i in range(len(x_axis)):
208
+ eye_line.append((x_axis[i], y_axis[i]))
209
+
210
+ return eye_line
211
+
212
+
213
+ def get_six_points(face_landmark, image):
214
+ _, perp_line1, _, _, m = get_line(face_landmark, image, type="nose_mid")
215
+ face_b = m
216
+
217
+ perp_line, _, _, _, _ = get_line(face_landmark, image, type="perp_line")
218
+ points1 = get_points_on_chin(perp_line1, face_landmark)
219
+ points = get_points_on_chin(perp_line, face_landmark)
220
+ if not points1:
221
+ face_e = tuple(np.asarray(points[0]))
222
+ elif not points:
223
+ face_e = tuple(np.asarray(points1[0]))
224
+ else:
225
+ face_e = tuple((np.asarray(points[0]) + np.asarray(points1[0])) / 2)
226
+ # face_e = points1[0]
227
+ nose_mid_line, _, _, _, _ = get_line(face_landmark, image, type="nose_long")
228
+
229
+ angle = get_angle(perp_line, nose_mid_line)
230
+ # print("angle: ", angle)
231
+ nose_mid_line, _, _, _, _ = get_line(face_landmark, image, type="nose_tip")
232
+ points = get_points_on_chin(nose_mid_line, face_landmark)
233
+ if len(points) < 2:
234
+ face_landmark = get_face_ellipse(face_landmark)
235
+ # print("extrapolating chin")
236
+ points = get_points_on_chin(
237
+ nose_mid_line, face_landmark, chin_type="chin_extrapolated"
238
+ )
239
+ if len(points) < 2:
240
+ points = []
241
+ points.append(face_landmark["chin"][0])
242
+ points.append(face_landmark["chin"][-1])
243
+ face_a = points[0]
244
+ face_c = points[-1]
245
+ # cv2.imshow('j', image)
246
+ # cv2.waitKey(0)
247
+ nose_mid_line, _, _, _, _ = get_line(face_landmark, image, type="bottom_lip")
248
+ points = get_points_on_chin(nose_mid_line, face_landmark)
249
+ face_d = points[0]
250
+ face_f = points[-1]
251
+
252
+ six_points = np.float32([face_a, face_b, face_c, face_f, face_e, face_d])
253
+
254
+ return six_points, angle
255
+
256
+
257
+ def get_angle(line1, line2):
258
+ delta_y = line1[-1][1] - line1[0][1]
259
+ delta_x = line1[-1][0] - line1[0][0]
260
+ perp_angle = math.degrees(math.atan2(delta_y, delta_x))
261
+ if delta_x < 0:
262
+ perp_angle = perp_angle + 180
263
+ if perp_angle < 0:
264
+ perp_angle += 360
265
+ if perp_angle > 180:
266
+ perp_angle -= 180
267
+
268
+ # print("perp", perp_angle)
269
+ delta_y = line2[-1][1] - line2[0][1]
270
+ delta_x = line2[-1][0] - line2[0][0]
271
+ nose_angle = math.degrees(math.atan2(delta_y, delta_x))
272
+
273
+ if delta_x < 0:
274
+ nose_angle = nose_angle + 180
275
+ if nose_angle < 0:
276
+ nose_angle += 360
277
+ if nose_angle > 180:
278
+ nose_angle -= 180
279
+ # print("nose", nose_angle)
280
+
281
+ angle = nose_angle - perp_angle
282
+ return angle
283
+
284
+
285
+ def mask_face(image, face_location, six_points, angle, args, type="surgical"):
286
+ debug = False
287
+
288
+ # Find the face angle
289
+ threshold = 13
290
+ if angle < -threshold:
291
+ type += "_right"
292
+ elif angle > threshold:
293
+ type += "_left"
294
+
295
+ face_height = face_location[2] - face_location[0]
296
+ face_width = face_location[1] - face_location[3]
297
+ # image = image_raw[
298
+ # face_location[0]-int(face_width/2): face_location[2]+int(face_width/2),
299
+ # face_location[3]-int(face_height/2): face_location[1]+int(face_height/2),
300
+ # :,
301
+ # ]
302
+ # cv2.imshow('win', image)
303
+ # cv2.waitKey(0)
304
+ # Read appropriate mask image
305
+ w = image.shape[0]
306
+ h = image.shape[1]
307
+ if not "empty" in type and not "inpaint" in type:
308
+ cfg = read_cfg(config_filename="masks/masks.cfg", mask_type=type, verbose=False)
309
+ else:
310
+ if "left" in type:
311
+ str = "surgical_blue_left"
312
+ elif "right" in type:
313
+ str = "surgical_blue_right"
314
+ else:
315
+ str = "surgical_blue"
316
+ cfg = read_cfg(config_filename="masks/masks.cfg", mask_type=str, verbose=False)
317
+ img = cv2.imread(cfg.template, cv2.IMREAD_UNCHANGED)
318
+
319
+ # Process the mask if necessary
320
+ if args.pattern:
321
+ # Apply pattern to mask
322
+ img = texture_the_mask(img, args.pattern, args.pattern_weight)
323
+
324
+ if args.color:
325
+ # Apply color to mask
326
+ img = color_the_mask(img, args.color, args.color_weight)
327
+
328
+ mask_line = np.float32(
329
+ [cfg.mask_a, cfg.mask_b, cfg.mask_c, cfg.mask_f, cfg.mask_e, cfg.mask_d]
330
+ )
331
+ # Warp the mask
332
+ M, mask = cv2.findHomography(mask_line, six_points)
333
+ dst_mask = cv2.warpPerspective(img, M, (h, w))
334
+ dst_mask_points = cv2.perspectiveTransform(mask_line.reshape(-1, 1, 2), M)
335
+ mask = dst_mask[:, :, 3]
336
+ face_height = face_location[2] - face_location[0]
337
+ face_width = face_location[1] - face_location[3]
338
+ image_face = image[
339
+ face_location[0] + int(face_height / 2) : face_location[2],
340
+ face_location[3] : face_location[1],
341
+ :,
342
+ ]
343
+
344
+ image_face = image
345
+
346
+ # Adjust Brightness
347
+ mask_brightness = get_avg_brightness(img)
348
+ img_brightness = get_avg_brightness(image_face)
349
+ delta_b = 1 + (img_brightness - mask_brightness) / 255
350
+ dst_mask = change_brightness(dst_mask, delta_b)
351
+
352
+ # Adjust Saturation
353
+ mask_saturation = get_avg_saturation(img)
354
+ img_saturation = get_avg_saturation(image_face)
355
+ delta_s = 1 - (img_saturation - mask_saturation) / 255
356
+ dst_mask = change_saturation(dst_mask, delta_s)
357
+
358
+ # Apply mask
359
+ mask_inv = cv2.bitwise_not(mask)
360
+ img_bg = cv2.bitwise_and(image, image, mask=mask_inv)
361
+ img_fg = cv2.bitwise_and(dst_mask, dst_mask, mask=mask)
362
+ out_img = cv2.add(img_bg, img_fg[:, :, 0:3])
363
+ if "empty" in type or "inpaint" in type:
364
+ out_img = img_bg
365
+ # Plot key points
366
+
367
+ if "inpaint" in type:
368
+ out_img = cv2.inpaint(out_img, mask, 3, cv2.INPAINT_TELEA)
369
+ # dst_NS = cv2.inpaint(img, mask, 3, cv2.INPAINT_NS)
370
+
371
+ if debug:
372
+ for i in six_points:
373
+ cv2.circle(out_img, (i[0], i[1]), radius=4, color=(0, 0, 255), thickness=-1)
374
+
375
+ for i in dst_mask_points:
376
+ cv2.circle(
377
+ out_img, (i[0][0], i[0][1]), radius=4, color=(0, 255, 0), thickness=-1
378
+ )
379
+
380
+ return out_img, mask
381
+
382
+
383
+ def draw_landmarks(face_landmarks, image):
384
+ pil_image = Image.fromarray(image)
385
+ d = ImageDraw.Draw(pil_image)
386
+ for facial_feature in face_landmarks.keys():
387
+ d.line(face_landmarks[facial_feature], width=5, fill="white")
388
+ pil_image.show()
389
+
390
+
391
+ def get_face_ellipse(face_landmark):
392
+ chin = face_landmark["chin"]
393
+ x = []
394
+ y = []
395
+ for point in chin:
396
+ x.append(point[0])
397
+ y.append(point[1])
398
+
399
+ x = np.asarray(x)
400
+ y = np.asarray(y)
401
+
402
+ a = fitEllipse(x, y)
403
+ center = ellipse_center(a)
404
+ phi = ellipse_angle_of_rotation(a)
405
+ axes = ellipse_axis_length(a)
406
+ a, b = axes
407
+
408
+ arc = 2.2
409
+ R = np.arange(0, arc * np.pi, 0.2)
410
+ xx = center[0] + a * np.cos(R) * np.cos(phi) - b * np.sin(R) * np.sin(phi)
411
+ yy = center[1] + a * np.cos(R) * np.sin(phi) + b * np.sin(R) * np.cos(phi)
412
+ chin_extrapolated = []
413
+ for i in range(len(R)):
414
+ chin_extrapolated.append((xx[i], yy[i]))
415
+ face_landmark["chin_extrapolated"] = chin_extrapolated
416
+ return face_landmark
417
+
418
+
419
+ def get_avg_brightness(img):
420
+ img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
421
+ h, s, v = cv2.split(img_hsv)
422
+ return np.mean(v)
423
+
424
+
425
+ def get_avg_saturation(img):
426
+ img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
427
+ h, s, v = cv2.split(img_hsv)
428
+ return np.mean(v)
429
+
430
+
431
+ def change_brightness(img, value=1.0):
432
+ img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
433
+ h, s, v = cv2.split(img_hsv)
434
+ v = value * v
435
+ v[v > 255] = 255
436
+ v = np.asarray(v, dtype=np.uint8)
437
+ final_hsv = cv2.merge((h, s, v))
438
+ img = cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
439
+ return img
440
+
441
+
442
+ def change_saturation(img, value=1.0):
443
+ img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
444
+ h, s, v = cv2.split(img_hsv)
445
+ s = value * s
446
+ s[s > 255] = 255
447
+ s = np.asarray(s, dtype=np.uint8)
448
+ final_hsv = cv2.merge((h, s, v))
449
+ img = cv2.cvtColor(final_hsv, cv2.COLOR_HSV2BGR)
450
+ return img
451
+
452
+
453
+ def check_path(path):
454
+ is_directory = False
455
+ is_file = False
456
+ is_other = False
457
+ if os.path.isdir(path):
458
+ is_directory = True
459
+ elif os.path.isfile(path):
460
+ is_file = True
461
+ else:
462
+ is_other = True
463
+
464
+ return is_directory, is_file, is_other
465
+
466
+
467
+ def shape_to_landmarks(shape):
468
+ face_landmarks = {}
469
+ face_landmarks["left_eyebrow"] = [
470
+ tuple(shape[17]),
471
+ tuple(shape[18]),
472
+ tuple(shape[19]),
473
+ tuple(shape[20]),
474
+ tuple(shape[21]),
475
+ ]
476
+ face_landmarks["right_eyebrow"] = [
477
+ tuple(shape[22]),
478
+ tuple(shape[23]),
479
+ tuple(shape[24]),
480
+ tuple(shape[25]),
481
+ tuple(shape[26]),
482
+ ]
483
+ face_landmarks["nose_bridge"] = [
484
+ tuple(shape[27]),
485
+ tuple(shape[28]),
486
+ tuple(shape[29]),
487
+ tuple(shape[30]),
488
+ ]
489
+ face_landmarks["nose_tip"] = [
490
+ tuple(shape[31]),
491
+ tuple(shape[32]),
492
+ tuple(shape[33]),
493
+ tuple(shape[34]),
494
+ tuple(shape[35]),
495
+ ]
496
+ face_landmarks["left_eye"] = [
497
+ tuple(shape[36]),
498
+ tuple(shape[37]),
499
+ tuple(shape[38]),
500
+ tuple(shape[39]),
501
+ tuple(shape[40]),
502
+ tuple(shape[41]),
503
+ ]
504
+ face_landmarks["right_eye"] = [
505
+ tuple(shape[42]),
506
+ tuple(shape[43]),
507
+ tuple(shape[44]),
508
+ tuple(shape[45]),
509
+ tuple(shape[46]),
510
+ tuple(shape[47]),
511
+ ]
512
+ face_landmarks["top_lip"] = [
513
+ tuple(shape[48]),
514
+ tuple(shape[49]),
515
+ tuple(shape[50]),
516
+ tuple(shape[51]),
517
+ tuple(shape[52]),
518
+ tuple(shape[53]),
519
+ tuple(shape[54]),
520
+ tuple(shape[60]),
521
+ tuple(shape[61]),
522
+ tuple(shape[62]),
523
+ tuple(shape[63]),
524
+ tuple(shape[64]),
525
+ ]
526
+
527
+ face_landmarks["bottom_lip"] = [
528
+ tuple(shape[54]),
529
+ tuple(shape[55]),
530
+ tuple(shape[56]),
531
+ tuple(shape[57]),
532
+ tuple(shape[58]),
533
+ tuple(shape[59]),
534
+ tuple(shape[48]),
535
+ tuple(shape[64]),
536
+ tuple(shape[65]),
537
+ tuple(shape[66]),
538
+ tuple(shape[67]),
539
+ tuple(shape[60]),
540
+ ]
541
+
542
+ face_landmarks["chin"] = [
543
+ tuple(shape[0]),
544
+ tuple(shape[1]),
545
+ tuple(shape[2]),
546
+ tuple(shape[3]),
547
+ tuple(shape[4]),
548
+ tuple(shape[5]),
549
+ tuple(shape[6]),
550
+ tuple(shape[7]),
551
+ tuple(shape[8]),
552
+ tuple(shape[9]),
553
+ tuple(shape[10]),
554
+ tuple(shape[11]),
555
+ tuple(shape[12]),
556
+ tuple(shape[13]),
557
+ tuple(shape[14]),
558
+ tuple(shape[15]),
559
+ tuple(shape[16]),
560
+ ]
561
+ return face_landmarks
562
+
563
+
564
+ def rect_to_bb(rect):
565
+ x1 = rect.left()
566
+ x2 = rect.right()
567
+ y1 = rect.top()
568
+ y2 = rect.bottom()
569
+ return (x1, x2, y2, x1)
570
+
571
+
572
+ def mask_image(theImage, args):
573
+ # Read the image
574
+ image = theImage
575
+ original_image = image.copy()
576
+ # gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
577
+ gray = image
578
+ face_locations = args.detector(gray, 1)
579
+ mask_type = args.mask_type
580
+ verbose = args.verbose
581
+ if args.code:
582
+ ind = random.randint(0, len(args.code_count) - 1)
583
+ mask_dict = args.mask_dict_of_dict[ind]
584
+ mask_type = mask_dict["type"]
585
+ args.color = mask_dict["color"]
586
+ args.pattern = mask_dict["texture"]
587
+ args.code_count[ind] += 1
588
+
589
+ elif mask_type == "random":
590
+ available_mask_types = get_available_mask_types()
591
+ mask_type = random.choice(available_mask_types)
592
+
593
+ if verbose:
594
+ tqdm.write("Faces found: {:2d}".format(len(face_locations)))
595
+ # Process each face in the image
596
+ masked_images = []
597
+ mask_binary_array = []
598
+ mask = []
599
+ for (i, face_location) in enumerate(face_locations):
600
+ shape = args.predictor(gray, face_location)
601
+ shape = face_utils.shape_to_np(shape)
602
+ face_landmarks = shape_to_landmarks(shape)
603
+ face_location = rect_to_bb(face_location)
604
+ # draw_landmarks(face_landmarks, image)
605
+ six_points_on_face, angle = get_six_points(face_landmarks, image)
606
+ mask = []
607
+ if mask_type != "all":
608
+ if len(masked_images) > 0:
609
+ image = masked_images.pop(0)
610
+ image, mask_binary = mask_face(
611
+ image, face_location, six_points_on_face, angle, args, type=mask_type
612
+ )
613
+
614
+ # compress to face tight
615
+ face_height = face_location[2] - face_location[0]
616
+ face_width = face_location[1] - face_location[3]
617
+ masked_images.append(image)
618
+ mask_binary_array.append(mask_binary)
619
+ mask.append(mask_type)
620
+ else:
621
+ available_mask_types = get_available_mask_types()
622
+ for m in range(len(available_mask_types)):
623
+ if len(masked_images) == len(available_mask_types):
624
+ image = masked_images.pop(m)
625
+ img, mask_binary = mask_face(
626
+ image,
627
+ face_location,
628
+ six_points_on_face,
629
+ angle,
630
+ args,
631
+ type=available_mask_types[m],
632
+ )
633
+ masked_images.insert(m, img)
634
+ mask_binary_array.insert(m, mask_binary)
635
+ mask = available_mask_types
636
+ cc = 1
637
+
638
+ return masked_images, mask, mask_binary_array, original_image
639
+
640
+
641
+ def is_image(path):
642
+ try:
643
+ extensions = path[-4:]
644
+ image_extensions = ["png", "PNG", "jpg", "JPG"]
645
+
646
+ if extensions[1:] in image_extensions:
647
+ return True
648
+ else:
649
+ print("Please input image file. png / jpg")
650
+ return False
651
+ except:
652
+ return False
653
+
654
+
655
+ def get_available_mask_types(config_filename="masks/masks.cfg"):
656
+ parser = ConfigParser()
657
+ parser.optionxform = str
658
+ parser.read(config_filename)
659
+ available_mask_types = parser.sections()
660
+ available_mask_types = [
661
+ string for string in available_mask_types if "left" not in string
662
+ ]
663
+ available_mask_types = [
664
+ string for string in available_mask_types if "right" not in string
665
+ ]
666
+
667
+ return available_mask_types
668
+
669
+
670
+ def print_orderly(str, n):
671
+ # print("")
672
+ hyphens = "-" * int((n - len(str)) / 2)
673
+ str_p = hyphens + " " + str + " " + hyphens
674
+ hyphens_bar = "-" * len(str_p)
675
+ print(hyphens_bar)
676
+ print(str_p)
677
+ print(hyphens_bar)
678
+
679
+
680
+ def display_MaskTheFace():
681
+ with open("utils/display.txt", "r") as file:
682
+ for line in file:
683
+ cc = 1
684
+ print(line, end="")