cc1234 commited on
Commit
9b06224
·
1 Parent(s): 86e1f1d

feat: implement batch processing for face embeddings in EnsembleFaceRecognition

Browse files
models/face_recognition.py CHANGED
@@ -1,7 +1,9 @@
1
  import numpy as np
2
  from typing import Dict, List, Tuple
 
3
 
4
  from deepface import DeepFace
 
5
 
6
  class EnsembleFaceRecognition:
7
  def __init__(self, model_weights: Dict[str, float] = None):
@@ -37,6 +39,54 @@ class EnsembleFaceRecognition:
37
  'facenet': DeepFace.represent(img_path=image, detector_backend='skip', model_name='Facenet512', normalization='Facenet2018',align=True)[0]['embedding'],
38
  'arc': DeepFace.represent(img_path=image, detector_backend='skip', model_name='ArcFace',align=True)[0]['embedding']}
39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  def ensemble_prediction(self,
41
  model_predictions: Dict[str, Tuple[List[str], List[float]]],
42
  temperature: float = 0.1,
 
1
  import numpy as np
2
  from typing import Dict, List, Tuple
3
+ import cv2
4
 
5
  from deepface import DeepFace
6
+ from deepface.modules import modeling, preprocessing
7
 
8
  class EnsembleFaceRecognition:
9
  def __init__(self, model_weights: Dict[str, float] = None):
 
39
  'facenet': DeepFace.represent(img_path=image, detector_backend='skip', model_name='Facenet512', normalization='Facenet2018',align=True)[0]['embedding'],
40
  'arc': DeepFace.represent(img_path=image, detector_backend='skip', model_name='ArcFace',align=True)[0]['embedding']}
41
 
42
+ def _preprocess_face_batch(self, faces: np.ndarray, target_size: Tuple[int, int], normalization: str) -> np.ndarray:
43
+ """Preprocess a batch of face images for model inference"""
44
+ batch_size = faces.shape[0]
45
+ processed_faces = []
46
+
47
+ for i in range(batch_size):
48
+ face = faces[i]
49
+ # Convert RGB to BGR (DeepFace expects BGR)
50
+ face = face[:, :, ::-1]
51
+
52
+ # Resize to model input size
53
+ resized = preprocessing.resize_image(face, target_size)
54
+
55
+ # Normalize
56
+ normalized = preprocessing.normalize_input(resized, normalization)
57
+
58
+ processed_faces.append(normalized)
59
+
60
+ # Stack into batch and remove the extra dimension added by resize_image
61
+ batch = np.vstack(processed_faces)
62
+ return batch
63
+
64
+ def get_face_embeddings_batch(self, faces: np.ndarray) -> Dict[str, np.ndarray]:
65
+ """Get face embeddings for a batch of images efficiently
66
+
67
+ Args:
68
+ faces: np.ndarray of shape (batch_size, height, width, channels)
69
+
70
+ Returns:
71
+ Dict with 'facenet' and 'arc' keys containing batched embeddings
72
+ """
73
+ # Load models (cached by DeepFace)
74
+ facenet_model = modeling.build_model(task="facial_recognition", model_name="Facenet512")
75
+ arcface_model = modeling.build_model(task="facial_recognition", model_name="ArcFace")
76
+
77
+ # Preprocess faces for each model
78
+ facenet_batch = self._preprocess_face_batch(faces, facenet_model.input_shape, "Facenet2018")
79
+ arcface_batch = self._preprocess_face_batch(faces, arcface_model.input_shape, "ArcFace")
80
+
81
+ # Get embeddings using direct model inference (bypassing DeepFace.represent)
82
+ facenet_embeddings = facenet_model.model(facenet_batch, training=False).numpy()
83
+ arcface_embeddings = arcface_model.model(arcface_batch, training=False).numpy()
84
+
85
+ return {
86
+ 'facenet': facenet_embeddings,
87
+ 'arc': arcface_embeddings
88
+ }
89
+
90
  def ensemble_prediction(self,
91
  model_predictions: Dict[str, Tuple[List[str], List[float]]],
92
  temperature: float = 0.1,
models/image_processor.py CHANGED
@@ -22,13 +22,15 @@ def get_face_predictions(face, ensemble, data_manager, results):
22
  Returns:
23
  List of (name, confidence) tuples
24
  """
25
- # Get embeddings for original and flipped images
26
- embeddings_orig = ensemble.get_face_embeddings(face)
27
- embeddings_flip = ensemble.get_face_embeddings(np.fliplr(face))
28
-
29
- # Average the embeddings
30
- facenet = np.mean([embeddings_orig['facenet'], embeddings_flip['facenet']], axis=0)
31
- arc = np.mean([embeddings_orig['arc'], embeddings_flip['arc']], axis=0)
 
 
32
 
33
  # Get predictions from both models
34
  model_predictions = {
 
22
  Returns:
23
  List of (name, confidence) tuples
24
  """
25
+ # Create batch with original and flipped images
26
+ face_batch = np.stack([face, face[:, ::-1, :]], axis=0)
27
+
28
+ # Get embeddings for both orientations in one batch call
29
+ embeddings_batch = ensemble.get_face_embeddings_batch(face_batch)
30
+
31
+ # Average the embeddings across orientations
32
+ facenet = np.mean(embeddings_batch['facenet'], axis=0)
33
+ arc = np.mean(embeddings_batch['arc'], axis=0)
34
 
35
  # Get predictions from both models
36
  model_predictions = {