From a65f87a65aca689da7c8f1fca4a260c915c96223 Mon Sep 17 00:00:00 2001 From: kremnik Date: Tue, 27 Aug 2024 06:06:39 +0300 Subject: [PATCH] Optimize ssd detector --- deepface/models/face_detection/Ssd.py | 95 +++++++++++---------------- tests/test_extract_faces.py | 2 +- 2 files changed, 39 insertions(+), 58 deletions(-) diff --git a/deepface/models/face_detection/Ssd.py b/deepface/models/face_detection/Ssd.py index 6f8460b02..d7d65083a 100644 --- a/deepface/models/face_detection/Ssd.py +++ b/deepface/models/face_detection/Ssd.py @@ -2,7 +2,6 @@ import os import gdown import cv2 -import pandas as pd import numpy as np from deepface.models.face_detection import OpenCv from deepface.commons import folder_utils @@ -50,11 +49,10 @@ def build_model(self) -> dict: + "You can install it as pip install opencv-contrib-python." ) from err - detector = {} - detector["face_detector"] = face_detector - detector["opencv_module"] = OpenCv.OpenCvClient() - - return detector + return { + "face_detector": face_detector, + "opencv_module": OpenCv.OpenCvClient() + } def detect_faces(self, img: np.ndarray) -> List[FacialAreaRegion]: """ @@ -66,13 +64,12 @@ def detect_faces(self, img: np.ndarray) -> List[FacialAreaRegion]: Returns: results (List[FacialAreaRegion]): A list of FacialAreaRegion objects """ - opencv_module: OpenCv.OpenCvClient = self.model["opencv_module"] - - resp = [] - detected_face = None + # Because cv2.dnn.blobFromImage expects CV_8U (8-bit unsigned integer) values + if img.dtype != np.uint8: + img = img.astype(np.uint8) - ssd_labels = ["img_id", "is_face", "confidence", "left", "top", "right", "bottom"] + opencv_module: OpenCv.OpenCvClient = self.model["opencv_module"] target_size = (300, 300) @@ -89,51 +86,35 @@ def detect_faces(self, img: np.ndarray) -> List[FacialAreaRegion]: face_detector.setInput(imageBlob) detections = face_detector.forward() - detections_df = pd.DataFrame(detections[0][0], columns=ssd_labels) - - detections_df = detections_df[detections_df["is_face"] == 1] # 0: background, 1: face - detections_df = detections_df[detections_df["confidence"] >= 0.90] - - detections_df["left"] = (detections_df["left"] * 300).astype(int) - detections_df["bottom"] = (detections_df["bottom"] * 300).astype(int) - detections_df["right"] = (detections_df["right"] * 300).astype(int) - detections_df["top"] = (detections_df["top"] * 300).astype(int) - - if detections_df.shape[0] > 0: - - for _, instance in detections_df.iterrows(): - - left = instance["left"] - right = instance["right"] - bottom = instance["bottom"] - top = instance["top"] - confidence = instance["confidence"] - - x = int(left * aspect_ratio_x) - y = int(top * aspect_ratio_y) - w = int(right * aspect_ratio_x) - int(left * aspect_ratio_x) - h = int(bottom * aspect_ratio_y) - int(top * aspect_ratio_y) - - detected_face = img[int(y) : int(y + h), int(x) : int(x + w)] - - left_eye, right_eye = opencv_module.find_eyes(detected_face) - - # eyes found in the detected face instead image itself - # detected face's coordinates should be added - if left_eye is not None: - left_eye = (int(x + left_eye[0]), int(y + left_eye[1])) - if right_eye is not None: - right_eye = (int(x + right_eye[0]), int(y + right_eye[1])) - - facial_area = FacialAreaRegion( - x=x, - y=y, - w=w, - h=h, - left_eye=left_eye, - right_eye=right_eye, - confidence=confidence, - ) - resp.append(facial_area) + faces = detections[0][0] + faces = faces[(faces[:, 1] == 1) & (faces[:, 2] >= 0.90)] + faces[:, 3:7] = np.int32(faces[:, 3:7] * 300) + faces[:, 3:7] = np.int32(faces[:, 3:7] * [aspect_ratio_x, aspect_ratio_y, aspect_ratio_x, aspect_ratio_y]) + faces[:, 5:7] -= faces[:, 3:5] + resp = [] + for face in faces: + confidence = face[2] + x, y, w, h = map(int, face[3:7]) + detected_face = img[y : y + h, x : x + w] + + left_eye, right_eye = opencv_module.find_eyes(detected_face) + + # eyes found in the detected face instead image itself + # detected face's coordinates should be added + if left_eye is not None: + left_eye = x + int(left_eye[0]), y + int(left_eye[1]) + if right_eye is not None: + right_eye = x + int(right_eye[0]), y + int(right_eye[1]) + + facial_area = FacialAreaRegion( + x=x, + y=y, + w=w, + h=h, + left_eye=left_eye, + right_eye=right_eye, + confidence=confidence, + ) + resp.append(facial_area) return resp diff --git a/tests/test_extract_faces.py b/tests/test_extract_faces.py index 1d8f84940..ba141e233 100644 --- a/tests/test_extract_faces.py +++ b/tests/test_extract_faces.py @@ -13,7 +13,7 @@ logger = Logger() -detectors = ["opencv", "mtcnn"] +detectors = ["opencv", "mtcnn", "ssd"] def test_different_detectors():