| import numpy as np |
| from deepface import DeepFace |
| import os |
|
|
| class FaceEmbedder: |
| def __init__(self, model_name="Facenet"): |
| self.model_name = model_name |
| |
| print(f"Initializing FaceEmbedder with model: {self.model_name}") |
| |
|
|
| def compute_embedding(self, image_path: str) -> np.ndarray: |
| if not os.path.exists(image_path): |
| raise FileNotFoundError(f"Image not found: {image_path}") |
| |
| objs = DeepFace.represent( |
| img_path=image_path, |
| model_name=self.model_name, |
| enforce_detection=False, |
| detector_backend="opencv", |
| align=True |
| ) |
| if not objs: |
| return np.zeros(128) |
| |
| emb = np.array(objs[0]["embedding"], dtype=np.float32) |
| return emb |
|
|
| def extract_face_details(self, image_input) -> dict: |
| """Extract embedding, facial bounding box, and cropped face image. |
| image_input can be a file path str or numpy ndarray (BGR/RGB image). |
| """ |
| objs = DeepFace.represent( |
| img_path=image_input, |
| model_name=self.model_name, |
| enforce_detection=False, |
| detector_backend="opencv", |
| align=True |
| ) |
| if not objs: |
| return { |
| "embedding": np.zeros(128, dtype=np.float32), |
| "facial_area": {"x": 0, "y": 0, "w": 0, "h": 0}, |
| "confidence": 0.0 |
| } |
| |
| target = objs[0] |
| emb = np.array(target["embedding"], dtype=np.float32) |
| facial_area = target.get("facial_area", {"x": 0, "y": 0, "w": 0, "h": 0}) |
| |
| return { |
| "embedding": emb, |
| "facial_area": facial_area, |
| "confidence": target.get("face_confidence", 1.0) |
| } |
|
|
| def batch_compute_embeddings(self, image_paths: list, batch_size: int = 16) -> np.ndarray: |
| embeddings = [] |
| for path in image_paths: |
| emb = self.compute_embedding(path) |
| embeddings.append(emb) |
| return np.vstack(embeddings) |
|
|
|
|