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() 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: Args:
model_name (string): face recognition or facial attribute model model_name (str): model identifier
VGG-Face, Facenet, OpenFace, DeepFace, DeepID for face recognition - VGG-Face, Facenet, Facenet512, OpenFace, DeepFace, DeepID, Dlib,
Age, Gender, Emotion, Race for facial attributes 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: Returns:
built_model built_model
""" """
return modeling.build_model(model_name=model_name) return modeling.build_model(task=task, model_name=model_name)
def verify( 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 numpy as np
import cv2 import cv2
from deepface.modules import detection from deepface.modules import detection, modeling
from deepface.models.Detector import Detector, DetectedFace, FacialAreaRegion 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 from deepface.commons.logger import Logger
logger = 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( def detect_faces(
detector_backend: str, img: np.ndarray, align: bool = True, expand_percentage: int = 0 detector_backend: str, img: np.ndarray, align: bool = True, expand_percentage: int = 0
) -> List[DetectedFace]: ) -> List[DetectedFace]:
@ -87,7 +36,9 @@ def detect_faces(
""" """
height, width, _ = img.shape 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 # validate expand percentage score
if expand_percentage < 0: if expand_percentage < 0:

View File

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

View File

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

View File

@ -13,26 +13,43 @@ from deepface.basemodels import (
Facenet, Facenet,
GhostFaceNet, 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.extendedmodels import Age, Gender, Race, Emotion
from deepface.spoofmodels import FasNet 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: Parameters:
model_name (string): face recognition or facial attribute model task (str): facial_recognition, facial_attribute, face_detector, spoofing
VGG-Face, Facenet, OpenFace, DeepFace, DeepID for face recognition model_name (str): model identifier
Age, Gender, Emotion, Race for facial attributes - 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: Returns:
built model class built model class
""" """
# singleton design pattern # singleton design pattern
global model_obj global cached_models
models = { models = {
"facial_recognition": {
"VGG-Face": VGGFace.VggFaceClient, "VGG-Face": VGGFace.VggFaceClient,
"OpenFace": OpenFace.OpenFaceClient, "OpenFace": OpenFace.OpenFaceClient,
"Facenet": Facenet.FaceNet128dClient, "Facenet": Facenet.FaceNet128dClient,
@ -43,21 +60,41 @@ def build_model(model_name: str) -> Any:
"ArcFace": ArcFace.ArcFaceClient, "ArcFace": ArcFace.ArcFaceClient,
"SFace": SFace.SFaceClient, "SFace": SFace.SFaceClient,
"GhostFaceNet": GhostFaceNet.GhostFaceNetClient, "GhostFaceNet": GhostFaceNet.GhostFaceNetClient,
},
"spoofing": {
"Fasnet": FasNet.Fasnet,
},
"facial_attribute": {
"Emotion": Emotion.EmotionClient, "Emotion": Emotion.EmotionClient,
"Age": Age.ApparentAgeClient, "Age": Age.ApparentAgeClient,
"Gender": Gender.GenderClient, "Gender": Gender.GenderClient,
"Race": Race.RaceClient, "Race": Race.RaceClient,
"Fasnet": FasNet.Fasnet, },
"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(): if models.get(task) is None:
model_obj = {} raise ValueError(f"unimplemented task - {task}")
if not model_name in model_obj.keys(): if not "cached_models" in globals():
model = models.get(model_name) 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: if model:
model_obj[model_name] = model() cached_models[task][model_name] = model()
else: 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 = [] 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. # 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 Returns
input_shape (tuple): input shape of given facial recognitio n model. 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") 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: if enable_face_analysis is False:
return return
DeepFace.build_model(model_name="Age") DeepFace.build_model(task="facial_attribute", model_name="Age")
logger.info("Age model is just built") 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") 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") logger.info("Emotion model is just built")

View File

@ -100,7 +100,9 @@ def verify(
tic = time.time() 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 dims = model.output_shape
# extract faces from img1 # 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_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 target_size = model.input_shape