77from app .models .YOLO import YOLO
88from app .database .faces import db_insert_face_embeddings_by_image_id
99from app .logging .setup_logging import get_logger
10+ from app .config .settings import (
11+ PICTO_CLUSTERING_CONF_THRESHOLD ,
12+ PICTO_CLUSTERING_BLUR_THRESHOLD ,
13+ PICTO_CLUSTERING_MIN_FACE_SIZE ,
14+ )
15+ from app .utils .face_quality import face_passes_quality_gate
1016
1117# Initialize logger
1218logger = get_logger (__name__ )
@@ -16,7 +22,7 @@ class FaceDetector:
1622 def __init__ (self ):
1723 self .yolo_detector = YOLO (
1824 YOLO_util_get_model_path ("face" ),
19- conf_threshold = 0.45 ,
25+ conf_threshold = PICTO_CLUSTERING_CONF_THRESHOLD ,
2026 iou_threshold = 0.45 ,
2127 )
2228 self .facenet = FaceNet (FaceNet_util_get_model_path ())
@@ -34,26 +40,38 @@ def detect_faces(self, image_id: str, image_path: str, forSearch: bool = False):
3440 logger .info (f"Detected { len (boxes )} faces in image { image_id } ." )
3541
3642 processed_faces , embeddings , bboxes , confidences = [], [], [], []
43+ faces_skipped = 0
3744
3845 for box , score in zip (boxes , scores ):
39- if score > self .yolo_detector .conf_threshold :
40- x1 , y1 , x2 , y2 = map (int , box )
46+ x1 , y1 , x2 , y2 = map (int , box )
4147
42- # Create bounding box dictionary in JSON format
43- bbox = {"x" : x1 , "y" : y1 , "width" : x2 - x1 , "height" : y2 - y1 }
44- bboxes .append (bbox )
45- confidences .append (float (score ))
48+ padding = 20
49+ face_img = img [
50+ max (0 , y1 - padding ) : min (img .shape [0 ], y2 + padding ),
51+ max (0 , x1 - padding ) : min (img .shape [1 ], x2 + padding ),
52+ ]
4653
47- padding = 20
48- face_img = img [
49- max (0 , y1 - padding ) : min (img .shape [0 ], y2 + padding ),
50- max (0 , x1 - padding ) : min (img .shape [1 ], x2 + padding ),
51- ]
52- processed_face = FaceNet_util_preprocess_image (face_img )
53- processed_faces .append (processed_face )
54+ if not face_passes_quality_gate (
55+ face_crop = face_img ,
56+ bbox = (x1 , y1 , x2 , y2 ),
57+ conf_score = float (score ),
58+ conf_threshold = self .yolo_detector .conf_threshold ,
59+ blur_threshold = PICTO_CLUSTERING_BLUR_THRESHOLD ,
60+ min_face_size = PICTO_CLUSTERING_MIN_FACE_SIZE ,
61+ ):
62+ faces_skipped += 1
63+ continue
5464
55- embedding = self .facenet .get_embedding (processed_face )
56- embeddings .append (embedding )
65+ # Create bounding box dictionary in JSON format
66+ bbox = {"x" : x1 , "y" : y1 , "width" : x2 - x1 , "height" : y2 - y1 }
67+ bboxes .append (bbox )
68+ confidences .append (float (score ))
69+
70+ processed_face = FaceNet_util_preprocess_image (face_img )
71+ processed_faces .append (processed_face )
72+
73+ embedding = self .facenet .get_embedding (processed_face )
74+ embeddings .append (embedding )
5775
5876 if not forSearch and embeddings :
5977 db_insert_face_embeddings_by_image_id (
@@ -64,6 +82,7 @@ def detect_faces(self, image_id: str, image_path: str, forSearch: bool = False):
6482 "ids" : f"{ class_ids } " ,
6583 "processed_faces" : processed_faces ,
6684 "num_faces" : len (embeddings ),
85+ "faces_skipped" : faces_skipped ,
6786 }
6887
6988 def close (self ):
0 commit comments