feat: implement FaceEngine service with Haar Cascade detection, eye-based alignment, and ArcFace embedding extraction
Browse files
app/services/face_recognition.py
CHANGED
|
@@ -114,6 +114,19 @@ class FaceEngine:
|
|
| 114 |
face_img = cv2.resize(face_img, (112, 112))
|
| 115 |
return face_img
|
| 116 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 117 |
def _preprocess_face(self, image_bgr: np.ndarray, x: int, y: int, w: int, h: int, eye_centers: Optional[List[np.ndarray]] = None) -> np.ndarray:
|
| 118 |
"""Preprocess face for ArcFace: Align, Crop, Resize, Normalize."""
|
| 119 |
if eye_centers and len(eye_centers) >= 2:
|
|
@@ -143,6 +156,9 @@ class FaceEngine:
|
|
| 143 |
"box": None
|
| 144 |
}
|
| 145 |
|
|
|
|
|
|
|
|
|
|
| 146 |
|
| 147 |
try:
|
| 148 |
if self.detector is None:
|
|
|
|
| 114 |
face_img = cv2.resize(face_img, (112, 112))
|
| 115 |
return face_img
|
| 116 |
|
| 117 |
+
def _normalize_brightness(self, image_bgr: np.ndarray) -> np.ndarray:
|
| 118 |
+
"""Apply CLAHE to normalize lighting sensitivity."""
|
| 119 |
+
try:
|
| 120 |
+
lab = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2LAB)
|
| 121 |
+
l, a, b = cv2.split(lab)
|
| 122 |
+
clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8, 8))
|
| 123 |
+
cl = clahe.apply(l)
|
| 124 |
+
limg = cv2.merge((cl, a, b))
|
| 125 |
+
return cv2.cvtColor(limg, cv2.COLOR_LAB2BGR)
|
| 126 |
+
except Exception as e:
|
| 127 |
+
logger.warning(f"Brightness normalization failed: {e}")
|
| 128 |
+
return image_bgr
|
| 129 |
+
|
| 130 |
def _preprocess_face(self, image_bgr: np.ndarray, x: int, y: int, w: int, h: int, eye_centers: Optional[List[np.ndarray]] = None) -> np.ndarray:
|
| 131 |
"""Preprocess face for ArcFace: Align, Crop, Resize, Normalize."""
|
| 132 |
if eye_centers and len(eye_centers) >= 2:
|
|
|
|
| 156 |
"box": None
|
| 157 |
}
|
| 158 |
|
| 159 |
+
# Apply brightness normalization for better low-light handling
|
| 160 |
+
image_bgr = self._normalize_brightness(image_bgr)
|
| 161 |
+
|
| 162 |
|
| 163 |
try:
|
| 164 |
if self.detector is None:
|