diff --git a/facelib/LandmarksProcessor.py b/facelib/LandmarksProcessor.py index f95cb0f..0480351 100644 --- a/facelib/LandmarksProcessor.py +++ b/facelib/LandmarksProcessor.py @@ -372,6 +372,30 @@ def get_image_hull_mask (image_shape, image_landmarks, eyebrows_expand_mod=1.0, ie_polys.overlay_mask(hull_mask) return hull_mask + +def get_image_eye_mask (image_shape, image_landmarks): + if len(image_landmarks) != 68: + raise Exception('get_image_eye_mask works only with 68 landmarks') + + h,w,c = image_shape + + hull_mask = np.zeros( (h,w,1),dtype=np.float32) + + image_landmarks = image_landmarks.astype(np.int) + + cv2.fillConvexPoly( hull_mask, cv2.convexHull( image_landmarks[36:42]), (1,) ) + cv2.fillConvexPoly( hull_mask, cv2.convexHull( image_landmarks[42:48]), (1,) ) + + dilate = h // 32 + hull_mask = cv2.dilate(hull_mask, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(dilate,dilate)), iterations = 1 ) + + blur = h // 16 + blur = blur + (1-blur % 2) + hull_mask = cv2.GaussianBlur(hull_mask, (blur, blur) , 0) + hull_mask = hull_mask[...,None] + + return hull_mask + def alpha_to_color (img_alpha, color): if len(img_alpha.shape) == 2: @@ -535,17 +559,6 @@ def get_cmask (image_shape, lmrks, eyebrows_expand_mod=1.0): #result = np.clip (result, 0, 1) return result -def get_image_eye_mask (image_shape, image_landmarks): - if len(image_landmarks) != 68: - raise Exception('get_image_eye_mask works only with 68 landmarks') - - hull_mask = np.zeros(image_shape[0:2]+(1,),dtype=np.float32) - - cv2.fillConvexPoly( hull_mask, cv2.convexHull( image_landmarks[36:42]), (1,) ) - cv2.fillConvexPoly( hull_mask, cv2.convexHull( image_landmarks[42:48]), (1,) ) - - return hull_mask - def blur_image_hull_mask (hull_mask): maxregion = np.argwhere(hull_mask==1.0) diff --git a/samplelib/SampleProcessor.py b/samplelib/SampleProcessor.py index fda1f91..fa7ba9c 100644 --- a/samplelib/SampleProcessor.py +++ b/samplelib/SampleProcessor.py @@ -36,9 +36,10 @@ class SampleProcessor(object): MODE_G = 41 #Grayscale MODE_GGG = 42 #3xGrayscale MODE_FACE_MASK_HULL = 43 #mask hull as grayscale - MODE_FACE_MASK_STRUCT = 44 #mask structure as grayscale - MODE_BGR_SHUFFLE = 45 #BGR shuffle - MODE_BGR_RANDOM_HSV_SHIFT = 46 + MODE_FACE_MASK_EYES_HULL = 44 #mask eyes hull as grayscale + MODE_FACE_MASK_STRUCT = 45 #mask structure as grayscale + MODE_BGR_SHUFFLE = 46 #BGR shuffle + MODE_BGR_RANDOM_HSV_SHIFT = 47 MODE_END = 50 class Options(object): @@ -101,13 +102,17 @@ class SampleProcessor(object): elif t >= SPTF.MODE_BEGIN and t < SPTF.MODE_END: mode_type = t - if mode_type == SPTF.MODE_FACE_MASK_HULL and not is_face_sample: - raise ValueError("MODE_FACE_MASK_HULL applicable only for face samples") - if mode_type == SPTF.MODE_FACE_MASK_STRUCT and not is_face_sample: - raise ValueError("MODE_FACE_MASK_STRUCT applicable only for face samples") + if is_face_sample: if target_face_type == SPTF.NONE: raise ValueError("target face type must be defined for face samples") + else: + if mode_type == SPTF.MODE_FACE_MASK_HULL: + raise ValueError("MODE_FACE_MASK_HULL applicable only for face samples") + if mode_type == SPTF.MODE_FACE_MASK_EYES_HULL: + raise ValueError("MODE_FACE_MASK_EYES_HULL applicable only for face samples") + elif mode_type == SPTF.MODE_FACE_MASK_STRUCT: + raise ValueError("MODE_FACE_MASK_STRUCT applicable only for face samples") can_warp = (img_type==SPTF.IMG_WARPED or img_type==SPTF.IMG_WARPED_TRANSFORMED) can_transform = (img_type==SPTF.IMG_WARPED_TRANSFORMED or img_type==SPTF.IMG_TRANSFORMED) @@ -144,6 +149,9 @@ class SampleProcessor(object): if sample.ie_polys is not None: sample.ie_polys.overlay_mask(img) + elif mode_type == SPTF.MODE_FACE_MASK_EYES_HULL: + img = LandmarksProcessor.get_image_eye_mask (sample_bgr.shape, sample.landmarks) + elif mode_type == SPTF.MODE_FACE_MASK_STRUCT: if sample.eyebrows_expand_mod is not None: img = LandmarksProcessor.get_face_struct_mask (sample_bgr.shape, sample.landmarks, eyebrows_expand_mod=sample.eyebrows_expand_mod ) @@ -154,7 +162,7 @@ class SampleProcessor(object): if motion_blur is not None: chance, mb_max_size = motion_blur chance = np.clip(chance, 0, 100) - + rnd_state = np.random.RandomState (sample_rnd_seed) mblur_rnd_chance = rnd_state.randint(100) mblur_rnd_kernel = rnd_state.randint(mb_max_size)+1 @@ -178,7 +186,9 @@ class SampleProcessor(object): if sample.face_type == FaceType.MARK_ONLY: mat = LandmarksProcessor.get_transform_mat (sample.landmarks, sample.shape[0], target_ft) - if mode_type == SPTF.MODE_FACE_MASK_HULL or mode_type == SPTF.MODE_FACE_MASK_STRUCT: + if mode_type == SPTF.MODE_FACE_MASK_HULL or \ + mode_type == SPTF.MODE_FACE_MASK_EYES_HULL or \ + mode_type == SPTF.MODE_FACE_MASK_STRUCT: img = cv2.warpAffine( img, mat, (sample.shape[0],sample.shape[0]), flags=cv2.INTER_CUBIC ) img = imagelib.warp_by_params (params, img, can_warp, can_transform, can_flip=True, border_replicate=False) img = cv2.resize( img, (resolution,resolution), cv2.INTER_CUBIC )[...,None] @@ -190,7 +200,9 @@ class SampleProcessor(object): else: mat = LandmarksProcessor.get_transform_mat (sample.landmarks, resolution, target_ft) - if mode_type == SPTF.MODE_FACE_MASK_HULL or mode_type == SPTF.MODE_FACE_MASK_STRUCT: + if mode_type == SPTF.MODE_FACE_MASK_HULL or \ + mode_type == SPTF.MODE_FACE_MASK_EYES_HULL or \ + mode_type == SPTF.MODE_FACE_MASK_STRUCT: img = imagelib.warp_by_params (params, img, can_warp, can_transform, can_flip=True, border_replicate=False) img = cv2.warpAffine( img, mat, (resolution,resolution), borderMode=cv2.BORDER_CONSTANT, flags=cv2.INTER_CUBIC )[...,None] else: @@ -201,7 +213,9 @@ class SampleProcessor(object): img = cv2.resize( img, (resolution,resolution), cv2.INTER_CUBIC ) - if mode_type == SPTF.MODE_FACE_MASK_HULL or mode_type == SPTF.MODE_FACE_MASK_STRUCT: + if mode_type == SPTF.MODE_FACE_MASK_HULL or \ + mode_type == SPTF.MODE_FACE_MASK_EYES_HULL or \ + mode_type == SPTF.MODE_FACE_MASK_STRUCT: out_sample = np.clip(img.astype(np.float32), 0, 1) else: img = np.clip(img.astype(np.float32), 0, 1)