From 103de47dfb5a6c21ef2f1af31923370cdd735cf5 Mon Sep 17 00:00:00 2001 From: Raghucharan16 Date: Thu, 20 Feb 2025 22:12:51 +0530 Subject: [PATCH 01/20] added buffalo_l model --- deepface/DeepFace.py | 2 +- .../models/facial_recognition/Buffalo_L.py | 76 +++++++++++++++++++ deepface/modules/modeling.py | 6 +- requirements.txt | 3 + 4 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 deepface/models/facial_recognition/Buffalo_L.py diff --git a/deepface/DeepFace.py b/deepface/DeepFace.py index ae0fb0b..99bcb64 100644 --- a/deepface/DeepFace.py +++ b/deepface/DeepFace.py @@ -54,7 +54,7 @@ def build_model(model_name: str, task: str = "facial_recognition") -> Any: Args: model_name (str): model identifier - VGG-Face, Facenet, Facenet512, OpenFace, DeepFace, DeepID, Dlib, - ArcFace, SFace and GhostFaceNet for face recognition + ArcFace, SFace GhostFaceNet and buffalo_l for face recognition - Age, Gender, Emotion, Race for facial attributes - opencv, mtcnn, ssd, dlib, retinaface, mediapipe, yolov8, yolov11n, yolov11s, yolov11m, yunet, fastmtcnn or centerface for face detectors diff --git a/deepface/models/facial_recognition/Buffalo_L.py b/deepface/models/facial_recognition/Buffalo_L.py new file mode 100644 index 0000000..0ec2365 --- /dev/null +++ b/deepface/models/facial_recognition/Buffalo_L.py @@ -0,0 +1,76 @@ +import cv2 +import numpy as np +from insightface.model_zoo import get_model +from deepface.models.FacialRecognition import FacialRecognition +from deepface.commons.logger import Logger + +logger = Logger() + +class Buffalo_L(FacialRecognition): + def __init__(self): + self.model = None + self.input_shape = (112, 112) # Buffalo_L recognition model expects 112x112 + self.output_shape = 512 # Embedding size for Buffalo_L + self.load_model() + + def load_model(self): + """ + Load the InsightFace Buffalo_L recognition model. + """ + # Load the recognition model directly (e.g., w600k_r50 from buffalo_l) + # The buffalo_l package includes recognition model weights + self.model = get_model('buffalo_l/w600k_r50.onnx', download=True) + self.model.prepare(ctx_id=-1, input_size=self.input_shape) # ctx_id=-1 for CPU + + def preprocess(self, img): + """ + Preprocess the image to match InsightFace recognition model expectations. + Args: + img (numpy array): Image in shape (1, 112, 112, 3) or (112, 112, 3) + Returns: + numpy array: Preprocessed image + """ + if len(img.shape) == 4: # (1, 112, 112, 3) + img = img[0] # Remove batch dimension + # Ensure image is in uint8 format (0-255 range) + if img.max() <= 1.0: # If normalized to [0, 1] + img = (img * 255).astype(np.uint8) + # Convert to BGR if in RGB (InsightFace expects BGR) + if img.shape[2] == 3: + img = img[:, :, ::-1] # RGB to BGR + return img + + def forward(self, img): + """ + Extract face embedding from a pre-cropped face image. + Args: + img (numpy array): Preprocessed face image with shape (1, 112, 112, 3) + Returns: + numpy array: Face embedding + """ + # Preprocess the input image + img = self.preprocess(img) + + # Extract embedding directly (no detection needed) + embedding = self.model.get_feat(img) + + # InsightFace recognition models return a list or array; ensure 1D output + if isinstance(embedding, (list, np.ndarray)) and len(embedding.shape) > 1: + embedding = embedding.flatten() + + return embedding + + def verify(self, img1, img2, threshold=0.65): + """ + Verify if two images contain the same person using cosine similarity. + Args: + img1, img2 (numpy arrays): Preprocessed images + threshold (float): Cosine similarity threshold + Returns: + tuple: (similarity_score, is_same_person) + """ + emb1 = self.forward(img1) + emb2 = self.forward(img2) + + similarity = np.dot(emb1, emb2) / (np.linalg.norm(emb1) * np.linalg.norm(emb2)) + return similarity, similarity > threshold \ No newline at end of file diff --git a/deepface/modules/modeling.py b/deepface/modules/modeling.py index 176d9e7..7ec067d 100644 --- a/deepface/modules/modeling.py +++ b/deepface/modules/modeling.py @@ -11,7 +11,8 @@ from deepface.models.facial_recognition import ( SFace, Dlib, Facenet, - GhostFaceNet + GhostFaceNet, + Buffalo_L ) from deepface.models.face_detection import ( FastMtCnn, @@ -59,7 +60,8 @@ def build_model(task: str, model_name: str) -> Any: "Dlib": Dlib.DlibClient, "ArcFace": ArcFace.ArcFaceClient, "SFace": SFace.SFaceClient, - "GhostFaceNet": GhostFaceNet.GhostFaceNetClient + "GhostFaceNet": GhostFaceNet.GhostFaceNetClient, + "Buffalo_L": Buffalo_L.Buffalo_L }, "spoofing": { "Fasnet": FasNet.Fasnet, diff --git a/requirements.txt b/requirements.txt index c208ada..fc28fd7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,3 +13,6 @@ mtcnn>=0.1.0 retina-face>=0.0.14 fire>=0.4.0 gunicorn>=20.1.0 +tf-keras +insightface==0.7.3 +onnxruntime>=1.9.0 \ No newline at end of file From 5a73d917444b4a386b6575cd0660efccc2b3ac54 Mon Sep 17 00:00:00 2001 From: Raghucharan16 Date: Thu, 20 Feb 2025 23:08:09 +0530 Subject: [PATCH 02/20] code review changes --- .../models/facial_recognition/Buffalo_L.py | 47 +++++++------------ deepface/modules/verification.py | 1 + requirements.txt | 5 +- requirements_additional.txt | 5 +- 4 files changed, 24 insertions(+), 34 deletions(-) diff --git a/deepface/models/facial_recognition/Buffalo_L.py b/deepface/models/facial_recognition/Buffalo_L.py index 0ec2365..fc01a4f 100644 --- a/deepface/models/facial_recognition/Buffalo_L.py +++ b/deepface/models/facial_recognition/Buffalo_L.py @@ -1,11 +1,19 @@ import cv2 import numpy as np -from insightface.model_zoo import get_model from deepface.models.FacialRecognition import FacialRecognition from deepface.commons.logger import Logger logger = Logger() +# Check for insightface dependency +try: + from insightface.model_zoo import get_model +except ModuleNotFoundError: + raise ModuleNotFoundError( + "InsightFace is an optional dependency for the Buffalo_L model." + "You can install it with: pip install insightface>=0.7.3" + ) + class Buffalo_L(FacialRecognition): def __init__(self): self.model = None @@ -17,8 +25,6 @@ class Buffalo_L(FacialRecognition): """ Load the InsightFace Buffalo_L recognition model. """ - # Load the recognition model directly (e.g., w600k_r50 from buffalo_l) - # The buffalo_l package includes recognition model weights self.model = get_model('buffalo_l/w600k_r50.onnx', download=True) self.model.prepare(ctx_id=-1, input_size=self.input_shape) # ctx_id=-1 for CPU @@ -32,12 +38,10 @@ class Buffalo_L(FacialRecognition): """ if len(img.shape) == 4: # (1, 112, 112, 3) img = img[0] # Remove batch dimension - # Ensure image is in uint8 format (0-255 range) if img.max() <= 1.0: # If normalized to [0, 1] img = (img * 255).astype(np.uint8) - # Convert to BGR if in RGB (InsightFace expects BGR) - if img.shape[2] == 3: - img = img[:, :, ::-1] # RGB to BGR + # Always convert RGB to BGR (InsightFace expects BGR, DeepFace provides RGB) + img = img[:, :, ::-1] return img def forward(self, img): @@ -48,29 +52,14 @@ class Buffalo_L(FacialRecognition): Returns: numpy array: Face embedding """ - # Preprocess the input image img = self.preprocess(img) - - # Extract embedding directly (no detection needed) embedding = self.model.get_feat(img) - # InsightFace recognition models return a list or array; ensure 1D output - if isinstance(embedding, (list, np.ndarray)) and len(embedding.shape) > 1: - embedding = embedding.flatten() + # Handle different embedding formats + if isinstance(embedding, np.ndarray): + if len(embedding.shape) > 1: + embedding = embedding.flatten() + elif isinstance(embedding, list): + embedding = np.array(embedding).flatten() - return embedding - - def verify(self, img1, img2, threshold=0.65): - """ - Verify if two images contain the same person using cosine similarity. - Args: - img1, img2 (numpy arrays): Preprocessed images - threshold (float): Cosine similarity threshold - Returns: - tuple: (similarity_score, is_same_person) - """ - emb1 = self.forward(img1) - emb2 = self.forward(img2) - - similarity = np.dot(emb1, emb2) / (np.linalg.norm(emb1) * np.linalg.norm(emb2)) - return similarity, similarity > threshold \ No newline at end of file + return embedding \ No newline at end of file diff --git a/deepface/modules/verification.py b/deepface/modules/verification.py index 43c3ba9..2e827b8 100644 --- a/deepface/modules/verification.py +++ b/deepface/modules/verification.py @@ -422,6 +422,7 @@ def find_threshold(model_name: str, distance_metric: str) -> float: "DeepFace": {"cosine": 0.23, "euclidean": 64, "euclidean_l2": 0.64}, "DeepID": {"cosine": 0.015, "euclidean": 45, "euclidean_l2": 0.17}, "GhostFaceNet": {"cosine": 0.65, "euclidean": 35.71, "euclidean_l2": 1.10}, + "Buffalo_L": {"cosine": 0.65, "euclidean": 11.13, "euclidean_l2": 1.1}, } threshold = thresholds.get(model_name, base_threshold).get(distance_metric, 0.4) diff --git a/requirements.txt b/requirements.txt index fc28fd7..afb1518 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,4 @@ flask_cors>=4.0.1 mtcnn>=0.1.0 retina-face>=0.0.14 fire>=0.4.0 -gunicorn>=20.1.0 -tf-keras -insightface==0.7.3 -onnxruntime>=1.9.0 \ No newline at end of file +gunicorn>=20.1.0 \ No newline at end of file diff --git a/requirements_additional.txt b/requirements_additional.txt index ea76fde..94d82dd 100644 --- a/requirements_additional.txt +++ b/requirements_additional.txt @@ -3,4 +3,7 @@ mediapipe>=0.8.7.3 dlib>=19.20.0 ultralytics>=8.0.122 facenet-pytorch>=2.5.3 -torch>=2.1.2 \ No newline at end of file +torch>=2.1.2 +insightface>=0.7.3 +onnxruntime>=1.9.0 +tf-keras \ No newline at end of file From ad0c7e75e76d24106d99aa9b2d6f202f0af29d28 Mon Sep 17 00:00:00 2001 From: Raghucharan16 Date: Thu, 20 Feb 2025 23:25:36 +0530 Subject: [PATCH 03/20] added weights --- .../models/facial_recognition/Buffalo_L.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/deepface/models/facial_recognition/Buffalo_L.py b/deepface/models/facial_recognition/Buffalo_L.py index fc01a4f..d769bf5 100644 --- a/deepface/models/facial_recognition/Buffalo_L.py +++ b/deepface/models/facial_recognition/Buffalo_L.py @@ -2,6 +2,9 @@ import cv2 import numpy as np from deepface.models.FacialRecognition import FacialRecognition from deepface.commons.logger import Logger +from deepface.basemodel import get_weights_path +from deepface.common import weight_utils +import os logger = Logger() @@ -22,11 +25,16 @@ class Buffalo_L(FacialRecognition): self.load_model() def load_model(self): - """ - Load the InsightFace Buffalo_L recognition model. - """ - self.model = get_model('buffalo_l/w600k_r50.onnx', download=True) - self.model.prepare(ctx_id=-1, input_size=self.input_shape) # ctx_id=-1 for CPU + root = os.path.join(get_weights_path(), 'insightface') + model_name = 'buffalo_l/w600k_r50.onnx' + model_path = os.path.join(root, model_name) + + if not os.path.exists(model_path): + url = 'https://drive.google.com/file/d/1N0GL-8ehw_bz2eZQWz2b0A5XBdXdxZhg/view?usp=sharing' + weight_utils.download_file(url, model_path) + + self.model = get_model(model_name, root=root) + self.model.prepare(ctx_id=-1, input_size=self.input_shape) def preprocess(self, img): """ From e19c7fcc1c683695133b94777279fa350e14b2e0 Mon Sep 17 00:00:00 2001 From: Raghucharan16 Date: Sat, 22 Feb 2025 19:14:29 +0530 Subject: [PATCH 04/20] added reviewed changes --- deepface/DeepFace.py | 2 +- .../models/facial_recognition/Buffalo_L.py | 64 +++++++++---------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/deepface/DeepFace.py b/deepface/DeepFace.py index bba0161..2f20a13 100644 --- a/deepface/DeepFace.py +++ b/deepface/DeepFace.py @@ -54,7 +54,7 @@ def build_model(model_name: str, task: str = "facial_recognition") -> Any: Args: model_name (str): model identifier - VGG-Face, Facenet, Facenet512, OpenFace, DeepFace, DeepID, Dlib, - ArcFace, SFace GhostFaceNet and buffalo_l for face recognition + ArcFace, SFace GhostFaceNet and Buffalo_L for face recognition - Age, Gender, Emotion, Race for facial attributes - opencv, mtcnn, ssd, dlib, retinaface, mediapipe, yolov8, yolov11n, yolov11s, yolov11m, yunet, fastmtcnn or centerface for face detectors diff --git a/deepface/models/facial_recognition/Buffalo_L.py b/deepface/models/facial_recognition/Buffalo_L.py index d769bf5..c1a1bcb 100644 --- a/deepface/models/facial_recognition/Buffalo_L.py +++ b/deepface/models/facial_recognition/Buffalo_L.py @@ -1,73 +1,73 @@ -import cv2 -import numpy as np -from deepface.models.FacialRecognition import FacialRecognition -from deepface.commons.logger import Logger -from deepface.basemodel import get_weights_path -from deepface.common import weight_utils import os +import numpy as np +from deepface.commons import weight_utils +from deepface.commons.logger import Logger +from deepface.models.FacialRecognition import FacialRecognition logger = Logger() -# Check for insightface dependency try: from insightface.model_zoo import get_model -except ModuleNotFoundError: +except ModuleNotFoundError as err: raise ModuleNotFoundError( "InsightFace is an optional dependency for the Buffalo_L model." "You can install it with: pip install insightface>=0.7.3" - ) + ) from err class Buffalo_L(FacialRecognition): def __init__(self): self.model = None - self.input_shape = (112, 112) # Buffalo_L recognition model expects 112x112 - self.output_shape = 512 # Embedding size for Buffalo_L + self.input_shape = (112, 112) # Buffalo_L expects 112x112 + self.output_shape = 512 # Embedding size self.load_model() def load_model(self): - root = os.path.join(get_weights_path(), 'insightface') - model_name = 'buffalo_l/w600k_r50.onnx' - model_path = os.path.join(root, model_name) - - if not os.path.exists(model_path): - url = 'https://drive.google.com/file/d/1N0GL-8ehw_bz2eZQWz2b0A5XBdXdxZhg/view?usp=sharing' - weight_utils.download_file(url, model_path) - - self.model = get_model(model_name, root=root) + """ + Load the InsightFace Buffalo_L recognition model. + """ + # Use DeepFace's utility to download weights if necessary + model_rel_path = os.path.join("insightface", "buffalo_l", "w600k_r50.onnx") + weights_path = weight_utils.download_weights_if_necessary( + file_name="webface_r50.onnx", + source_url="https://drive.google.com/uc?export=download&confirm=pbef&id=1N0GL-8ehw_bz2eZQWz2b0A5XBdXdxZhg" + ) + # Load model from weights folder + self.model = get_model("buffalo_l/w600k_r50.onnx", root=os.path.dirname(weights_path)) self.model.prepare(ctx_id=-1, input_size=self.input_shape) - def preprocess(self, img): + def preprocess(self, img: np.ndarray) -> np.ndarray: """ Preprocess the image to match InsightFace recognition model expectations. Args: - img (numpy array): Image in shape (1, 112, 112, 3) or (112, 112, 3) + img: Image in shape (1, 112, 112, 3) or (112, 112, 3) Returns: - numpy array: Preprocessed image + Preprocessed image as numpy array """ if len(img.shape) == 4: # (1, 112, 112, 3) img = img[0] # Remove batch dimension if img.max() <= 1.0: # If normalized to [0, 1] img = (img * 255).astype(np.uint8) - # Always convert RGB to BGR (InsightFace expects BGR, DeepFace provides RGB) + # Always convert RGB to BGR (DeepFace outputs RGB, InsightFace expects BGR) img = img[:, :, ::-1] return img - def forward(self, img): + def forward(self, img: np.ndarray) -> list[float]: """ Extract face embedding from a pre-cropped face image. Args: - img (numpy array): Preprocessed face image with shape (1, 112, 112, 3) + img: Preprocessed face image with shape (1, 112, 112, 3) Returns: - numpy array: Face embedding + Face embedding as a list of floats """ img = self.preprocess(img) embedding = self.model.get_feat(img) # Handle different embedding formats - if isinstance(embedding, np.ndarray): - if len(embedding.shape) > 1: - embedding = embedding.flatten() + if isinstance(embedding, np.ndarray) and len(embedding.shape) > 1: + embedding = embedding.flatten() elif isinstance(embedding, list): embedding = np.array(embedding).flatten() - - return embedding \ No newline at end of file + else: + raise ValueError(f"Unexpected embedding type: {type(embedding)}") + + return embedding.tolist() # Convert to list per FacialRecognition spec \ No newline at end of file From 2dbae0edcadf9b49e8558766c8de7a82d7454cf4 Mon Sep 17 00:00:00 2001 From: Raghucharan16 Date: Sun, 23 Feb 2025 11:51:02 +0530 Subject: [PATCH 05/20] review changes --- .../models/facial_recognition/Buffalo_L.py | 38 +++++++++++++++---- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/deepface/models/facial_recognition/Buffalo_L.py b/deepface/models/facial_recognition/Buffalo_L.py index c1a1bcb..9b6b8d2 100644 --- a/deepface/models/facial_recognition/Buffalo_L.py +++ b/deepface/models/facial_recognition/Buffalo_L.py @@ -10,7 +10,7 @@ try: from insightface.model_zoo import get_model except ModuleNotFoundError as err: raise ModuleNotFoundError( - "InsightFace is an optional dependency for the Buffalo_L model." + "InsightFace is an optional dependency for the Buffalo_L model. " "You can install it with: pip install insightface>=0.7.3" ) from err @@ -18,21 +18,43 @@ class Buffalo_L(FacialRecognition): def __init__(self): self.model = None self.input_shape = (112, 112) # Buffalo_L expects 112x112 - self.output_shape = 512 # Embedding size + self.output_shape = 512 # Embedding size self.load_model() def load_model(self): """ Load the InsightFace Buffalo_L recognition model. """ - # Use DeepFace's utility to download weights if necessary - model_rel_path = os.path.join("insightface", "buffalo_l", "w600k_r50.onnx") + # Define the model filename and subdirectory + sub_dir = "buffalo_l" + model_file = "w600k_r50.onnx" + model_rel_path = os.path.join(sub_dir, model_file) + + # Define the weights directory and ensure the buffalo_l subdirectory exists + weights_dir = os.path.join(os.path.expanduser("~"), ".deepface", "weights") + buffalo_l_dir = os.path.join(weights_dir, sub_dir) + if not os.path.exists(buffalo_l_dir): + os.makedirs(buffalo_l_dir, exist_ok=True) + print("Created directory:", buffalo_l_dir) + + # Download the model weights if not already present weights_path = weight_utils.download_weights_if_necessary( - file_name="webface_r50.onnx", + file_name=model_rel_path, source_url="https://drive.google.com/uc?export=download&confirm=pbef&id=1N0GL-8ehw_bz2eZQWz2b0A5XBdXdxZhg" ) - # Load model from weights folder - self.model = get_model("buffalo_l/w600k_r50.onnx", root=os.path.dirname(weights_path)) + print("Downloaded model path:", weights_path) + + # Verify that the model file exists at the expected location + expected_model_path = os.path.join(buffalo_l_dir, model_file) + if os.path.exists(expected_model_path): + print("Model file found at expected location:", expected_model_path) + else: + print("Model file NOT found at expected location:", expected_model_path) + + # Use the full absolute path for loading the model + full_model_path = os.path.join(buffalo_l_dir, model_file) + print("Full model path:", full_model_path) + self.model = get_model(full_model_path) self.model.prepare(ctx_id=-1, input_size=self.input_shape) def preprocess(self, img: np.ndarray) -> np.ndarray: @@ -47,7 +69,7 @@ class Buffalo_L(FacialRecognition): img = img[0] # Remove batch dimension if img.max() <= 1.0: # If normalized to [0, 1] img = (img * 255).astype(np.uint8) - # Always convert RGB to BGR (DeepFace outputs RGB, InsightFace expects BGR) + # Convert RGB to BGR (DeepFace outputs RGB, InsightFace expects BGR) img = img[:, :, ::-1] return img From 655a22165039a1acde18fea95ea9c4a522ef788b Mon Sep 17 00:00:00 2001 From: Raghucharan16 Date: Wed, 26 Feb 2025 23:41:16 +0530 Subject: [PATCH 06/20] added review changes --- .../models/facial_recognition/Buffalo_L.py | 65 +++++++++---------- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/deepface/models/facial_recognition/Buffalo_L.py b/deepface/models/facial_recognition/Buffalo_L.py index 9b6b8d2..27e4e8a 100644 --- a/deepface/models/facial_recognition/Buffalo_L.py +++ b/deepface/models/facial_recognition/Buffalo_L.py @@ -1,60 +1,59 @@ import os import numpy as np -from deepface.commons import weight_utils -from deepface.commons.logger import Logger -from deepface.models.FacialRecognition import FacialRecognition - -logger = Logger() +from typing import List try: from insightface.model_zoo import get_model except ModuleNotFoundError as err: raise ModuleNotFoundError( - "InsightFace is an optional dependency for the Buffalo_L model. " + "InsightFace is an optional dependency for the Buffalo_L model." "You can install it with: pip install insightface>=0.7.3" ) from err +from deepface.commons import weight_utils, folder_utils +from deepface.commons.logger import Logger +from deepface.models.FacialRecognition import FacialRecognition + +logger = Logger() + class Buffalo_L(FacialRecognition): def __init__(self): self.model = None - self.input_shape = (112, 112) # Buffalo_L expects 112x112 - self.output_shape = 512 # Embedding size + self.input_shape = (112, 112) + self.output_shape = 512 self.load_model() def load_model(self): """ Load the InsightFace Buffalo_L recognition model. """ - # Define the model filename and subdirectory - sub_dir = "buffalo_l" - model_file = "w600k_r50.onnx" - model_rel_path = os.path.join(sub_dir, model_file) + # Define the relative model path + model_rel_path = os.path.join("buffalo_l", "w600k_r50.onnx") - # Define the weights directory and ensure the buffalo_l subdirectory exists - weights_dir = os.path.join(os.path.expanduser("~"), ".deepface", "weights") - buffalo_l_dir = os.path.join(weights_dir, sub_dir) + # Get the DeepFace weights directory + home = folder_utils.get_deepface_home() + weights_dir = os.path.join(home, ".deepface", "weights") + buffalo_l_dir = os.path.join(weights_dir, "buffalo_l") + + # Ensure the buffalo_l subdirectory exists if not os.path.exists(buffalo_l_dir): os.makedirs(buffalo_l_dir, exist_ok=True) - print("Created directory:", buffalo_l_dir) + logger.info(f"Created directory: {buffalo_l_dir}") - # Download the model weights if not already present + # Download the model weights weights_path = weight_utils.download_weights_if_necessary( file_name=model_rel_path, source_url="https://drive.google.com/uc?export=download&confirm=pbef&id=1N0GL-8ehw_bz2eZQWz2b0A5XBdXdxZhg" ) - print("Downloaded model path:", weights_path) - # Verify that the model file exists at the expected location - expected_model_path = os.path.join(buffalo_l_dir, model_file) - if os.path.exists(expected_model_path): - print("Model file found at expected location:", expected_model_path) + # Verify the model file exists + if os.path.exists(weights_path): + logger.debug(f"Model file found at: {weights_path}") else: - print("Model file NOT found at expected location:", expected_model_path) + logger.debug(f"Model file NOT found at: {weights_path}") - # Use the full absolute path for loading the model - full_model_path = os.path.join(buffalo_l_dir, model_file) - print("Full model path:", full_model_path) - self.model = get_model(full_model_path) + # Load the model using the full absolute path + self.model = get_model(weights_path) self.model.prepare(ctx_id=-1, input_size=self.input_shape) def preprocess(self, img: np.ndarray) -> np.ndarray: @@ -65,15 +64,14 @@ class Buffalo_L(FacialRecognition): Returns: Preprocessed image as numpy array """ - if len(img.shape) == 4: # (1, 112, 112, 3) - img = img[0] # Remove batch dimension - if img.max() <= 1.0: # If normalized to [0, 1] + if len(img.shape) == 4: + img = img[0] + if img.max() <= 1.0: img = (img * 255).astype(np.uint8) - # Convert RGB to BGR (DeepFace outputs RGB, InsightFace expects BGR) img = img[:, :, ::-1] return img - def forward(self, img: np.ndarray) -> list[float]: + def forward(self, img: np.ndarray) -> List[float]: """ Extract face embedding from a pre-cropped face image. Args: @@ -84,7 +82,6 @@ class Buffalo_L(FacialRecognition): img = self.preprocess(img) embedding = self.model.get_feat(img) - # Handle different embedding formats if isinstance(embedding, np.ndarray) and len(embedding.shape) > 1: embedding = embedding.flatten() elif isinstance(embedding, list): @@ -92,4 +89,4 @@ class Buffalo_L(FacialRecognition): else: raise ValueError(f"Unexpected embedding type: {type(embedding)}") - return embedding.tolist() # Convert to list per FacialRecognition spec \ No newline at end of file + return embedding.tolist() \ No newline at end of file From 0d7c36a63b1873a4923a4a0fd37815a93855b52b Mon Sep 17 00:00:00 2001 From: raghucharan16 Date: Thu, 27 Feb 2025 11:55:35 +0530 Subject: [PATCH 07/20] raising exceptions for model weights and 3D img checks --- deepface/models/facial_recognition/Buffalo_L.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/deepface/models/facial_recognition/Buffalo_L.py b/deepface/models/facial_recognition/Buffalo_L.py index 27e4e8a..53a291d 100644 --- a/deepface/models/facial_recognition/Buffalo_L.py +++ b/deepface/models/facial_recognition/Buffalo_L.py @@ -50,7 +50,7 @@ class Buffalo_L(FacialRecognition): if os.path.exists(weights_path): logger.debug(f"Model file found at: {weights_path}") else: - logger.debug(f"Model file NOT found at: {weights_path}") + raise FileNotFoundError(f"Model file not found at: {weights_path}") # Load the model using the full absolute path self.model = get_model(weights_path) @@ -66,9 +66,11 @@ class Buffalo_L(FacialRecognition): """ if len(img.shape) == 4: img = img[0] + if len(img.shape) != 3: + raise ValueError(f"Expected image to be 3D after preprocessing, but got shape: {img.shape}") if img.max() <= 1.0: img = (img * 255).astype(np.uint8) - img = img[:, :, ::-1] + img = img[:, :, ::-1] # Convert RGB to BGR return img def forward(self, img: np.ndarray) -> List[float]: From 1a5d74b893794737634c0675fe5352a7ea22d552 Mon Sep 17 00:00:00 2001 From: raghucharan16 Date: Fri, 28 Feb 2025 15:11:59 +0530 Subject: [PATCH 08/20] review changes --- .../models/facial_recognition/Buffalo_L.py | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/deepface/models/facial_recognition/Buffalo_L.py b/deepface/models/facial_recognition/Buffalo_L.py index 53a291d..32ab9f3 100644 --- a/deepface/models/facial_recognition/Buffalo_L.py +++ b/deepface/models/facial_recognition/Buffalo_L.py @@ -2,14 +2,6 @@ import os import numpy as np from typing import List -try: - from insightface.model_zoo import get_model -except ModuleNotFoundError as err: - raise ModuleNotFoundError( - "InsightFace is an optional dependency for the Buffalo_L model." - "You can install it with: pip install insightface>=0.7.3" - ) from err - from deepface.commons import weight_utils, folder_utils from deepface.commons.logger import Logger from deepface.models.FacialRecognition import FacialRecognition @@ -27,20 +19,30 @@ class Buffalo_L(FacialRecognition): """ Load the InsightFace Buffalo_L recognition model. """ - # Define the relative model path - model_rel_path = os.path.join("buffalo_l", "w600k_r50.onnx") + try: + from insightface.model_zoo import get_model + except ModuleNotFoundError as err: + raise ModuleNotFoundError( + "InsightFace is an optional dependency for the Buffalo_L model." + "You can install it with: pip install insightface>=0.7.3" + ) from err - # Get the DeepFace weights directory + # Define the model filename and subdirectory + sub_dir = "buffalo_l" + model_file = "w600k_r50.onnx" + model_rel_path = os.path.join(sub_dir, model_file) + + # Get the DeepFace home directory and construct weights path home = folder_utils.get_deepface_home() weights_dir = os.path.join(home, ".deepface", "weights") - buffalo_l_dir = os.path.join(weights_dir, "buffalo_l") + buffalo_l_dir = os.path.join(weights_dir, sub_dir) # Ensure the buffalo_l subdirectory exists if not os.path.exists(buffalo_l_dir): os.makedirs(buffalo_l_dir, exist_ok=True) logger.info(f"Created directory: {buffalo_l_dir}") - # Download the model weights + # Download the model weights if not already present weights_path = weight_utils.download_weights_if_necessary( file_name=model_rel_path, source_url="https://drive.google.com/uc?export=download&confirm=pbef&id=1N0GL-8ehw_bz2eZQWz2b0A5XBdXdxZhg" @@ -52,8 +54,8 @@ class Buffalo_L(FacialRecognition): else: raise FileNotFoundError(f"Model file not found at: {weights_path}") - # Load the model using the full absolute path - self.model = get_model(weights_path) + # Load the model + self.model = get_model(model_file, root=buffalo_l_dir) self.model.prepare(ctx_id=-1, input_size=self.input_shape) def preprocess(self, img: np.ndarray) -> np.ndarray: From 2a1babbe142e025c5c57cbda347a9c1e269ea23c Mon Sep 17 00:00:00 2001 From: raghucharan16 Date: Fri, 28 Feb 2025 16:08:15 +0530 Subject: [PATCH 09/20] updated optional requirements for Buffalo_L --- deepface/models/facial_recognition/Buffalo_L.py | 5 +++-- requirements_additional.txt | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/deepface/models/facial_recognition/Buffalo_L.py b/deepface/models/facial_recognition/Buffalo_L.py index 32ab9f3..5f27110 100644 --- a/deepface/models/facial_recognition/Buffalo_L.py +++ b/deepface/models/facial_recognition/Buffalo_L.py @@ -23,8 +23,9 @@ class Buffalo_L(FacialRecognition): from insightface.model_zoo import get_model except ModuleNotFoundError as err: raise ModuleNotFoundError( - "InsightFace is an optional dependency for the Buffalo_L model." - "You can install it with: pip install insightface>=0.7.3" + "InsightFace and its dependencies are optional for the Buffalo_L model. " + "Please install them with: " + "pip install insightface>=0.7.3 onnxruntime>=1.9.0 typing-extensions pydantic" ) from err # Define the model filename and subdirectory diff --git a/requirements_additional.txt b/requirements_additional.txt index 94d82dd..dd30b95 100644 --- a/requirements_additional.txt +++ b/requirements_additional.txt @@ -6,4 +6,6 @@ facenet-pytorch>=2.5.3 torch>=2.1.2 insightface>=0.7.3 onnxruntime>=1.9.0 -tf-keras \ No newline at end of file +tf-keras +typing-extensions +pydantic \ No newline at end of file From b8494b01a1d1355aead8b1dba5cdda430406af06 Mon Sep 17 00:00:00 2001 From: raghucharan16 Date: Fri, 28 Feb 2025 16:33:50 +0530 Subject: [PATCH 10/20] updated optional requirements for Buffalo_L --- deepface/models/facial_recognition/Buffalo_L.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deepface/models/facial_recognition/Buffalo_L.py b/deepface/models/facial_recognition/Buffalo_L.py index 5f27110..960542b 100644 --- a/deepface/models/facial_recognition/Buffalo_L.py +++ b/deepface/models/facial_recognition/Buffalo_L.py @@ -21,8 +21,8 @@ class Buffalo_L(FacialRecognition): """ try: from insightface.model_zoo import get_model - except ModuleNotFoundError as err: - raise ModuleNotFoundError( + except Exception as err: + raise Exception( "InsightFace and its dependencies are optional for the Buffalo_L model. " "Please install them with: " "pip install insightface>=0.7.3 onnxruntime>=1.9.0 typing-extensions pydantic" From fac74113ca348796f80f97e760d2be001394e2ee Mon Sep 17 00:00:00 2001 From: raghucharan16 Date: Fri, 28 Feb 2025 16:52:37 +0530 Subject: [PATCH 11/20] added exceptional handling --- deepface/models/facial_recognition/Buffalo_L.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deepface/models/facial_recognition/Buffalo_L.py b/deepface/models/facial_recognition/Buffalo_L.py index 960542b..ea71f8e 100644 --- a/deepface/models/facial_recognition/Buffalo_L.py +++ b/deepface/models/facial_recognition/Buffalo_L.py @@ -22,7 +22,7 @@ class Buffalo_L(FacialRecognition): try: from insightface.model_zoo import get_model except Exception as err: - raise Exception( + raise ModuleNotFoundError( "InsightFace and its dependencies are optional for the Buffalo_L model. " "Please install them with: " "pip install insightface>=0.7.3 onnxruntime>=1.9.0 typing-extensions pydantic" From 41667299399e0ce8c54b054661a28b9930aabe40 Mon Sep 17 00:00:00 2001 From: raghucharan16 Date: Fri, 28 Feb 2025 17:14:17 +0530 Subject: [PATCH 12/20] minor linting changes --- deepface/models/facial_recognition/Buffalo_L.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/deepface/models/facial_recognition/Buffalo_L.py b/deepface/models/facial_recognition/Buffalo_L.py index ea71f8e..ed99a12 100644 --- a/deepface/models/facial_recognition/Buffalo_L.py +++ b/deepface/models/facial_recognition/Buffalo_L.py @@ -1,6 +1,6 @@ import os -import numpy as np from typing import List +import numpy as np from deepface.commons import weight_utils, folder_utils from deepface.commons.logger import Logger @@ -70,7 +70,8 @@ class Buffalo_L(FacialRecognition): if len(img.shape) == 4: img = img[0] if len(img.shape) != 3: - raise ValueError(f"Expected image to be 3D after preprocessing, but got shape: {img.shape}") + raise ValueError( + f"Expected image to be 3D after preprocessing, but got shape: {img.shape}") if img.max() <= 1.0: img = (img * 255).astype(np.uint8) img = img[:, :, ::-1] # Convert RGB to BGR @@ -86,12 +87,11 @@ class Buffalo_L(FacialRecognition): """ img = self.preprocess(img) embedding = self.model.get_feat(img) - if isinstance(embedding, np.ndarray) and len(embedding.shape) > 1: embedding = embedding.flatten() elif isinstance(embedding, list): embedding = np.array(embedding).flatten() else: raise ValueError(f"Unexpected embedding type: {type(embedding)}") - - return embedding.tolist() \ No newline at end of file + return embedding.tolist() + \ No newline at end of file From 2a6b222d521b795d9b32660040c49c56cc55d7b2 Mon Sep 17 00:00:00 2001 From: raghucharan16 Date: Fri, 28 Feb 2025 17:56:14 +0530 Subject: [PATCH 13/20] pylint diable linr too long --- deepface/models/facial_recognition/Buffalo_L.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deepface/models/facial_recognition/Buffalo_L.py b/deepface/models/facial_recognition/Buffalo_L.py index ed99a12..bf44379 100644 --- a/deepface/models/facial_recognition/Buffalo_L.py +++ b/deepface/models/facial_recognition/Buffalo_L.py @@ -46,7 +46,7 @@ class Buffalo_L(FacialRecognition): # Download the model weights if not already present weights_path = weight_utils.download_weights_if_necessary( file_name=model_rel_path, - source_url="https://drive.google.com/uc?export=download&confirm=pbef&id=1N0GL-8ehw_bz2eZQWz2b0A5XBdXdxZhg" + source_url="https://drive.google.com/uc?export=download&confirm=pbef&id=1N0GL-8ehw_bz2eZQWz2b0A5XBdXdxZhg" # pylint: disable=line-too-long ) # Verify the model file exists From 527a89c9318079ef260ba7a511efa8ffe2ff5441 Mon Sep 17 00:00:00 2001 From: raghucharan16 Date: Sat, 1 Mar 2025 12:18:09 +0530 Subject: [PATCH 14/20] review chanages --- .../models/facial_recognition/Buffalo_L.py | 52 +++++++++++-------- requirements_additional.txt | 3 +- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/deepface/models/facial_recognition/Buffalo_L.py b/deepface/models/facial_recognition/Buffalo_L.py index bf44379..7e4b0d5 100644 --- a/deepface/models/facial_recognition/Buffalo_L.py +++ b/deepface/models/facial_recognition/Buffalo_L.py @@ -1,5 +1,5 @@ import os -from typing import List +from typing import List, Union import numpy as np from deepface.commons import weight_utils, folder_utils @@ -25,12 +25,12 @@ class Buffalo_L(FacialRecognition): raise ModuleNotFoundError( "InsightFace and its dependencies are optional for the Buffalo_L model. " "Please install them with: " - "pip install insightface>=0.7.3 onnxruntime>=1.9.0 typing-extensions pydantic" + "pip install insightface>=0.7.3 onnxruntime>=1.9.0 typing-extensions pydantic albumentations" ) from err # Define the model filename and subdirectory sub_dir = "buffalo_l" - model_file = "w600k_r50.onnx" + model_file = "webface_r50.onnx" model_rel_path = os.path.join(sub_dir, model_file) # Get the DeepFace home directory and construct weights path @@ -46,7 +46,7 @@ class Buffalo_L(FacialRecognition): # Download the model weights if not already present weights_path = weight_utils.download_weights_if_necessary( file_name=model_rel_path, - source_url="https://drive.google.com/uc?export=download&confirm=pbef&id=1N0GL-8ehw_bz2eZQWz2b0A5XBdXdxZhg" # pylint: disable=line-too-long + source_url="https://drive.google.com/uc?export=download&confirm=pbef&id=1N0GL-8ehw_bz2eZQWz2b0A5XBdXdxZhg" # pylint: disable=line-too-long ) # Verify the model file exists @@ -55,20 +55,27 @@ class Buffalo_L(FacialRecognition): else: raise FileNotFoundError(f"Model file not found at: {weights_path}") - # Load the model - self.model = get_model(model_file, root=buffalo_l_dir) + # Load the model using the full path + self.model = get_model(weights_path) self.model.prepare(ctx_id=-1, input_size=self.input_shape) def preprocess(self, img: np.ndarray) -> np.ndarray: """ - Preprocess the image to match InsightFace recognition model expectations. + Preprocess the image or batch of images to match InsightFace recognition model expectations. Args: - img: Image in shape (1, 112, 112, 3) or (112, 112, 3) + img: Image in shape (1, 112, 112, 3) or (112, 112, 3) or batch (batch_size, 112, 112, 3) Returns: - Preprocessed image as numpy array + Preprocessed image or batch as numpy array """ - if len(img.shape) == 4: - img = img[0] + if len(img.shape) == 4: # Batch of images + preprocessed_imgs = [] + for i in range(img.shape[0]): + single_img = img[i] + if single_img.max() <= 1.0: + single_img = (single_img * 255).astype(np.uint8) + single_img = single_img[:, :, ::-1] # Convert RGB to BGR + preprocessed_imgs.append(single_img) + return np.array(preprocessed_imgs) if len(img.shape) != 3: raise ValueError( f"Expected image to be 3D after preprocessing, but got shape: {img.shape}") @@ -77,21 +84,20 @@ class Buffalo_L(FacialRecognition): img = img[:, :, ::-1] # Convert RGB to BGR return img - def forward(self, img: np.ndarray) -> List[float]: + def forward(self, img: np.ndarray) -> Union[List[float], List[List[float]]]: """ - Extract face embedding from a pre-cropped face image. + Extract face embedding from a pre-cropped face image or batch of images. Args: - img: Preprocessed face image with shape (1, 112, 112, 3) + img: Preprocessed face image with shape (1, 112, 112, 3) or batch (batch_size, 112, 112, 3) Returns: - Face embedding as a list of floats + Face embedding as a list of floats (single image) or list of lists of floats (batch) """ img = self.preprocess(img) - embedding = self.model.get_feat(img) - if isinstance(embedding, np.ndarray) and len(embedding.shape) > 1: - embedding = embedding.flatten() - elif isinstance(embedding, list): - embedding = np.array(embedding).flatten() + if len(img.shape) == 4: # Batch + embeddings = self.model.get_feat(img) + return [embedding.tolist() for embedding in embeddings] + elif len(img.shape) == 3: # Single image + embedding = self.model.get_feat(np.expand_dims(img, axis=0))[0] + return embedding.tolist() else: - raise ValueError(f"Unexpected embedding type: {type(embedding)}") - return embedding.tolist() - \ No newline at end of file + raise ValueError(f"Unexpected embedding type after preprocessing: {img.shape}") \ No newline at end of file diff --git a/requirements_additional.txt b/requirements_additional.txt index dd30b95..cc38a19 100644 --- a/requirements_additional.txt +++ b/requirements_additional.txt @@ -8,4 +8,5 @@ insightface>=0.7.3 onnxruntime>=1.9.0 tf-keras typing-extensions -pydantic \ No newline at end of file +pydantic +albumentations \ No newline at end of file From e363a56f09e39acdf5226a6da9789b5f3bfceb89 Mon Sep 17 00:00:00 2001 From: Raghucharan16 Date: Sat, 1 Mar 2025 13:16:10 +0530 Subject: [PATCH 15/20] added review changes --- .../models/facial_recognition/Buffalo_L.py | 64 +++++++++---------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/deepface/models/facial_recognition/Buffalo_L.py b/deepface/models/facial_recognition/Buffalo_L.py index 7e4b0d5..ff92300 100644 --- a/deepface/models/facial_recognition/Buffalo_L.py +++ b/deepface/models/facial_recognition/Buffalo_L.py @@ -30,7 +30,7 @@ class Buffalo_L(FacialRecognition): # Define the model filename and subdirectory sub_dir = "buffalo_l" - model_file = "webface_r50.onnx" + model_file = "webface_r50.onnx" # Corrected from w600k_r50.onnx per serengil's comment model_rel_path = os.path.join(sub_dir, model_file) # Get the DeepFace home directory and construct weights path @@ -46,58 +46,56 @@ class Buffalo_L(FacialRecognition): # Download the model weights if not already present weights_path = weight_utils.download_weights_if_necessary( file_name=model_rel_path, - source_url="https://drive.google.com/uc?export=download&confirm=pbef&id=1N0GL-8ehw_bz2eZQWz2b0A5XBdXdxZhg" # pylint: disable=line-too-long + source_url="https://drive.google.com/uc?export=download&confirm=pbef&id=1N0GL-8ehw_bz2eZQWz2b0A5XBdXdxZhg" ) # Verify the model file exists - if os.path.exists(weights_path): - logger.debug(f"Model file found at: {weights_path}") - else: + if not os.path.exists(weights_path): raise FileNotFoundError(f"Model file not found at: {weights_path}") + else: + logger.debug(f"Model file found at: {weights_path}") # Load the model using the full path - self.model = get_model(weights_path) + self.model = get_model(weights_path) # Updated per serengil's feedback self.model.prepare(ctx_id=-1, input_size=self.input_shape) def preprocess(self, img: np.ndarray) -> np.ndarray: """ - Preprocess the image or batch of images to match InsightFace recognition model expectations. + Preprocess the input image for the Buffalo_L model. + Args: - img: Image in shape (1, 112, 112, 3) or (112, 112, 3) or batch (batch_size, 112, 112, 3) + img: Input image as a numpy array of shape (112, 112, 3) or (1, 112, 112, 3). + Returns: - Preprocessed image or batch as numpy array + Preprocessed image as numpy array. """ - if len(img.shape) == 4: # Batch of images - preprocessed_imgs = [] - for i in range(img.shape[0]): - single_img = img[i] - if single_img.max() <= 1.0: - single_img = (single_img * 255).astype(np.uint8) - single_img = single_img[:, :, ::-1] # Convert RGB to BGR - preprocessed_imgs.append(single_img) - return np.array(preprocessed_imgs) - if len(img.shape) != 3: - raise ValueError( - f"Expected image to be 3D after preprocessing, but got shape: {img.shape}") - if img.max() <= 1.0: - img = (img * 255).astype(np.uint8) - img = img[:, :, ::-1] # Convert RGB to BGR + # Ensure input is a single image + if len(img.shape) == 4: + if img.shape[0] == 1: + img = img[0] # Squeeze batch dimension if it's a single-image batch + else: + raise ValueError("Buffalo_L model expects a single image, not a batch.") + elif len(img.shape) != 3 or img.shape != (112, 112, 3): + raise ValueError("Input image must have shape (112, 112, 3).") + + # Convert RGB to BGR as required by InsightFace + img = img[:, :, ::-1] return img def forward(self, img: np.ndarray) -> Union[List[float], List[List[float]]]: """ - Extract face embedding from a pre-cropped face image or batch of images. + Extract face embedding from a pre-cropped face image. Args: img: Preprocessed face image with shape (1, 112, 112, 3) or batch (batch_size, 112, 112, 3) Returns: - Face embedding as a list of floats (single image) or list of lists of floats (batch) + Face embedding as a list of floats or list of lists of floats """ img = self.preprocess(img) - if len(img.shape) == 4: # Batch - embeddings = self.model.get_feat(img) - return [embedding.tolist() for embedding in embeddings] - elif len(img.shape) == 3: # Single image - embedding = self.model.get_feat(np.expand_dims(img, axis=0))[0] - return embedding.tolist() + embedding = self.model.get_feat(img) + if isinstance(embedding, np.ndarray) and len(embedding.shape) > 1: + embedding = embedding.flatten() + elif isinstance(embedding, list): + embedding = np.array(embedding).flatten() else: - raise ValueError(f"Unexpected embedding type after preprocessing: {img.shape}") \ No newline at end of file + raise ValueError(f"Unexpected embedding type: {type(embedding)}") + return embedding.tolist() \ No newline at end of file From 112eb0a6c2bcb269bf82c2f7ee17221271973ebf Mon Sep 17 00:00:00 2001 From: Raghucharan16 Date: Sat, 1 Mar 2025 13:20:30 +0530 Subject: [PATCH 16/20] added review changes --- deepface/models/facial_recognition/Buffalo_L.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deepface/models/facial_recognition/Buffalo_L.py b/deepface/models/facial_recognition/Buffalo_L.py index ff92300..c86f315 100644 --- a/deepface/models/facial_recognition/Buffalo_L.py +++ b/deepface/models/facial_recognition/Buffalo_L.py @@ -46,7 +46,7 @@ class Buffalo_L(FacialRecognition): # Download the model weights if not already present weights_path = weight_utils.download_weights_if_necessary( file_name=model_rel_path, - source_url="https://drive.google.com/uc?export=download&confirm=pbef&id=1N0GL-8ehw_bz2eZQWz2b0A5XBdXdxZhg" + source_url="https://drive.google.com/uc?export=download&confirm=pbef&id=1N0GL-8ehw_bz2eZQWz2b0A5XBdXdxZhg" #pylint: disable=line-too-long ) # Verify the model file exists From 91319705b18a92d452ed5cd0574fd0fbc81d5cca Mon Sep 17 00:00:00 2001 From: Raghucharan16 Date: Sat, 1 Mar 2025 14:01:59 +0530 Subject: [PATCH 17/20] added review changes --- deepface/models/facial_recognition/Buffalo_L.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/deepface/models/facial_recognition/Buffalo_L.py b/deepface/models/facial_recognition/Buffalo_L.py index c86f315..efe1524 100644 --- a/deepface/models/facial_recognition/Buffalo_L.py +++ b/deepface/models/facial_recognition/Buffalo_L.py @@ -25,7 +25,8 @@ class Buffalo_L(FacialRecognition): raise ModuleNotFoundError( "InsightFace and its dependencies are optional for the Buffalo_L model. " "Please install them with: " - "pip install insightface>=0.7.3 onnxruntime>=1.9.0 typing-extensions pydantic albumentations" + "pip install insightface>=0.7.3 onnxruntime>=1.9.0 typing-extensions pydantic" + "albumentations" ) from err # Define the model filename and subdirectory @@ -86,7 +87,8 @@ class Buffalo_L(FacialRecognition): """ Extract face embedding from a pre-cropped face image. Args: - img: Preprocessed face image with shape (1, 112, 112, 3) or batch (batch_size, 112, 112, 3) + img: Preprocessed face image with shape (1, 112, 112, 3) + or batch (batch_size, 112, 112, 3) Returns: Face embedding as a list of floats or list of lists of floats """ @@ -98,4 +100,5 @@ class Buffalo_L(FacialRecognition): embedding = np.array(embedding).flatten() else: raise ValueError(f"Unexpected embedding type: {type(embedding)}") - return embedding.tolist() \ No newline at end of file + return embedding.tolist() + \ No newline at end of file From 058a0fa59056444655fc522cf6859b4cd08359e7 Mon Sep 17 00:00:00 2001 From: Raghucharan16 Date: Sat, 1 Mar 2025 14:06:01 +0530 Subject: [PATCH 18/20] added review changes --- .../models/facial_recognition/Buffalo_L.py | 69 +++++++++---------- 1 file changed, 31 insertions(+), 38 deletions(-) diff --git a/deepface/models/facial_recognition/Buffalo_L.py b/deepface/models/facial_recognition/Buffalo_L.py index efe1524..ad59169 100644 --- a/deepface/models/facial_recognition/Buffalo_L.py +++ b/deepface/models/facial_recognition/Buffalo_L.py @@ -16,9 +16,7 @@ class Buffalo_L(FacialRecognition): self.load_model() def load_model(self): - """ - Load the InsightFace Buffalo_L recognition model. - """ + """Load the InsightFace Buffalo_L recognition model.""" try: from insightface.model_zoo import get_model except Exception as err: @@ -29,76 +27,71 @@ class Buffalo_L(FacialRecognition): "albumentations" ) from err - # Define the model filename and subdirectory sub_dir = "buffalo_l" - model_file = "webface_r50.onnx" # Corrected from w600k_r50.onnx per serengil's comment + model_file = "webface_r50.onnx" model_rel_path = os.path.join(sub_dir, model_file) - - # Get the DeepFace home directory and construct weights path home = folder_utils.get_deepface_home() weights_dir = os.path.join(home, ".deepface", "weights") buffalo_l_dir = os.path.join(weights_dir, sub_dir) - # Ensure the buffalo_l subdirectory exists if not os.path.exists(buffalo_l_dir): os.makedirs(buffalo_l_dir, exist_ok=True) logger.info(f"Created directory: {buffalo_l_dir}") - # Download the model weights if not already present weights_path = weight_utils.download_weights_if_necessary( file_name=model_rel_path, source_url="https://drive.google.com/uc?export=download&confirm=pbef&id=1N0GL-8ehw_bz2eZQWz2b0A5XBdXdxZhg" #pylint: disable=line-too-long ) - # Verify the model file exists if not os.path.exists(weights_path): raise FileNotFoundError(f"Model file not found at: {weights_path}") else: logger.debug(f"Model file found at: {weights_path}") - # Load the model using the full path - self.model = get_model(weights_path) # Updated per serengil's feedback + self.model = get_model(weights_path) self.model.prepare(ctx_id=-1, input_size=self.input_shape) def preprocess(self, img: np.ndarray) -> np.ndarray: """ - Preprocess the input image for the Buffalo_L model. + Preprocess the input image or batch of images. Args: - img: Input image as a numpy array of shape (112, 112, 3) or (1, 112, 112, 3). + img: Input image or batch with shape (112, 112, 3) + or (batch_size, 112, 112, 3). Returns: - Preprocessed image as numpy array. + Preprocessed image(s) with RGB converted to BGR. """ - # Ensure input is a single image - if len(img.shape) == 4: - if img.shape[0] == 1: - img = img[0] # Squeeze batch dimension if it's a single-image batch - else: - raise ValueError("Buffalo_L model expects a single image, not a batch.") - elif len(img.shape) != 3 or img.shape != (112, 112, 3): - raise ValueError("Input image must have shape (112, 112, 3).") + if len(img.shape) == 3: + img = np.expand_dims(img, axis=0) # Convert single image to batch of 1 + elif len(img.shape) != 4: + raise ValueError("Input must have shape (112, 112, 3) or (batch_size, 112, 112, 3).") - # Convert RGB to BGR as required by InsightFace - img = img[:, :, ::-1] + # Convert RGB to BGR for the entire batch + img = img[:, :, :, ::-1] return img def forward(self, img: np.ndarray) -> Union[List[float], List[List[float]]]: """ - Extract face embedding from a pre-cropped face image. + Extract facial embedding(s) from the input image or batch of images. + Args: - img: Preprocessed face image with shape (1, 112, 112, 3) - or batch (batch_size, 112, 112, 3) + img: Input image or batch with shape (112, 112, 3) + or (batch_size, 112, 112, 3). + Returns: - Face embedding as a list of floats or list of lists of floats + Embedding as a list of floats (single image) + or list of lists of floats (batch). """ + # Preprocess the input (single image or batch) img = self.preprocess(img) - embedding = self.model.get_feat(img) - if isinstance(embedding, np.ndarray) and len(embedding.shape) > 1: - embedding = embedding.flatten() - elif isinstance(embedding, list): - embedding = np.array(embedding).flatten() - else: - raise ValueError(f"Unexpected embedding type: {type(embedding)}") - return embedding.tolist() - \ No newline at end of file + batch_size = img.shape[0] + + # Handle both single images and batches + embeddings = [] + for i in range(batch_size): + embedding = self.model.get_feat(img[i]) + embeddings.append(embedding.flatten().tolist()) + + # Return single embedding if batch_size is 1, otherwise return list of embeddings + return embeddings[0] if batch_size == 1 else embeddings \ No newline at end of file From 643ac3dc358a7c751974558b3a3707b99bcfb6b1 Mon Sep 17 00:00:00 2001 From: Raghucharan16 Date: Sat, 1 Mar 2025 14:34:19 +0530 Subject: [PATCH 19/20] added review changes --- deepface/models/facial_recognition/Buffalo_L.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/deepface/models/facial_recognition/Buffalo_L.py b/deepface/models/facial_recognition/Buffalo_L.py index ad59169..27930ec 100644 --- a/deepface/models/facial_recognition/Buffalo_L.py +++ b/deepface/models/facial_recognition/Buffalo_L.py @@ -39,14 +39,13 @@ class Buffalo_L(FacialRecognition): logger.info(f"Created directory: {buffalo_l_dir}") weights_path = weight_utils.download_weights_if_necessary( - file_name=model_rel_path, - source_url="https://drive.google.com/uc?export=download&confirm=pbef&id=1N0GL-8ehw_bz2eZQWz2b0A5XBdXdxZhg" #pylint: disable=line-too-long + file_name=model_rel_path, + source_url="https://drive.google.com/uc?export=download&confirm=pbef&id=1N0GL-8ehw_bz2eZQWz2b0A5XBdXdxZhg" #pylint: disable=line-too-long ) if not os.path.exists(weights_path): raise FileNotFoundError(f"Model file not found at: {weights_path}") - else: - logger.debug(f"Model file found at: {weights_path}") + logger.debug(f"Model file found at: {weights_path}") self.model = get_model(weights_path) self.model.prepare(ctx_id=-1, input_size=self.input_shape) @@ -65,8 +64,7 @@ class Buffalo_L(FacialRecognition): if len(img.shape) == 3: img = np.expand_dims(img, axis=0) # Convert single image to batch of 1 elif len(img.shape) != 4: - raise ValueError("Input must have shape (112, 112, 3) or (batch_size, 112, 112, 3).") - + raise ValueError(f"Input must have shape (112, 112, 3) or (X, 112, 112, 3). Got {img.shape}") # Convert RGB to BGR for the entire batch img = img[:, :, :, ::-1] return img From e2d1d5acb4ec54be384585aac058025ced52a225 Mon Sep 17 00:00:00 2001 From: Raghucharan16 Date: Sat, 1 Mar 2025 14:48:47 +0530 Subject: [PATCH 20/20] added review changes --- deepface/models/facial_recognition/Buffalo_L.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/deepface/models/facial_recognition/Buffalo_L.py b/deepface/models/facial_recognition/Buffalo_L.py index 27930ec..eeca234 100644 --- a/deepface/models/facial_recognition/Buffalo_L.py +++ b/deepface/models/facial_recognition/Buffalo_L.py @@ -64,7 +64,7 @@ class Buffalo_L(FacialRecognition): if len(img.shape) == 3: img = np.expand_dims(img, axis=0) # Convert single image to batch of 1 elif len(img.shape) != 4: - raise ValueError(f"Input must have shape (112, 112, 3) or (X, 112, 112, 3). Got {img.shape}") + raise ValueError(f"Input must be (112, 112, 3) or (X, 112, 112, 3). Got {img.shape}") # Convert RGB to BGR for the entire batch img = img[:, :, :, ::-1] return img @@ -92,4 +92,5 @@ class Buffalo_L(FacialRecognition): embeddings.append(embedding.flatten().tolist()) # Return single embedding if batch_size is 1, otherwise return list of embeddings - return embeddings[0] if batch_size == 1 else embeddings \ No newline at end of file + return embeddings[0] if batch_size == 1 else embeddings + \ No newline at end of file