cosmetic changes about interfaces

This commit is contained in:
Sefik Ilkin Serengil 2024-01-21 13:52:31 +00:00
parent 70b4f1a722
commit 0d6aa10b82
26 changed files with 196 additions and 120 deletions

View File

@ -1,5 +1,6 @@
import os
import gdown
import numpy as np
from deepface.commons import functions
from deepface.commons.logger import Logger
from deepface.models.FacialRecognition import FacialRecognition
@ -43,7 +44,7 @@ else:
)
# pylint: disable=too-few-public-methods
class ArcFace(FacialRecognition):
class ArcFaceClient(FacialRecognition):
"""
ArcFace model class
"""
@ -52,6 +53,18 @@ class ArcFace(FacialRecognition):
self.model = load_model()
self.model_name = "ArcFace"
def find_embeddings(self, img: np.ndarray) -> list:
"""
find embeddings with ArcFace model
Args:
img (np.ndarray): pre-loaded image in BGR
Returns
embeddings (list): multi-dimensional vector
"""
# model.predict causes memory issue when it is called in a for loop
# embedding = model.predict(img, verbose=0)[0].tolist()
return self.model(img, training=False).numpy()[0].tolist()
def load_model(
url="https://github.com/serengil/deepface_models/releases/download/v1.0/arcface_weights.h5",

View File

@ -1,5 +1,6 @@
import os
import gdown
import numpy as np
from deepface.commons import functions
from deepface.commons.logger import Logger
from deepface.models.FacialRecognition import FacialRecognition
@ -39,7 +40,7 @@ else:
# -------------------------------------
# pylint: disable=too-few-public-methods
class DeepId(FacialRecognition):
class DeepIdClient(FacialRecognition):
"""
DeepId model class
"""
@ -48,6 +49,18 @@ class DeepId(FacialRecognition):
self.model = load_model()
self.model_name = "DeepId"
def find_embeddings(self, img: np.ndarray) -> list:
"""
find embeddings with DeepId model
Args:
img (np.ndarray): pre-loaded image in BGR
Returns
embeddings (list): multi-dimensional vector
"""
# model.predict causes memory issue when it is called in a for loop
# embedding = model.predict(img, verbose=0)[0].tolist()
return self.model(img, training=False).numpy()[0].tolist()
def load_model(
url="https://github.com/serengil/deepface_models/releases/download/v1.0/deepid_keras_weights.h5",

View File

@ -11,7 +11,7 @@ logger = Logger(module="basemodels.DlibResNet")
# pylint: disable=too-few-public-methods
class Dlib(FacialRecognition):
class DlibClient(FacialRecognition):
"""
Dlib model class
"""
@ -22,13 +22,31 @@ class Dlib(FacialRecognition):
def find_embeddings(self, img: np.ndarray) -> list:
"""
Custom find embeddings function of Dlib different than FacialRecognition's one
find embeddings with Dlib model - different than regular models
Args:
img (np.ndarray)
Retunrs:
embeddings (list)
img (np.ndarray): pre-loaded image in BGR
Returns
embeddings (list): multi-dimensional vector
"""
return self.model.predict(img)[0].tolist()
# return self.model.predict(img)[0].tolist()
# extract_faces returns 4 dimensional images
if len(img.shape) == 4:
img = img[0]
# bgr to rgb
img = img[:, :, ::-1] # bgr to rgb
# img is in scale of [0, 1] but expected [0, 255]
if img.max() <= 1:
img = img * 255
img = img.astype(np.uint8)
img_representation = self.model.model.compute_face_descriptor(img)
img_representation = np.array(img_representation)
img_representation = np.expand_dims(img_representation, axis=0)
return img_representation[0].tolist()
class DlibResNet:
@ -69,38 +87,12 @@ class DlibResNet:
# ---------------------
model = dlib.face_recognition_model_v1(weight_file)
self.__model = model
self.model = dlib.face_recognition_model_v1(weight_file)
# ---------------------
# return None # classes must return None
def predict(self, img_aligned: np.ndarray) -> np.ndarray:
# functions.detectFace returns 4 dimensional images
if len(img_aligned.shape) == 4:
img_aligned = img_aligned[0]
# functions.detectFace returns bgr images
img_aligned = img_aligned[:, :, ::-1] # bgr to rgb
# deepface.detectFace returns an array in scale of [0, 1]
# but dlib expects in scale of [0, 255]
if img_aligned.max() <= 1:
img_aligned = img_aligned * 255
img_aligned = img_aligned.astype(np.uint8)
model = self.__model
img_representation = model.compute_face_descriptor(img_aligned)
img_representation = np.array(img_representation)
img_representation = np.expand_dims(img_representation, axis=0)
return img_representation
class DlibMetaData:
def __init__(self):

View File

@ -1,5 +1,6 @@
import os
import gdown
import numpy as np
from deepface.commons import functions
from deepface.commons.logger import Logger
from deepface.models.FacialRecognition import FacialRecognition
@ -43,7 +44,7 @@ else:
# --------------------------------
# pylint: disable=too-few-public-methods
class FaceNet128d(FacialRecognition):
class FaceNet128dClient(FacialRecognition):
"""
FaceNet-128d model class
"""
@ -52,8 +53,20 @@ class FaceNet128d(FacialRecognition):
self.model = load_facenet128d_model()
self.model_name = "FaceNet-128d"
def find_embeddings(self, img: np.ndarray) -> list:
"""
find embeddings with FaceNet-128d model
Args:
img (np.ndarray): pre-loaded image in BGR
Returns
embeddings (list): multi-dimensional vector
"""
# model.predict causes memory issue when it is called in a for loop
# embedding = model.predict(img, verbose=0)[0].tolist()
return self.model(img, training=False).numpy()[0].tolist()
class FaceNet512d(FacialRecognition):
class FaceNet512dClient(FacialRecognition):
"""
FaceNet-1512d model class
"""
@ -62,6 +75,18 @@ class FaceNet512d(FacialRecognition):
self.model = load_facenet512d_model()
self.model_name = "FaceNet-512d"
def find_embeddings(self, img: np.ndarray) -> list:
"""
find embeddings with FaceNet-512d model
Args:
img (np.ndarray): pre-loaded image in BGR
Returns
embeddings (list): multi-dimensional vector
"""
# model.predict causes memory issue when it is called in a for loop
# embedding = model.predict(img, verbose=0)[0].tolist()
return self.model(img, training=False).numpy()[0].tolist()
def scaling(x, scale):
return x * scale

View File

@ -1,6 +1,7 @@
import os
import zipfile
import gdown
import numpy as np
from deepface.commons import functions
from deepface.commons.logger import Logger
from deepface.models.FacialRecognition import FacialRecognition
@ -36,7 +37,7 @@ else:
# -------------------------------------
# pylint: disable=line-too-long, too-few-public-methods
class DeepFace(FacialRecognition):
class DeepFaceClient(FacialRecognition):
"""
Fb's DeepFace model class
"""
@ -45,6 +46,18 @@ class DeepFace(FacialRecognition):
self.model = load_model()
self.model_name = "DeepFace"
def find_embeddings(self, img: np.ndarray) -> list:
"""
find embeddings with OpenFace model
Args:
img (np.ndarray): pre-loaded image in BGR
Returns
embeddings (list): multi-dimensional vector
"""
# model.predict causes memory issue when it is called in a for loop
# embedding = model.predict(img, verbose=0)[0].tolist()
return self.model(img, training=False).numpy()[0].tolist()
def load_model(
url="https://github.com/swghosh/DeepFace/releases/download/weights-vggface2-2d-aligned/VGGFace2_DeepFace_weights_val-0.9034.h5.zip",

View File

@ -1,6 +1,7 @@
import os
import gdown
import tensorflow as tf
import numpy as np
from deepface.commons import functions
from deepface.commons.logger import Logger
from deepface.models.FacialRecognition import FacialRecognition
@ -26,7 +27,7 @@ else:
# ---------------------------------------
# pylint: disable=too-few-public-methods
class OpenFace(FacialRecognition):
class OpenFaceClient(FacialRecognition):
"""
OpenFace model class
"""
@ -35,6 +36,18 @@ class OpenFace(FacialRecognition):
self.model = load_model()
self.model_name = "OpenFace"
def find_embeddings(self, img: np.ndarray) -> list:
"""
find embeddings with OpenFace model
Args:
img (np.ndarray): pre-loaded image in BGR
Returns
embeddings (list): multi-dimensional vector
"""
# model.predict causes memory issue when it is called in a for loop
# embedding = model.predict(img, verbose=0)[0].tolist()
return self.model(img, training=False).numpy()[0].tolist()
def load_model(
url="https://github.com/serengil/deepface_models/releases/download/v1.0/openface_weights.h5",

View File

@ -14,7 +14,7 @@ logger = Logger(module="basemodels.SFace")
# pylint: disable=line-too-long, too-few-public-methods
class SFace(FacialRecognition):
class SFaceClient(FacialRecognition):
"""
SFace model class
"""
@ -25,13 +25,20 @@ class SFace(FacialRecognition):
def find_embeddings(self, img: np.ndarray) -> list:
"""
Custom find embeddings function of SFace different than FacialRecognition's one
find embeddings with SFace model - different than regular models
Args:
img (np.ndarray)
Retunrs:
embeddings (list)
img (np.ndarray): pre-loaded image in BGR
Returns
embeddings (list): multi-dimensional vector
"""
return self.model.predict(img)[0].tolist()
# return self.model.predict(img)[0].tolist()
# revert the image to original format and preprocess using the model
input_blob = (img[0] * 255).astype(np.uint8)
embeddings = self.model.model.feature(input_blob)
return embeddings[0].tolist()
def load_model(
@ -74,17 +81,6 @@ class SFaceWrapper:
self.layers = [_Layer()]
def predict(self, image: np.ndarray) -> np.ndarray:
# Preprocess
input_blob = (image[0] * 255).astype(
np.uint8
) # revert the image to original format and preprocess using the model
# Forward
embeddings = self.model.feature(input_blob)
return embeddings
class _Layer:
input_shape = (None, 112, 112, 3)

View File

@ -1,5 +1,6 @@
import os
import gdown
import numpy as np
from deepface.commons import functions
from deepface.commons.logger import Logger
from deepface.models.FacialRecognition import FacialRecognition
@ -37,7 +38,7 @@ else:
# ---------------------------------------
# pylint: disable=too-few-public-methods
class VggFace(FacialRecognition):
class VggFaceClient(FacialRecognition):
"""
VGG-Face model class
"""
@ -46,6 +47,18 @@ class VggFace(FacialRecognition):
self.model = load_model()
self.model_name = "VGG-Face"
def find_embeddings(self, img: np.ndarray) -> list:
"""
find embeddings with VGG-Face model
Args:
img (np.ndarray): pre-loaded image in BGR
Returns
embeddings (list): multi-dimensional vector
"""
# model.predict causes memory issue when it is called in a for loop
# embedding = model.predict(img, verbose=0)[0].tolist()
return self.model(img, training=False).numpy()[0].tolist()
def base_model() -> Sequential:
"""

View File

@ -2,15 +2,15 @@ from typing import Any
import numpy as np
from deepface.models.Detector import Detector
from deepface.detectors import (
OpenCvWrapper,
SsdWrapper,
DlibWrapper,
MtcnnWrapper,
RetinaFaceWrapper,
MediapipeWrapper,
YoloWrapper,
YunetWrapper,
FastMtcnnWrapper,
FastMtCnn,
MediaPipe,
MtCnn,
OpenCv,
Dlib,
RetinaFace,
Ssd,
Yolo,
YuNet,
)
@ -25,15 +25,15 @@ def build_model(detector_backend: str) -> Any:
global face_detector_obj # singleton design pattern
backends = {
"opencv": OpenCvWrapper.OpenCv,
"mtcnn": MtcnnWrapper.MtCnn,
"ssd": SsdWrapper.Ssd,
"dlib": DlibWrapper.Dlib,
"retinaface": RetinaFaceWrapper.RetinaFace,
"mediapipe": MediapipeWrapper.MediaPipe,
"yolov8": YoloWrapper.Yolo,
"yunet": YunetWrapper.YuNet,
"fastmtcnn": FastMtcnnWrapper.FastMtCnn,
"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,
}
if not "face_detector_obj" in globals():

View File

@ -9,7 +9,7 @@ from deepface.commons.logger import Logger
logger = Logger(module="detectors.DlibWrapper")
class Dlib(Detector):
class DlibClient(Detector):
def __init__(self):
self.model = self.build_model()

View File

@ -7,7 +7,7 @@ from deepface.models.Detector import Detector
# Examples https://www.kaggle.com/timesler/guide-to-mtcnn-in-facenet-pytorch
class FastMtCnn(Detector):
class FastMtCnnClient(Detector):
def __init__(self):
self.model = self.build_model()

View File

@ -5,7 +5,7 @@ from deepface.models.Detector import Detector
# Link - https://google.github.io/mediapipe/solutions/face_detection
class MediaPipe(Detector):
class MediaPipeClient(Detector):
def __init__(self):
self.model = self.build_model()

View File

@ -4,7 +4,7 @@ from mtcnn import MTCNN
from deepface.models.Detector import Detector
class MtCnn(Detector):
class MtCnnClient(Detector):
"""
Class to cover common face detection functionalitiy for MtCnn backend
"""

View File

@ -5,7 +5,7 @@ import numpy as np
from deepface.models.Detector import Detector
class OpenCv(Detector):
class OpenCvClient(Detector):
"""
Class to cover common face detection functionalitiy for OpenCv backend
"""

View File

@ -4,7 +4,7 @@ from retinaface.commons import postprocess
from deepface.models.Detector import Detector
class RetinaFace(Detector):
class RetinaFaceClient(Detector):
def __init__(self):
self.model = rf.build_model()

View File

@ -3,7 +3,7 @@ import gdown
import cv2
import pandas as pd
import numpy as np
from deepface.detectors import OpenCvWrapper
from deepface.detectors import OpenCv
from deepface.commons import functions
from deepface.models.Detector import Detector
from deepface.commons.logger import Logger
@ -13,7 +13,7 @@ logger = Logger(module="detectors.SsdWrapper")
# pylint: disable=line-too-long
class Ssd(Detector):
class SsdClient(Detector):
def __init__(self):
self.model = self.build_model()
@ -65,7 +65,7 @@ class Ssd(Detector):
detector = {}
detector["face_detector"] = face_detector
detector["opencv_module"] = OpenCvWrapper.OpenCv()
detector["opencv_module"] = OpenCv.OpenCvClient()
return detector
@ -134,7 +134,7 @@ class Ssd(Detector):
confidence = instance["confidence"]
if align:
opencv_module: OpenCvWrapper.OpenCv = self.model["opencv_module"]
opencv_module: OpenCv.OpenCv = self.model["opencv_module"]
left_eye, right_eye = opencv_module.find_eyes(detected_face)
detected_face = self.align_face(
img=detected_face, left_eye=left_eye, right_eye=right_eye

View File

@ -16,7 +16,7 @@ WEIGHT_URL = "https://drive.google.com/uc?id=1qcr9DbgsX3ryrz2uU8w4Xm3cOrRywXqb"
LANDMARKS_CONFIDENCE_THRESHOLD = 0.5
class Yolo(Detector):
class YoloClient(Detector):
def __init__(self):
self.model = self.build_model()

View File

@ -10,7 +10,7 @@ from deepface.models.Detector import Detector
logger = Logger(module="detectors.YunetWrapper")
class YuNet(Detector):
class YuNetClient(Detector):
def __init__(self):
self.model = self.build_model()

View File

@ -23,7 +23,7 @@ else:
# ----------------------------------------
# pylint: disable=too-few-public-methods
class ApparentAge(Demography):
class ApparentAgeClient(Demography):
"""
Age model class
"""

View File

@ -33,7 +33,7 @@ else:
labels = ["angry", "disgust", "fear", "happy", "sad", "surprise", "neutral"]
# pylint: disable=too-few-public-methods
class FacialExpression(Demography):
class EmotionClient(Demography):
"""
Emotion model class
"""

View File

@ -26,7 +26,7 @@ else:
labels = ["Woman", "Man"]
# pylint: disable=too-few-public-methods
class Gender(Demography):
class GenderClient(Demography):
"""
Gender model class
"""

View File

@ -25,7 +25,7 @@ else:
labels = ["asian", "indian", "black", "white", "middle eastern", "latino hispanic"]
# pylint: disable=too-few-public-methods
class Race(Demography):
class RaceClient(Demography):
"""
Race model class
"""

View File

@ -1,5 +1,5 @@
from abc import ABC, abstractmethod
from typing import Union
from typing import Union, Optional
import numpy as np
from PIL import Image
@ -12,7 +12,10 @@ class Detector(ABC):
pass
def align_face(
self, img: np.ndarray, left_eye: Union[list, tuple], right_eye: Union[list, tuple]
self,
img: np.ndarray,
left_eye: Optional[Union[list, tuple]] = None,
right_eye: Optional[Union[list, tuple]] = None,
) -> np.ndarray:
"""
Align a given image horizantally with respect to their left and right eye locations

View File

@ -1,4 +1,4 @@
from abc import ABC
from abc import ABC, abstractmethod
from typing import Any, Union
import numpy as np
from deepface.commons import functions
@ -16,13 +16,6 @@ class FacialRecognition(ABC):
model: Union[Model, Any]
model_name: str
@abstractmethod
def find_embeddings(self, img: np.ndarray) -> list:
if not isinstance(self.model, Model):
raise ValueError(
"If a facial recognition model is not type of (tf.)keras.models.Model,"
"Then its find_embeddings method must be implemented its own module."
f"However {self.model_name}'s model type is {type(self.model)}"
)
# model.predict causes memory issue when it is called in a for loop
# embedding = model.predict(img, verbose=0)[0].tolist()
return self.model(img, training=False).numpy()[0].tolist()
pass

View File

@ -5,12 +5,12 @@ from typing import Any
from deepface.basemodels import (
VGGFace,
OpenFace,
Facenet,
FbDeepFace,
DeepID,
DlibResNet,
ArcFace,
SFace,
Dlib,
FaceNet,
)
from deepface.extendedmodels import Age, Gender, Race, Emotion
@ -31,19 +31,19 @@ def build_model(model_name: str) -> Any:
global model_obj
models = {
"VGG-Face": VGGFace.VggFace,
"OpenFace": OpenFace.OpenFace,
"Facenet": Facenet.FaceNet128d,
"Facenet512": Facenet.FaceNet512d,
"DeepFace": FbDeepFace.DeepFace,
"DeepID": DeepID.DeepId,
"Dlib": DlibResNet.Dlib,
"ArcFace": ArcFace.ArcFace,
"SFace": SFace.SFace,
"Emotion": Emotion.FacialExpression,
"Age": Age.ApparentAge,
"Gender": Gender.Gender,
"Race": Race.Race,
"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,
"Emotion": Emotion.EmotionClient,
"Age": Age.ApparentAgeClient,
"Gender": Gender.GenderClient,
"Race": Race.RaceClient,
}
if not "model_obj" in globals():

View File

@ -14,11 +14,12 @@ model_names = [
"Facenet512",
"OpenFace",
"DeepFace",
"DeepID",
# "DeepID",
"Dlib",
"ArcFace",
"SFace",
]
detector_backends = ["opencv", "ssd", "dlib", "mtcnn", "retinaface"]
@ -44,10 +45,11 @@ dfs = DeepFace.find(
for df in dfs:
logger.info(df)
# extract faces
for detector_backend in detector_backends:
face_objs = DeepFace.extract_faces(
img_path="dataset/img1.jpg", detector_backend=detector_backend
img_path="dataset/img11.jpg", detector_backend=detector_backend
)
for face_obj in face_objs:
face = face_obj["face"]