From 4713572a24fd909014404e979337b8e3d295f387 Mon Sep 17 00:00:00 2001 From: Andrea Lanfranchi Date: Wed, 21 Feb 2024 15:12:51 +0100 Subject: [PATCH 01/10] Amend incompatible assignement warning --- deepface/modules/detection.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/deepface/modules/detection.py b/deepface/modules/detection.py index 1e96b05..fc9ef6c 100644 --- a/deepface/modules/detection.py +++ b/deepface/modules/detection.py @@ -210,6 +210,5 @@ def align_face( return img, 0 angle = float(np.degrees(np.arctan2(right_eye[1] - left_eye[1], right_eye[0] - left_eye[0]))) - img = Image.fromarray(img) - img = np.array(img.rotate(angle)) + img = np.array(Image.fromarray(img).rotate(angle)) return img, angle From adf6328cd9246bd33ec20bc526d8d11a5e734493 Mon Sep 17 00:00:00 2001 From: Andrea Lanfranchi Date: Wed, 21 Feb 2024 15:14:01 +0100 Subject: [PATCH 02/10] Look for string in string collection --- deepface/modules/modeling.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deepface/modules/modeling.py b/deepface/modules/modeling.py index f9c6464..271fc25 100644 --- a/deepface/modules/modeling.py +++ b/deepface/modules/modeling.py @@ -40,7 +40,7 @@ def build_model(model_name: str) -> Any: if not "model_obj" in globals(): model_obj = {} - if not model_name in model_obj: + if not model_name in model_obj.keys(): model = models.get(model_name) if model: model = model() From 810dfac4feeaf473a2f1275702a6d0609f753d46 Mon Sep 17 00:00:00 2001 From: Andrea Lanfranchi Date: Wed, 21 Feb 2024 15:18:51 +0100 Subject: [PATCH 03/10] Simplify model initialization --- deepface/modules/modeling.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/deepface/modules/modeling.py b/deepface/modules/modeling.py index 271fc25..8cd603c 100644 --- a/deepface/modules/modeling.py +++ b/deepface/modules/modeling.py @@ -43,8 +43,7 @@ def build_model(model_name: str) -> Any: if not model_name in model_obj.keys(): model = models.get(model_name) if model: - model = model() - model_obj[model_name] = model + model_obj[model_name] = model() else: raise ValueError(f"Invalid model_name passed - {model_name}") From 051a8d317270b32aa7f4f00dfca88792819512ed Mon Sep 17 00:00:00 2001 From: Andrea Lanfranchi Date: Wed, 21 Feb 2024 15:56:47 +0100 Subject: [PATCH 04/10] Use return boolean to detect effective capture Actually an image is always returned but empty --- deepface/modules/realtime.py | 51 +++++++++++++++++------------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/deepface/modules/realtime.py b/deepface/modules/realtime.py index b87377f..94b2d1e 100644 --- a/deepface/modules/realtime.py +++ b/deepface/modules/realtime.py @@ -68,9 +68,8 @@ def analysis( cap = cv2.VideoCapture(source) # webcam while True: - _, img = cap.read() - - if img is None: + has_frame, img = cap.read() + if not has_frame: break # cv2.namedWindow('img', cv2.WINDOW_FREERATIO) @@ -111,36 +110,34 @@ def analysis( detected_faces = [] face_index = 0 for x, y, w, h in faces: - if w > 130: # discard small detected faces + if w <= 130: # discard small detected faces + continue + face_detected = True + if face_index == 0: + face_included_frames += 1 # increase frame for a single face - face_detected = True - if face_index == 0: - face_included_frames = ( - face_included_frames + 1 - ) # increase frame for a single face + cv2.rectangle( + img, (x, y), (x + w, y + h), (67, 67, 67), 1 + ) # draw rectangle to main image - cv2.rectangle( - img, (x, y), (x + w, y + h), (67, 67, 67), 1 - ) # draw rectangle to main image + cv2.putText( + img, + str(frame_threshold - face_included_frames), + (int(x + w / 4), int(y + h / 1.5)), + cv2.FONT_HERSHEY_SIMPLEX, + 4, + (255, 255, 255), + 2, + ) - cv2.putText( - img, - str(frame_threshold - face_included_frames), - (int(x + w / 4), int(y + h / 1.5)), - cv2.FONT_HERSHEY_SIMPLEX, - 4, - (255, 255, 255), - 2, - ) + detected_face = img[int(y) : int(y + h), int(x) : int(x + w)] # crop detected face - detected_face = img[int(y) : int(y + h), int(x) : int(x + w)] # crop detected face + # ------------------------------------- - # ------------------------------------- + detected_faces.append((x, y, w, h)) + face_index = face_index + 1 - detected_faces.append((x, y, w, h)) - face_index = face_index + 1 - - # ------------------------------------- + # ------------------------------------- if face_detected == True and face_included_frames == frame_threshold and freeze == False: freeze = True From c4b48ce46f2e508b36dbd6d78dd425a9a1cd5cb0 Mon Sep 17 00:00:00 2001 From: Andrea Lanfranchi Date: Wed, 21 Feb 2024 16:28:07 +0100 Subject: [PATCH 05/10] Early discard extracted faces below threshold --- deepface/modules/realtime.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deepface/modules/realtime.py b/deepface/modules/realtime.py index 94b2d1e..8abbda8 100644 --- a/deepface/modules/realtime.py +++ b/deepface/modules/realtime.py @@ -91,6 +91,8 @@ def analysis( faces = [] for face_obj in face_objs: facial_area = face_obj["facial_area"] + if facial_area["w"] <= 130: # discard small detected faces + continue faces.append( ( facial_area["x"], @@ -110,8 +112,6 @@ def analysis( detected_faces = [] face_index = 0 for x, y, w, h in faces: - if w <= 130: # discard small detected faces - continue face_detected = True if face_index == 0: face_included_frames += 1 # increase frame for a single face From 72e5669302cbbbaa4c91ed84151ccc684f508dc2 Mon Sep 17 00:00:00 2001 From: Andrea Lanfranchi Date: Wed, 21 Feb 2024 19:18:01 +0100 Subject: [PATCH 06/10] Use path join and amend undetected faces addition repetition --- deepface/modules/recognition.py | 65 ++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/deepface/modules/recognition.py b/deepface/modules/recognition.py index b771e14..8cd2ed4 100644 --- a/deepface/modules/recognition.py +++ b/deepface/modules/recognition.py @@ -99,7 +99,7 @@ def find( file_name = f"representations_{model_name}.pkl" file_name = file_name.replace("-", "_").lower() - datastore_path = f"{db_path}/{file_name}" + datastore_path = os.path.join(db_path, file_name) df_cols = [ "identity", @@ -162,7 +162,7 @@ def find( logger.info( f"{len(newbies)} new representations are just added" f" whereas {len(oldies)} represented one(s) are just dropped" - f" in {db_path}/{file_name} file." + f" in {os.path.join(db_path,file_name)} file." ) if not silent: @@ -173,8 +173,8 @@ def find( if len(employees) == 0: raise ValueError( - f"There is no image in {db_path} folder!" - "Validate .jpg, .jpeg or .png files exist in this path.", + f"Could not find any valid image in {db_path} folder!" + "Valid images are .jpg, .jpeg or .png files.", ) # ------------------------ @@ -196,7 +196,7 @@ def find( pickle.dump(representations, f) if not silent: - logger.info(f"Representations stored in {db_path}/{file_name} file.") + logger.info(f"Representations stored in {datastore_path} file.") # ---------------------------- # now, we got representations for facial database @@ -241,6 +241,9 @@ def find( distances = [] for _, instance in df.iterrows(): source_representation = instance[f"{model_name}_representation"] + if source_representation is None: + distances.append(float("inf")) # no representation for this image + continue target_dims = len(list(target_representation)) source_dims = len(list(source_representation)) @@ -292,7 +295,7 @@ def find( return resp_obj -def __list_images(path: str) -> list: +def __list_images(path: str) -> list[str]: """ List images in a given path Args: @@ -304,7 +307,7 @@ def __list_images(path: str) -> list: for r, _, f in os.walk(path): for file in f: if file.lower().endswith((".jpg", ".jpeg", ".png")): - exact_path = f"{r}/{file}" + exact_path = os.path.join(r, file) images.append(exact_path) return images @@ -365,31 +368,35 @@ def __find_bulk_embeddings( expand_percentage=expand_percentage, ) except ValueError as err: - logger.warn( - f"Exception while extracting faces from {employee}: {str(err)}. Skipping it." + logger.error( + f"Exception while extracting faces from {employee}: {str(err)}" ) img_objs = [] - for img_obj in img_objs: - img_content = img_obj["face"] - img_region = img_obj["facial_area"] - embedding_obj = representation.represent( - img_path=img_content, - model_name=model_name, - enforce_detection=enforce_detection, - detector_backend="skip", - align=align, - normalization=normalization, - ) + if len(img_objs) == 0: + logger.warn(f"No face detected in {employee}. It will be skipped in detection.") + representations.append((employee, None, 0, 0, 0, 0)) + else: + for img_obj in img_objs: + img_content = img_obj["face"] + img_region = img_obj["facial_area"] + embedding_obj = representation.represent( + img_path=img_content, + model_name=model_name, + enforce_detection=enforce_detection, + detector_backend="skip", + align=align, + normalization=normalization, + ) - img_representation = embedding_obj[0]["embedding"] + img_representation = embedding_obj[0]["embedding"] + representations.append(( + employee, + img_representation, + img_region["x"], + img_region["y"], + img_region["w"], + img_region["h"] + )) - instance = [] - instance.append(employee) - instance.append(img_representation) - instance.append(img_region["x"]) - instance.append(img_region["y"]) - instance.append(img_region["w"]) - instance.append(img_region["h"]) - representations.append(instance) return representations From 63079d3095c82e7f2f5db51561cb36de955ec415 Mon Sep 17 00:00:00 2001 From: Andrea Lanfranchi Date: Thu, 22 Feb 2024 12:05:41 +0100 Subject: [PATCH 07/10] Use regex to match file patterns Also use os.listdir as is clear recursion is not intended --- deepface/modules/recognition.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/deepface/modules/recognition.py b/deepface/modules/recognition.py index 8cd2ed4..8e56c60 100644 --- a/deepface/modules/recognition.py +++ b/deepface/modules/recognition.py @@ -1,5 +1,6 @@ # built-in dependencies import os +import re import pickle from typing import List, Union, Optional import time @@ -14,6 +15,7 @@ from deepface.commons.logger import Logger from deepface.modules import representation, detection, modeling, verification from deepface.models.FacialRecognition import FacialRecognition + logger = Logger(module="deepface/modules/recognition.py") @@ -303,12 +305,12 @@ def __list_images(path: str) -> list[str]: Returns: images (list): list of exact image paths """ - images = [] - for r, _, f in os.walk(path): - for file in f: - if file.lower().endswith((".jpg", ".jpeg", ".png")): - exact_path = os.path.join(r, file) - images.append(exact_path) + images = list[str]() + pattern = re.compile(r".*\.(jpg|jpeg|png)$", re.IGNORECASE) + for file_name in os.listdir(path): + if pattern.match(file_name): + images.append(os.path.join(path, file_name)) + return images From 9dc0040a121ad157ad1b712e603218e90ef9d8a9 Mon Sep 17 00:00:00 2001 From: Andrea Lanfranchi Date: Thu, 22 Feb 2024 12:41:21 +0100 Subject: [PATCH 08/10] Amend typing --- deepface/modules/recognition.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deepface/modules/recognition.py b/deepface/modules/recognition.py index 8e56c60..f975e3b 100644 --- a/deepface/modules/recognition.py +++ b/deepface/modules/recognition.py @@ -297,7 +297,7 @@ def find( return resp_obj -def __list_images(path: str) -> list[str]: +def __list_images(path: str) -> List[str]: """ List images in a given path Args: @@ -305,7 +305,7 @@ def __list_images(path: str) -> list[str]: Returns: images (list): list of exact image paths """ - images = list[str]() + images = [] pattern = re.compile(r".*\.(jpg|jpeg|png)$", re.IGNORECASE) for file_name in os.listdir(path): if pattern.match(file_name): From 5a28a0b0f06eff799896a2ec389ab698cb7e3ae9 Mon Sep 17 00:00:00 2001 From: Andrea Lanfranchi Date: Thu, 22 Feb 2024 12:46:22 +0100 Subject: [PATCH 09/10] Revert usage of regex --- deepface/modules/recognition.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/deepface/modules/recognition.py b/deepface/modules/recognition.py index f975e3b..1ca7248 100644 --- a/deepface/modules/recognition.py +++ b/deepface/modules/recognition.py @@ -1,6 +1,5 @@ # built-in dependencies import os -import re import pickle from typing import List, Union, Optional import time @@ -15,7 +14,6 @@ from deepface.commons.logger import Logger from deepface.modules import representation, detection, modeling, verification from deepface.models.FacialRecognition import FacialRecognition - logger = Logger(module="deepface/modules/recognition.py") @@ -306,11 +304,11 @@ def __list_images(path: str) -> List[str]: images (list): list of exact image paths """ images = [] - pattern = re.compile(r".*\.(jpg|jpeg|png)$", re.IGNORECASE) - for file_name in os.listdir(path): - if pattern.match(file_name): - images.append(os.path.join(path, file_name)) - + for r, _, f in os.walk(path): + for file in f: + if file.lower().endswith((".jpg", ".jpeg", ".png")): + exact_path = os.path.join(r, file) + images.append(exact_path) return images From 954ac6e883e875308975ffcce5135571fcde0175 Mon Sep 17 00:00:00 2001 From: Andrea Lanfranchi Date: Thu, 22 Feb 2024 13:01:10 +0100 Subject: [PATCH 10/10] Remove trailing white-spaces --- deepface/modules/recognition.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/deepface/modules/recognition.py b/deepface/modules/recognition.py index 1ca7248..e8545b1 100644 --- a/deepface/modules/recognition.py +++ b/deepface/modules/recognition.py @@ -391,11 +391,11 @@ def __find_bulk_embeddings( img_representation = embedding_obj[0]["embedding"] representations.append(( - employee, - img_representation, - img_region["x"], - img_region["y"], - img_region["w"], + employee, + img_representation, + img_region["x"], + img_region["y"], + img_region["w"], img_region["h"] ))