From db62b82cc35e8f03c0b6e7bc86220182ce8bb356 Mon Sep 17 00:00:00 2001 From: cristinapunti Date: Wed, 16 Nov 2022 09:54:17 +0100 Subject: [PATCH 01/13] first commit --- face_alignment/api.py | 129 +++++++++++++++++++++++++++++++++++++--- face_alignment/utils.py | 3 + 2 files changed, 124 insertions(+), 8 deletions(-) diff --git a/face_alignment/api.py b/face_alignment/api.py index d1cfbfd..49f289c 100644 --- a/face_alignment/api.py +++ b/face_alignment/api.py @@ -1,3 +1,10 @@ +import time +import matplotlib.pyplot as plt +from PIL import Image +import cv2 + +import torchvision.transforms as T + import torch import warnings from enum import IntEnum @@ -5,6 +12,7 @@ from .utils import * +from core_lib.utilities import logger class LandmarksType(IntEnum): """Enum class defining the type of landmarks to detect. @@ -115,8 +123,22 @@ def get_landmarks_from_image(self, image_or_path, detected_faces=None, return_bb """ image = get_image(image_or_path) + start = time.time() + + ht = image.shape[0] + wd = image.shape[1] + + # Force detected faces to be OUR bounding boxes + detected_faces=[np.array([1.0, np.float(ht-1), np.float(wd-1), 1.0])] + #print(f'detected_faces: {detected_faces}') + logger.info(f'Landmark detector input image size: {ht} x {wd}') + if detected_faces is None: detected_faces = self.face_detector.detect_from_image(image.copy()) + + final = time.time() + logger.warning(f'Execution time for detected_faces: {final-start} seconds! ') + logger.warning(f'{len(detected_faces)} Face(s) Detected!') if len(detected_faces) == 0: warnings.warn("No faces were detected.") @@ -128,45 +150,136 @@ def get_landmarks_from_image(self, image_or_path, detected_faces=None, return_bb landmarks = [] landmarks_scores = [] for i, d in enumerate(detected_faces): + logger.info(f'Bounding Box for face detected is {d}') + center = torch.tensor( [d[2] - (d[2] - d[0]) / 2.0, d[3] - (d[3] - d[1]) / 2.0]) - center[1] = center[1] - (d[3] - d[1]) * 0.12 + center[1] = center[1] - (d[3] - d[1]) * 0.12 # PERQUE?? NO ES FA SERVIR MES! scale = (d[2] - d[0] + d[3] - d[1]) / self.face_detector.reference_scale - + #scale = 2 #??????? + + logger.warning('FACE ALIGNMENT') + logger.info(f'Input image: {(image).shape}') + logger.info(f'Extra information: Center {center}, Scale value {scale} // Reference scale {self.face_detector.reference_scale}') + + # image shape -> Size([358, 358, 3]) + + # Save image + im = Image.fromarray(image) + logger.error("SAVE INPUT IMAGE!!!") + output_path = os.path.join('/Users/crisalix/Desktop/test/image.jpg') + im.save(output_path) + + ''' + logger.warning('CROP') + # Crop taking into account center and scale --> Crop + Resize inp = crop(image, center, scale) - inp = torch.from_numpy(inp.transpose( - (2, 0, 1))).float() - - inp = inp.to(self.device) + logger.info(f'Shape after crop {inp.shape}') + # inp.shape -> Size([256, 256, 3]) + + # Save crop + logger.error("SAVE CROPPED IMAGE!!!") + inp_arr = Image.fromarray(inp) + output_path = os.path.join('/Users/crisalix/Desktop/test/image_2.jpg') + inp_arr.save(output_path) + + # Transpose and torch! + inp = torch.from_numpy(inp.transpose((2, 0, 1))).float() + # inp.shape -> torch.Size([3, 256, 256]) + + ''' + + #Resize + torch + transpose to our + transform = T.Resize(size = (256,256)) + inp = transform(torch.from_numpy(image.transpose((2, 0, 1))).float()) + + inp = inp.to(self.device) inp.div_(255.0).unsqueeze_(0) + # inp.shape -> torch.Size([1, 3, 256, 256]) + logger.warning("FACE ALIGNMENT NET!!!") out = self.face_alignment_net(inp).detach() if self.flip_input: out += flip(self.face_alignment_net(flip(inp)).detach(), is_label=True) out = out.cpu().numpy() + # Out Face Alignment + logger.warning("AFTER FACE ALIGNMENT!!!") + logger.info(f'FA_NET output type: {type(out)} and shape: {out.shape}') + logger.error(f'SAVE HEATMAP IMAGE!!!') + #for i in range(len(out[0])): + fig = plt.figure(figsize=plt.figaspect(.5)) + plt.imshow(out[0][0]) + output_path = os.path.join('/Users/crisalix/Desktop/test/', 'image_hm' + str(0) + '.jpg') + plt.savefig(output_path, subsampling=0, quality=95) + plt.close(fig) + + ''' pts, pts_img, scores = get_preds_fromhm(out, center.numpy(), scale) pts, pts_img = torch.from_numpy(pts), torch.from_numpy(pts_img) - pts, pts_img = pts.view(68, 2) * 4, pts_img.view(68, 2) + pts, pts_img = pts.view(68, 2) * 4 , pts_img.view(68, 2) + ''' + + # New option, not using scale nor center values + pts, pts_img, scores = get_preds_fromhm(out) + pts, pts_img = torch.from_numpy(pts), torch.from_numpy(pts_img) + pts, pts_img = pts.view(68, 2) * 5.59375 , pts.view(68, 2) * 5.59375 + scores = scores.squeeze(0) + logger.warning("AFTER GET PREDS FROM HM!!!") + logger.info(f'POINTS PREDS -> pts_img size: {pts_img.shape}') + + logger.error(f'SAVE IMAGE AFTER FA!!!') + fig = plt.figure(figsize=plt.figaspect(.5)) + + ''' + transform = T.Compose([ + T.ToPILImage(), + T.Resize(size = (256,256)) + ]) + pts_image = transform(image) ''' + + plt.imshow(image) # pts_image + plt.scatter(pts[:, 0], pts[:, 1], marker="o", color="red", s=2) #pts_img + output_path = os.path.join('/Users/crisalix/Desktop/test/image_after_FA.jpg') + plt.savefig(output_path, subsampling=0, quality=95) + plt.close(fig) + if self.landmarks_type == LandmarksType._3D: + logger.warning("LANDMARKS TYPE 3D!!!") heatmaps = np.zeros((68, 256, 256), dtype=np.float32) for i in range(68): if pts[i, 0] > 0 and pts[i, 1] > 0: heatmaps[i] = draw_gaussian( heatmaps[i], pts[i], 2) + logger.info(f'Heatmaps 2 info {heatmaps.shape}') + + logger.error(f'SAVE HEATMAP 2 IMAGE!!!') + fig = plt.figure(figsize=plt.figaspect(.5)) + plt.imshow(heatmaps[0]) + output_path = os.path.join('/Users/crisalix/Desktop/test/', 'image_hm' + str(2) + '.jpg') + plt.savefig(output_path, subsampling=0, quality=95) + plt.close(fig) + heatmaps = torch.from_numpy( heatmaps).unsqueeze_(0) + logger.info(f'Heatmap size: {heatmaps.shape}') + logger.warning("DEPTH PREDICTION!!!") heatmaps = heatmaps.to(self.device) depth_pred = self.depth_prediciton_net( torch.cat((inp, heatmaps), 1)).data.cpu().view(68, 1) + logger.info(f'Output depth predictor: {depth_pred.shape}') pts_img = torch.cat( - (pts_img, depth_pred * (1.0 / (256.0 / (200.0 * scale)))), 1) + (pts_img, depth_pred * (1.0 / (256.0 / (200.0 * scale)))), 1) #Understand depth_pred modification!!! + logger.info(f'Last output: {pts_img.shape}') + logger.info(f'Last output: {pts_img}') landmarks.append(pts_img.numpy()) landmarks_scores.append(scores) + + logger.print('---------------------------------------') if not return_bboxes: detected_faces = None diff --git a/face_alignment/utils.py b/face_alignment/utils.py index 2618770..8e18611 100644 --- a/face_alignment/utils.py +++ b/face_alignment/utils.py @@ -1,3 +1,5 @@ +from core_lib.utilities import logger + import os import sys import errno @@ -196,6 +198,7 @@ def get_preds_fromhm(hm, center=None, scale=None): """ B, C, H, W = hm.shape hm_reshape = hm.reshape(B, C, H * W) + logger.info(f'HM shape: {hm_reshape.shape}') idx = np.argmax(hm_reshape, axis=-1) scores = np.take_along_axis(hm_reshape, np.expand_dims(idx, axis=-1), axis=-1).squeeze(-1) preds, preds_orig = _get_preds_fromhm(hm, idx, center, scale) From 7110832cff251343070308fceafa744ad3d74190 Mon Sep 17 00:00:00 2001 From: cristinapunti Date: Wed, 16 Nov 2022 11:29:46 +0100 Subject: [PATCH 02/13] small change --- face_alignment/api.py | 1 - 1 file changed, 1 deletion(-) diff --git a/face_alignment/api.py b/face_alignment/api.py index 49f289c..73877ad 100644 --- a/face_alignment/api.py +++ b/face_alignment/api.py @@ -275,7 +275,6 @@ def get_landmarks_from_image(self, image_or_path, detected_faces=None, return_bb (pts_img, depth_pred * (1.0 / (256.0 / (200.0 * scale)))), 1) #Understand depth_pred modification!!! logger.info(f'Last output: {pts_img.shape}') - logger.info(f'Last output: {pts_img}') landmarks.append(pts_img.numpy()) landmarks_scores.append(scores) From 05199e1b1b32c1f8436109c6d1a3cbdadb778273 Mon Sep 17 00:00:00 2001 From: cristinapunti Date: Mon, 21 Nov 2022 12:12:03 +0100 Subject: [PATCH 03/13] Clean code --- face_alignment/api.py | 108 +++------------------------------------- face_alignment/utils.py | 1 - 2 files changed, 7 insertions(+), 102 deletions(-) diff --git a/face_alignment/api.py b/face_alignment/api.py index 73877ad..89d3cb5 100644 --- a/face_alignment/api.py +++ b/face_alignment/api.py @@ -123,22 +123,15 @@ def get_landmarks_from_image(self, image_or_path, detected_faces=None, return_bb """ image = get_image(image_or_path) - start = time.time() - + # Input image size ht = image.shape[0] wd = image.shape[1] # Force detected faces to be OUR bounding boxes - detected_faces=[np.array([1.0, np.float(ht-1), np.float(wd-1), 1.0])] - #print(f'detected_faces: {detected_faces}') - logger.info(f'Landmark detector input image size: {ht} x {wd}') + detected_faces=[np.array([0.0, np.float(ht), np.float(wd), 0.0])] if detected_faces is None: detected_faces = self.face_detector.detect_from_image(image.copy()) - - final = time.time() - logger.warning(f'Execution time for detected_faces: {final-start} seconds! ') - logger.warning(f'{len(detected_faces)} Face(s) Detected!') if len(detected_faces) == 0: warnings.warn("No faces were detected.") @@ -149,137 +142,50 @@ def get_landmarks_from_image(self, image_or_path, detected_faces=None, return_bb landmarks = [] landmarks_scores = [] - for i, d in enumerate(detected_faces): - logger.info(f'Bounding Box for face detected is {d}') - + for i, d in enumerate(detected_faces): center = torch.tensor( [d[2] - (d[2] - d[0]) / 2.0, d[3] - (d[3] - d[1]) / 2.0]) - center[1] = center[1] - (d[3] - d[1]) * 0.12 # PERQUE?? NO ES FA SERVIR MES! + center[1] = center[1] - (d[3] - d[1]) * 0.12 scale = (d[2] - d[0] + d[3] - d[1]) / self.face_detector.reference_scale - #scale = 2 #??????? - logger.warning('FACE ALIGNMENT') - logger.info(f'Input image: {(image).shape}') - logger.info(f'Extra information: Center {center}, Scale value {scale} // Reference scale {self.face_detector.reference_scale}') - - # image shape -> Size([358, 358, 3]) - - # Save image - im = Image.fromarray(image) - logger.error("SAVE INPUT IMAGE!!!") - output_path = os.path.join('/Users/crisalix/Desktop/test/image.jpg') - im.save(output_path) - - ''' - logger.warning('CROP') - # Crop taking into account center and scale --> Crop + Resize - inp = crop(image, center, scale) - logger.info(f'Shape after crop {inp.shape}') - # inp.shape -> Size([256, 256, 3]) - - # Save crop - logger.error("SAVE CROPPED IMAGE!!!") - inp_arr = Image.fromarray(inp) - output_path = os.path.join('/Users/crisalix/Desktop/test/image_2.jpg') - inp_arr.save(output_path) - - # Transpose and torch! - inp = torch.from_numpy(inp.transpose((2, 0, 1))).float() - # inp.shape -> torch.Size([3, 256, 256]) - - ''' - - #Resize + torch + transpose to our transform = T.Resize(size = (256,256)) inp = transform(torch.from_numpy(image.transpose((2, 0, 1))).float()) inp = inp.to(self.device) inp.div_(255.0).unsqueeze_(0) - # inp.shape -> torch.Size([1, 3, 256, 256]) - logger.warning("FACE ALIGNMENT NET!!!") out = self.face_alignment_net(inp).detach() if self.flip_input: out += flip(self.face_alignment_net(flip(inp)).detach(), is_label=True) out = out.cpu().numpy() - # Out Face Alignment - logger.warning("AFTER FACE ALIGNMENT!!!") - logger.info(f'FA_NET output type: {type(out)} and shape: {out.shape}') - logger.error(f'SAVE HEATMAP IMAGE!!!') - #for i in range(len(out[0])): - fig = plt.figure(figsize=plt.figaspect(.5)) - plt.imshow(out[0][0]) - output_path = os.path.join('/Users/crisalix/Desktop/test/', 'image_hm' + str(0) + '.jpg') - plt.savefig(output_path, subsampling=0, quality=95) - plt.close(fig) - - ''' - pts, pts_img, scores = get_preds_fromhm(out, center.numpy(), scale) - pts, pts_img = torch.from_numpy(pts), torch.from_numpy(pts_img) - pts, pts_img = pts.view(68, 2) * 4 , pts_img.view(68, 2) - ''' - # New option, not using scale nor center values pts, pts_img, scores = get_preds_fromhm(out) pts, pts_img = torch.from_numpy(pts), torch.from_numpy(pts_img) - pts, pts_img = pts.view(68, 2) * 5.59375 , pts.view(68, 2) * 5.59375 + resize_scale = image.shape[1]/out.shape[2] #(358/64) + pts, pts_img = pts.view(68, 2) * resize_scale, pts.view(68, 2) * resize_scale scores = scores.squeeze(0) - logger.warning("AFTER GET PREDS FROM HM!!!") - logger.info(f'POINTS PREDS -> pts_img size: {pts_img.shape}') - - logger.error(f'SAVE IMAGE AFTER FA!!!') - fig = plt.figure(figsize=plt.figaspect(.5)) - - ''' - transform = T.Compose([ - T.ToPILImage(), - T.Resize(size = (256,256)) - ]) - pts_image = transform(image) ''' - - plt.imshow(image) # pts_image - plt.scatter(pts[:, 0], pts[:, 1], marker="o", color="red", s=2) #pts_img - output_path = os.path.join('/Users/crisalix/Desktop/test/image_after_FA.jpg') - plt.savefig(output_path, subsampling=0, quality=95) - plt.close(fig) - if self.landmarks_type == LandmarksType._3D: - logger.warning("LANDMARKS TYPE 3D!!!") heatmaps = np.zeros((68, 256, 256), dtype=np.float32) for i in range(68): if pts[i, 0] > 0 and pts[i, 1] > 0: heatmaps[i] = draw_gaussian( heatmaps[i], pts[i], 2) - logger.info(f'Heatmaps 2 info {heatmaps.shape}') - - logger.error(f'SAVE HEATMAP 2 IMAGE!!!') - fig = plt.figure(figsize=plt.figaspect(.5)) - plt.imshow(heatmaps[0]) - output_path = os.path.join('/Users/crisalix/Desktop/test/', 'image_hm' + str(2) + '.jpg') - plt.savefig(output_path, subsampling=0, quality=95) - plt.close(fig) heatmaps = torch.from_numpy( heatmaps).unsqueeze_(0) - logger.info(f'Heatmap size: {heatmaps.shape}') - logger.warning("DEPTH PREDICTION!!!") heatmaps = heatmaps.to(self.device) depth_pred = self.depth_prediciton_net( torch.cat((inp, heatmaps), 1)).data.cpu().view(68, 1) - logger.info(f'Output depth predictor: {depth_pred.shape}') pts_img = torch.cat( - (pts_img, depth_pred * (1.0 / (256.0 / (200.0 * scale)))), 1) #Understand depth_pred modification!!! + (pts_img, depth_pred * (1.0 / (256.0 / (200.0 * scale)))), 1) - logger.info(f'Last output: {pts_img.shape}') landmarks.append(pts_img.numpy()) landmarks_scores.append(scores) - logger.print('---------------------------------------') - if not return_bboxes: detected_faces = None if not return_landmark_score: diff --git a/face_alignment/utils.py b/face_alignment/utils.py index 8e18611..0256af9 100644 --- a/face_alignment/utils.py +++ b/face_alignment/utils.py @@ -198,7 +198,6 @@ def get_preds_fromhm(hm, center=None, scale=None): """ B, C, H, W = hm.shape hm_reshape = hm.reshape(B, C, H * W) - logger.info(f'HM shape: {hm_reshape.shape}') idx = np.argmax(hm_reshape, axis=-1) scores = np.take_along_axis(hm_reshape, np.expand_dims(idx, axis=-1), axis=-1).squeeze(-1) preds, preds_orig = _get_preds_fromhm(hm, idx, center, scale) From 6ef25cfd350cdcb9fbb374995d116271fb8dfe53 Mon Sep 17 00:00:00 2001 From: cristinapunti Date: Wed, 23 Nov 2022 12:33:14 +0100 Subject: [PATCH 04/13] update using initial code + reverse scale --- face_alignment/api.py | 54 +++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 33 deletions(-) diff --git a/face_alignment/api.py b/face_alignment/api.py index 89d3cb5..b213b3e 100644 --- a/face_alignment/api.py +++ b/face_alignment/api.py @@ -1,10 +1,3 @@ -import time -import matplotlib.pyplot as plt -from PIL import Image -import cv2 - -import torchvision.transforms as T - import torch import warnings from enum import IntEnum @@ -12,8 +5,6 @@ from .utils import * -from core_lib.utilities import logger - class LandmarksType(IntEnum): """Enum class defining the type of landmarks to detect. @@ -35,8 +26,8 @@ class NetworkSize(IntEnum): class FaceAlignment: - def __init__(self, landmarks_type, face_align_model_path, depth_pred_model_path, network_size=NetworkSize.LARGE, - device='cuda', flip_input=False, face_detector='sfd', face_detector_kwargs=None, verbose=False): + def __init__(self, landmarks_type, face_align_model_path, depth_pred_model_path=None, network_size=NetworkSize.LARGE, + device='cuda', flip_input=False, face_detector=None, face_detector_kwargs=None, verbose=False): self.device = device self.flip_input = flip_input self.landmarks_type = landmarks_type @@ -59,10 +50,13 @@ def __init__(self, landmarks_type, face_align_model_path, depth_pred_model_path, torch.backends.cudnn.benchmark = True # Get the face detector - face_detector_module = __import__('face_alignment.detection.' + face_detector, - globals(), locals(), [face_detector], 0) - face_detector_kwargs = face_detector_kwargs or {} - self.face_detector = face_detector_module.FaceDetector(device=device, verbose=verbose, **face_detector_kwargs) + if face_detector: + face_detector_module = __import__('face_alignment.detection.' + face_detector, + globals(), locals(), [face_detector], 0) + face_detector_kwargs = face_detector_kwargs or {} + self.face_detector = face_detector_module.FaceDetector(device=device, verbose=verbose, **face_detector_kwargs) + else: + self.face_detector = None # Initialise the face alignemnt networks if landmarks_type == LandmarksType._2D: @@ -123,13 +117,6 @@ def get_landmarks_from_image(self, image_or_path, detected_faces=None, return_bb """ image = get_image(image_or_path) - # Input image size - ht = image.shape[0] - wd = image.shape[1] - - # Force detected faces to be OUR bounding boxes - detected_faces=[np.array([0.0, np.float(ht), np.float(wd), 0.0])] - if detected_faces is None: detected_faces = self.face_detector.detect_from_image(image.copy()) @@ -142,16 +129,20 @@ def get_landmarks_from_image(self, image_or_path, detected_faces=None, return_bb landmarks = [] landmarks_scores = [] - for i, d in enumerate(detected_faces): + for i, d in enumerate(detected_faces): center = torch.tensor( [d[2] - (d[2] - d[0]) / 2.0, d[3] - (d[3] - d[1]) / 2.0]) - center[1] = center[1] - (d[3] - d[1]) * 0.12 - scale = (d[2] - d[0] + d[3] - d[1]) / self.face_detector.reference_scale + if self.face_detector: + center[1] = center[1] - (d[3] - d[1]) * 0.12 + scale = (d[2] - d[0] + d[3] - d[1]) / self.face_detector.reference_scale + else: + scale = (d[2]-d[0])/200 - transform = T.Resize(size = (256,256)) - inp = transform(torch.from_numpy(image.transpose((2, 0, 1))).float()) + inp = crop(image, center, scale) + inp = torch.from_numpy(inp.transpose( + (2, 0, 1))).float() - inp = inp.to(self.device) + inp = inp.to(self.device) inp.div_(255.0).unsqueeze_(0) out = self.face_alignment_net(inp).detach() @@ -159,12 +150,9 @@ def get_landmarks_from_image(self, image_or_path, detected_faces=None, return_bb out += flip(self.face_alignment_net(flip(inp)).detach(), is_label=True) out = out.cpu().numpy() - # New option, not using scale nor center values - pts, pts_img, scores = get_preds_fromhm(out) + pts, pts_img, scores = get_preds_fromhm(out, center.numpy(), scale) pts, pts_img = torch.from_numpy(pts), torch.from_numpy(pts_img) - resize_scale = image.shape[1]/out.shape[2] #(358/64) - pts, pts_img = pts.view(68, 2) * resize_scale, pts.view(68, 2) * resize_scale - + pts, pts_img = pts.view(68, 2) * 4, pts_img.view(68, 2) scores = scores.squeeze(0) if self.landmarks_type == LandmarksType._3D: From 266b87b2d14c7544f4b7690d48c82358d261e996 Mon Sep 17 00:00:00 2001 From: cristinapunti Date: Wed, 23 Nov 2022 14:57:36 +0100 Subject: [PATCH 05/13] error when face_detector not provided --- face_alignment/api.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/face_alignment/api.py b/face_alignment/api.py index b213b3e..249a07a 100644 --- a/face_alignment/api.py +++ b/face_alignment/api.py @@ -116,9 +116,11 @@ def get_landmarks_from_image(self, image_or_path, detected_faces=None, return_bb (landmark, landmark_score, None ) """ image = get_image(image_or_path) - - if detected_faces is None: + detected_faces = None + try: detected_faces = self.face_detector.detect_from_image(image.copy()) + except: + raise Exception(f"A list of bounding boxes or a face_detector method is needed.") if len(detected_faces) == 0: warnings.warn("No faces were detected.") @@ -209,7 +211,6 @@ def get_landmarks_from_batch(self, image_batch, detected_faces=None, return_bbox (landmark, None, detected_face) (landmark, landmark_score, None ) """ - if detected_faces is None: detected_faces = self.face_detector.detect_from_batch(image_batch) From d864724aed0be1312c21f9d0604d9962cc4772ac Mon Sep 17 00:00:00 2001 From: cristinapunti Date: Wed, 23 Nov 2022 15:00:45 +0100 Subject: [PATCH 06/13] remove logger --- face_alignment/utils.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/face_alignment/utils.py b/face_alignment/utils.py index 0256af9..2618770 100644 --- a/face_alignment/utils.py +++ b/face_alignment/utils.py @@ -1,5 +1,3 @@ -from core_lib.utilities import logger - import os import sys import errno From 89075ffc74a15bd8ee122080f8e5818ab7411ea6 Mon Sep 17 00:00:00 2001 From: cristinapunti Date: Wed, 23 Nov 2022 15:11:49 +0100 Subject: [PATCH 07/13] delete forced error --- face_alignment/api.py | 1 - 1 file changed, 1 deletion(-) diff --git a/face_alignment/api.py b/face_alignment/api.py index 249a07a..fabbfbb 100644 --- a/face_alignment/api.py +++ b/face_alignment/api.py @@ -116,7 +116,6 @@ def get_landmarks_from_image(self, image_or_path, detected_faces=None, return_bb (landmark, landmark_score, None ) """ image = get_image(image_or_path) - detected_faces = None try: detected_faces = self.face_detector.detect_from_image(image.copy()) except: From d30268720c1ed90b15c3244d67b5f545c158db59 Mon Sep 17 00:00:00 2001 From: cristinapunti Date: Wed, 23 Nov 2022 15:19:05 +0100 Subject: [PATCH 08/13] minor error --- face_alignment/api.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/face_alignment/api.py b/face_alignment/api.py index fabbfbb..4436184 100644 --- a/face_alignment/api.py +++ b/face_alignment/api.py @@ -116,10 +116,12 @@ def get_landmarks_from_image(self, image_or_path, detected_faces=None, return_bb (landmark, landmark_score, None ) """ image = get_image(image_or_path) - try: - detected_faces = self.face_detector.detect_from_image(image.copy()) - except: - raise Exception(f"A list of bounding boxes or a face_detector method is needed.") + + if detected_faces is None: + try: + detected_faces = self.face_detector.detect_from_image(image.copy()) + except: + raise Exception(f"A list of bounding boxes or a face_detector method is needed.") if len(detected_faces) == 0: warnings.warn("No faces were detected.") @@ -210,6 +212,7 @@ def get_landmarks_from_batch(self, image_batch, detected_faces=None, return_bbox (landmark, None, detected_face) (landmark, landmark_score, None ) """ + if detected_faces is None: detected_faces = self.face_detector.detect_from_batch(image_batch) From f7c8361a0a22f7f686e09255f39e5f68e9bf3bee Mon Sep 17 00:00:00 2001 From: cristinapunti Date: Thu, 24 Nov 2022 10:20:46 +0100 Subject: [PATCH 09/13] check time --- face_alignment/api.py | 13 +++++++++++-- face_alignment/utils.py | 4 +--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/face_alignment/api.py b/face_alignment/api.py index 4436184..1058f81 100644 --- a/face_alignment/api.py +++ b/face_alignment/api.py @@ -3,6 +3,9 @@ from enum import IntEnum from distutils.version import LooseVersion +import time +from core_lib.utilities import logger + from .utils import * class LandmarksType(IntEnum): @@ -116,7 +119,7 @@ def get_landmarks_from_image(self, image_or_path, detected_faces=None, return_bb (landmark, landmark_score, None ) """ image = get_image(image_or_path) - + if detected_faces is None: try: detected_faces = self.face_detector.detect_from_image(image.copy()) @@ -148,15 +151,21 @@ def get_landmarks_from_image(self, image_or_path, detected_faces=None, return_bb inp = inp.to(self.device) inp.div_(255.0).unsqueeze_(0) + start = time.time() out = self.face_alignment_net(inp).detach() if self.flip_input: out += flip(self.face_alignment_net(flip(inp)).detach(), is_label=True) out = out.cpu().numpy() - + final = time.time() + logger.info(f'Total time model inference: {final-start}') + + start_hm = time.time() pts, pts_img, scores = get_preds_fromhm(out, center.numpy(), scale) pts, pts_img = torch.from_numpy(pts), torch.from_numpy(pts_img) pts, pts_img = pts.view(68, 2) * 4, pts_img.view(68, 2) scores = scores.squeeze(0) + final_hm = time.time() + logger.info(f'Total time predictions from hm: {final_hm-start_hm}') if self.landmarks_type == LandmarksType._3D: heatmaps = np.zeros((68, 256, 256), dtype=np.float32) diff --git a/face_alignment/utils.py b/face_alignment/utils.py index 2618770..ee88791 100644 --- a/face_alignment/utils.py +++ b/face_alignment/utils.py @@ -145,7 +145,6 @@ def crop(image, center, scale, resolution=256.0): return newImg -@jit(nopython=True) def transform_np(point, center, scale, resolution, invert=False): """Generate and affine transformation matrix. @@ -203,7 +202,6 @@ def get_preds_fromhm(hm, center=None, scale=None): return preds, preds_orig, scores -@jit(nopython=True) def _get_preds_fromhm(hm, idx, center=None, scale=None): """Obtain (x,y) coordinates given a set of N heatmaps and the coresponding locations of the maximums. If the center @@ -234,7 +232,7 @@ def _get_preds_fromhm(hm, idx, center=None, scale=None): preds[i, j] += np.sign(diff) * 0.25 preds -= 0.5 - + preds_orig = np.zeros_like(preds) if center is not None and scale is not None: for i in range(B): From 1d83810f130ac498f3c494b00b921d34e9e307a8 Mon Sep 17 00:00:00 2001 From: cristinapunti Date: Fri, 25 Nov 2022 09:53:12 +0100 Subject: [PATCH 10/13] disable graph_executor_optimize before inference --- face_alignment/api.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/face_alignment/api.py b/face_alignment/api.py index 1058f81..044f370 100644 --- a/face_alignment/api.py +++ b/face_alignment/api.py @@ -151,6 +151,7 @@ def get_landmarks_from_image(self, image_or_path, detected_faces=None, return_bb inp = inp.to(self.device) inp.div_(255.0).unsqueeze_(0) + torch._C._set_graph_executor_optimize(False) start = time.time() out = self.face_alignment_net(inp).detach() if self.flip_input: @@ -158,14 +159,12 @@ def get_landmarks_from_image(self, image_or_path, detected_faces=None, return_bb out = out.cpu().numpy() final = time.time() logger.info(f'Total time model inference: {final-start}') - - start_hm = time.time() + torch._C._set_graph_executor_optimize(True) + pts, pts_img, scores = get_preds_fromhm(out, center.numpy(), scale) pts, pts_img = torch.from_numpy(pts), torch.from_numpy(pts_img) pts, pts_img = pts.view(68, 2) * 4, pts_img.view(68, 2) scores = scores.squeeze(0) - final_hm = time.time() - logger.info(f'Total time predictions from hm: {final_hm-start_hm}') if self.landmarks_type == LandmarksType._3D: heatmaps = np.zeros((68, 256, 256), dtype=np.float32) From 41fab9dd716fdad1c0d88823da61f8d0218b0590 Mon Sep 17 00:00:00 2001 From: cristinapunti Date: Fri, 25 Nov 2022 10:41:47 +0100 Subject: [PATCH 11/13] delete time checkers --- face_alignment/api.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/face_alignment/api.py b/face_alignment/api.py index 044f370..cae5f63 100644 --- a/face_alignment/api.py +++ b/face_alignment/api.py @@ -3,9 +3,6 @@ from enum import IntEnum from distutils.version import LooseVersion -import time -from core_lib.utilities import logger - from .utils import * class LandmarksType(IntEnum): @@ -152,13 +149,10 @@ def get_landmarks_from_image(self, image_or_path, detected_faces=None, return_bb inp.div_(255.0).unsqueeze_(0) torch._C._set_graph_executor_optimize(False) - start = time.time() out = self.face_alignment_net(inp).detach() if self.flip_input: out += flip(self.face_alignment_net(flip(inp)).detach(), is_label=True) out = out.cpu().numpy() - final = time.time() - logger.info(f'Total time model inference: {final-start}') torch._C._set_graph_executor_optimize(True) pts, pts_img, scores = get_preds_fromhm(out, center.numpy(), scale) From 3aa20f6b22b8dfb3c979be862a06f27cc6846fb6 Mon Sep 17 00:00:00 2001 From: cristinapunti Date: Tue, 29 Nov 2022 10:01:25 +0100 Subject: [PATCH 12/13] add comments --- face_alignment/api.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/face_alignment/api.py b/face_alignment/api.py index cae5f63..d03f3cc 100644 --- a/face_alignment/api.py +++ b/face_alignment/api.py @@ -139,6 +139,7 @@ def get_landmarks_from_image(self, image_or_path, detected_faces=None, return_bb center[1] = center[1] - (d[3] - d[1]) * 0.12 scale = (d[2] - d[0] + d[3] - d[1]) / self.face_detector.reference_scale else: + # Everywhere the variable scale is multiplied by 200 for no reason, if we divide here by 200 it works scale = (d[2]-d[0])/200 inp = crop(image, center, scale) @@ -148,6 +149,7 @@ def get_landmarks_from_image(self, image_or_path, detected_faces=None, return_bb inp = inp.to(self.device) inp.div_(255.0).unsqueeze_(0) + # Disabling optimizations: https://github.com/pytorch/pytorch/blob/master/torch/csrc/jit/OVERVIEW.md#disabling-optimizations torch._C._set_graph_executor_optimize(False) out = self.face_alignment_net(inp).detach() if self.flip_input: From 349ceeb1f8840fb23b1685260d71bb674ea6f440 Mon Sep 17 00:00:00 2001 From: gilTriginer Date: Mon, 5 Dec 2022 13:01:40 +0100 Subject: [PATCH 13/13] Hardcode high version --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 48bf9e3..ae98e4b 100644 --- a/setup.py +++ b/setup.py @@ -33,8 +33,8 @@ def find_version(*file_paths): with open(path.join(here, 'README.md'), encoding='utf-8') as readme_file: long_description = readme_file.read() -VERSION = find_version('face_alignment', '__init__.py') - +# VERSION = find_version('face_alignment', '__init__.py') +VERSION = '2.0.0' #TODO Remove hardcoded value requirements = [ 'torch', 'numpy',