Merge pull request #1296 from serengil/feat-task-0408-managing-global-variables

manage global variables in single place
This commit is contained in:
Sefik Ilkin Serengil 2024-08-04 12:14:29 +01:00 committed by GitHub
commit 62055d09d2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 114 additions and 110 deletions

View File

@ -48,17 +48,23 @@ if tf_version == 2:
folder_utils.initialize_folder()
def build_model(model_name: str) -> Any:
def build_model(model_name: str, task: str = "facial_recognition") -> Any:
"""
This function builds a deepface model
This function builds a pre-trained model
Args:
model_name (string): face recognition or facial attribute model
VGG-Face, Facenet, OpenFace, DeepFace, DeepID for face recognition
Age, Gender, Emotion, Race for facial attributes
model_name (str): model identifier
- VGG-Face, Facenet, Facenet512, OpenFace, DeepFace, DeepID, Dlib,
ArcFace, SFace, GhostFaceNet for face recognition
- Age, Gender, Emotion, Race for facial attributes
- opencv, mtcnn, ssd, dlib, retinaface, mediapipe, yolov8, yunet,
fastmtcnn or centerface for face detectors
- Fasnet for spoofing
task (str): facial_recognition, facial_attribute, face_detector, spoofing
default is facial_recognition
Returns:
built_model
"""
return modeling.build_model(model_name=model_name)
return modeling.build_model(task=task, model_name=model_name)
def verify(

View File

@ -1 +1 @@
__version__ = "0.0.92"
__version__ = "0.0.93"

View File

@ -1,64 +1,13 @@
from typing import Any, List, Tuple
from typing import List, Tuple
import numpy as np
import cv2
from deepface.modules import detection
from deepface.modules import detection, modeling
from deepface.models.Detector import Detector, DetectedFace, FacialAreaRegion
from deepface.detectors import (
FastMtCnn,
MediaPipe,
MtCnn,
OpenCv,
Dlib,
RetinaFace,
Ssd,
Yolo,
YuNet,
CenterFace,
)
from deepface.commons.logger import Logger
logger = Logger()
def build_model(detector_backend: str) -> Any:
"""
Build a face detector model
Args:
detector_backend (str): backend detector name
Returns:
built detector (Any)
"""
global face_detector_obj # singleton design pattern
backends = {
"opencv": OpenCv.OpenCvClient,
"mtcnn": MtCnn.MtCnnClient,
"ssd": Ssd.SsdClient,
"dlib": Dlib.DlibClient,
"retinaface": RetinaFace.RetinaFaceClient,
"mediapipe": MediaPipe.MediaPipeClient,
"yolov8": Yolo.YoloClient,
"yunet": YuNet.YuNetClient,
"fastmtcnn": FastMtCnn.FastMtCnnClient,
"centerface": CenterFace.CenterFaceClient,
}
if not "face_detector_obj" in globals():
face_detector_obj = {}
built_models = list(face_detector_obj.keys())
if detector_backend not in built_models:
face_detector = backends.get(detector_backend)
if face_detector:
face_detector = face_detector()
face_detector_obj[detector_backend] = face_detector
else:
raise ValueError("invalid detector_backend passed - " + detector_backend)
return face_detector_obj[detector_backend]
def detect_faces(
detector_backend: str, img: np.ndarray, align: bool = True, expand_percentage: int = 0
) -> List[DetectedFace]:
@ -87,7 +36,9 @@ def detect_faces(
"""
height, width, _ = img.shape
face_detector: Detector = build_model(detector_backend)
face_detector: Detector = modeling.build_model(
task="face_detector", model_name=detector_backend
)
# validate expand percentage score
if expand_percentage < 0:

View File

@ -158,7 +158,9 @@ def analyze(
pbar.set_description(f"Action: {action}")
if action == "emotion":
emotion_predictions = modeling.build_model("Emotion").predict(img_content)
emotion_predictions = modeling.build_model(
task="facial_attribute", model_name="Emotion"
).predict(img_content)
sum_of_predictions = emotion_predictions.sum()
obj["emotion"] = {}
@ -169,12 +171,16 @@ def analyze(
obj["dominant_emotion"] = Emotion.labels[np.argmax(emotion_predictions)]
elif action == "age":
apparent_age = modeling.build_model("Age").predict(img_content)
apparent_age = modeling.build_model(
task="facial_attribute", model_name="Age"
).predict(img_content)
# int cast is for exception - object of type 'float32' is not JSON serializable
obj["age"] = int(apparent_age)
elif action == "gender":
gender_predictions = modeling.build_model("Gender").predict(img_content)
gender_predictions = modeling.build_model(
task="facial_attribute", model_name="Gender"
).predict(img_content)
obj["gender"] = {}
for i, gender_label in enumerate(Gender.labels):
gender_prediction = 100 * gender_predictions[i]
@ -183,7 +189,9 @@ def analyze(
obj["dominant_gender"] = Gender.labels[np.argmax(gender_predictions)]
elif action == "race":
race_predictions = modeling.build_model("Race").predict(img_content)
race_predictions = modeling.build_model(
task="facial_attribute", model_name="Race"
).predict(img_content)
sum_of_predictions = race_predictions.sum()
obj["race"] = {}

View File

@ -25,7 +25,7 @@ def extract_faces(
align: bool = True,
expand_percentage: int = 0,
grayscale: bool = False,
color_face: str = 'rgb',
color_face: str = "rgb",
normalize_face: bool = True,
anti_spoofing: bool = False,
) -> List[Dict[str, Any]]:
@ -126,16 +126,14 @@ def extract_faces(
logger.warn("Parameter grayscale is deprecated. Use color_face instead.")
current_img = cv2.cvtColor(current_img, cv2.COLOR_BGR2GRAY)
else:
if color_face == 'rgb':
if color_face == "rgb":
current_img = current_img[:, :, ::-1]
elif color_face == 'bgr':
elif color_face == "bgr":
pass # image is in BGR
elif color_face == 'gray':
elif color_face == "gray":
current_img = cv2.cvtColor(current_img, cv2.COLOR_BGR2GRAY)
else:
raise ValueError(
f"The color_face can be rgb, bgr or gray, but it is {color_face}."
)
raise ValueError(f"The color_face can be rgb, bgr or gray, but it is {color_face}.")
if normalize_face:
current_img = current_img / 255 # normalize input in [0, 1]
@ -159,7 +157,7 @@ def extract_faces(
}
if anti_spoofing is True:
antispoof_model = modeling.build_model(model_name="Fasnet")
antispoof_model = modeling.build_model(task="spoofing", model_name="Fasnet")
is_real, antispoof_score = antispoof_model.analyze(img=img, facial_area=(x, y, w, h))
resp_obj["is_real"] = is_real
resp_obj["antispoof_score"] = antispoof_score

View File

@ -13,51 +13,88 @@ from deepface.basemodels import (
Facenet,
GhostFaceNet,
)
from deepface.detectors import (
FastMtCnn,
MediaPipe,
MtCnn,
OpenCv,
Dlib as DlibDetector,
RetinaFace,
Ssd,
Yolo,
YuNet,
CenterFace,
)
from deepface.extendedmodels import Age, Gender, Race, Emotion
from deepface.spoofmodels import FasNet
def build_model(model_name: str) -> Any:
def build_model(task: str, model_name: str) -> Any:
"""
This function builds a deepface model
This function loads a pre-trained models as singletonish way
Parameters:
model_name (string): face recognition or facial attribute model
VGG-Face, Facenet, OpenFace, DeepFace, DeepID for face recognition
Age, Gender, Emotion, Race for facial attributes
task (str): facial_recognition, facial_attribute, face_detector, spoofing
model_name (str): model identifier
- VGG-Face, Facenet, Facenet512, OpenFace, DeepFace, DeepID, Dlib,
ArcFace, SFace, GhostFaceNet for face recognition
- Age, Gender, Emotion, Race for facial attributes
- opencv, mtcnn, ssd, dlib, retinaface, mediapipe, yolov8, yunet,
fastmtcnn or centerface for face detectors
- Fasnet for spoofing
Returns:
built model class
"""
# singleton design pattern
global model_obj
global cached_models
models = {
"VGG-Face": VGGFace.VggFaceClient,
"OpenFace": OpenFace.OpenFaceClient,
"Facenet": Facenet.FaceNet128dClient,
"Facenet512": Facenet.FaceNet512dClient,
"DeepFace": FbDeepFace.DeepFaceClient,
"DeepID": DeepID.DeepIdClient,
"Dlib": Dlib.DlibClient,
"ArcFace": ArcFace.ArcFaceClient,
"SFace": SFace.SFaceClient,
"GhostFaceNet": GhostFaceNet.GhostFaceNetClient,
"Emotion": Emotion.EmotionClient,
"Age": Age.ApparentAgeClient,
"Gender": Gender.GenderClient,
"Race": Race.RaceClient,
"Fasnet": FasNet.Fasnet,
"facial_recognition": {
"VGG-Face": VGGFace.VggFaceClient,
"OpenFace": OpenFace.OpenFaceClient,
"Facenet": Facenet.FaceNet128dClient,
"Facenet512": Facenet.FaceNet512dClient,
"DeepFace": FbDeepFace.DeepFaceClient,
"DeepID": DeepID.DeepIdClient,
"Dlib": Dlib.DlibClient,
"ArcFace": ArcFace.ArcFaceClient,
"SFace": SFace.SFaceClient,
"GhostFaceNet": GhostFaceNet.GhostFaceNetClient,
},
"spoofing": {
"Fasnet": FasNet.Fasnet,
},
"facial_attribute": {
"Emotion": Emotion.EmotionClient,
"Age": Age.ApparentAgeClient,
"Gender": Gender.GenderClient,
"Race": Race.RaceClient,
},
"face_detector": {
"opencv": OpenCv.OpenCvClient,
"mtcnn": MtCnn.MtCnnClient,
"ssd": Ssd.SsdClient,
"dlib": DlibDetector.DlibClient,
"retinaface": RetinaFace.RetinaFaceClient,
"mediapipe": MediaPipe.MediaPipeClient,
"yolov8": Yolo.YoloClient,
"yunet": YuNet.YuNetClient,
"fastmtcnn": FastMtCnn.FastMtCnnClient,
"centerface": CenterFace.CenterFaceClient,
},
}
if not "model_obj" in globals():
model_obj = {}
if models.get(task) is None:
raise ValueError(f"unimplemented task - {task}")
if not model_name in model_obj.keys():
model = models.get(model_name)
if not "cached_models" in globals():
cached_models = {current_task: {} for current_task in models.keys()}
if cached_models[task].get(model_name) is None:
model = models[task].get(model_name)
if model:
model_obj[model_name] = model()
cached_models[task][model_name] = model()
else:
raise ValueError(f"Invalid model_name passed - {model_name}")
raise ValueError(f"Invalid model_name passed - {task}/{model_name}")
return model_obj[model_name]
return cached_models[task][model_name]

View File

@ -65,7 +65,9 @@ def represent(
"""
resp_objs = []
model: FacialRecognition = modeling.build_model(model_name)
model: FacialRecognition = modeling.build_model(
task="facial_recognition", model_name=model_name
)
# ---------------------------------
# we have run pre-process in verification. so, this can be skipped if it is coming from verify.

View File

@ -171,7 +171,7 @@ def build_facial_recognition_model(model_name: str) -> None:
Returns
input_shape (tuple): input shape of given facial recognitio n model.
"""
_ = DeepFace.build_model(model_name=model_name)
_ = DeepFace.build_model(task="facial_recognition", model_name=model_name)
logger.info(f"{model_name} is built")
@ -267,11 +267,11 @@ def build_demography_models(enable_face_analysis: bool) -> None:
"""
if enable_face_analysis is False:
return
DeepFace.build_model(model_name="Age")
DeepFace.build_model(task="facial_attribute", model_name="Age")
logger.info("Age model is just built")
DeepFace.build_model(model_name="Gender")
DeepFace.build_model(task="facial_attribute", model_name="Gender")
logger.info("Gender model is just built")
DeepFace.build_model(model_name="Emotion")
DeepFace.build_model(task="facial_attribute", model_name="Emotion")
logger.info("Emotion model is just built")

View File

@ -100,7 +100,9 @@ def verify(
tic = time.time()
model: FacialRecognition = modeling.build_model(model_name)
model: FacialRecognition = modeling.build_model(
task="facial_recognition", model_name=model_name
)
dims = model.output_shape
# extract faces from img1

View File

@ -1,3 +1,3 @@
{
"version": "0.0.92"
"version": "0.0.93"
}

View File

@ -16,7 +16,7 @@ logger = Logger()
model_name = "VGG-Face"
model: FacialRecognition = DeepFace.build_model(model_name=model_name)
model: FacialRecognition = DeepFace.build_model(task="facial_recognition", model_name=model_name)
target_size = model.input_shape