sol9x-sagar's picture
initial setup
2979822
"""Face detection."""
import cv2
import numpy as np
from typing import List, Dict
from pathlib import Path
def load_detector(
model_path: str,
input_size: tuple,
confidence_threshold: float = 0.8,
nms_threshold: float = 0.3,
top_k: int = 5000,
):
"""Load face detector."""
if not Path(model_path).exists():
return None
try:
return cv2.FaceDetectorYN.create(
str(model_path),
"",
input_size,
confidence_threshold,
nms_threshold,
top_k,
)
except Exception:
return None
def detect(
image: np.ndarray, detector, min_face_size: int = 60, margin: int = 5
) -> List[Dict]:
"""Detect faces. Filter by min size and edge margin. Return list of {bbox, confidence}."""
if detector is None or image is None:
return []
img_h, img_w = image.shape[:2]
detector.setInputSize((img_w, img_h))
_, faces = detector.detect(image)
if faces is None or len(faces) == 0:
return []
detections = []
for face in faces:
x, y, w, h = face[:4].astype(int)
# FaceDetectorYN returns [num_faces, 15] [web:47]
# In your previous code you used face[14]; keep it.
conf = float(face[14])
# Clip bbox instead of dropping it (prevents "no faces" due to tiny out-of-bounds)
x2 = x + w
y2 = y + h
x = max(0, x)
y = max(0, y)
x2 = min(img_w - 1, x2)
y2 = min(img_h - 1, y2)
w = max(1, x2 - x)
h = max(1, y2 - y)
# Edge margin filter
dist_left = x
dist_right = img_w - (x + w)
dist_top = y
dist_bottom = img_h - (y + h)
if min(dist_left, dist_right, dist_top, dist_bottom) < margin:
continue
if w >= min_face_size and h >= min_face_size:
detections.append(
{
"bbox": {
"x": float(x),
"y": float(y),
"width": float(w),
"height": float(h),
},
"confidence": conf,
}
)
return detections