mirror of
https://github.com/serengil/deepface.git
synced 2025-06-07 20:15:21 +00:00
using type hinting for backend functions
This commit is contained in:
parent
58945bd14d
commit
f23ab85fd1
@ -889,8 +889,12 @@ def extract_faces(
|
|||||||
|
|
||||||
@deprecated(version="0.0.78", reason="Use DeepFace.extract_faces instead of DeepFace.detectFace")
|
@deprecated(version="0.0.78", reason="Use DeepFace.extract_faces instead of DeepFace.detectFace")
|
||||||
def detectFace(
|
def detectFace(
|
||||||
img_path, target_size=(224, 224), detector_backend="opencv", enforce_detection=True, align=True
|
img_path: Union[str, np.ndarray],
|
||||||
):
|
target_size: tuple = (224, 224),
|
||||||
|
detector_backend: str = "opencv",
|
||||||
|
enforce_detection: bool = True,
|
||||||
|
align: bool = True,
|
||||||
|
) -> np.ndarray:
|
||||||
"""
|
"""
|
||||||
Deprecated function. Use extract_faces for same functionality.
|
Deprecated function. Use extract_faces for same functionality.
|
||||||
|
|
||||||
@ -942,7 +946,7 @@ def detectFace(
|
|||||||
functions.initialize_folder()
|
functions.initialize_folder()
|
||||||
|
|
||||||
|
|
||||||
def cli():
|
def cli() -> None:
|
||||||
"""
|
"""
|
||||||
command line interface function will be offered in this block
|
command line interface function will be offered in this block
|
||||||
"""
|
"""
|
||||||
|
@ -14,8 +14,8 @@ logger = Logger(module="basemodels.ArcFace")
|
|||||||
tf_version = int(tf.__version__.split(".", maxsplit=1)[0])
|
tf_version = int(tf.__version__.split(".", maxsplit=1)[0])
|
||||||
|
|
||||||
if tf_version == 1:
|
if tf_version == 1:
|
||||||
|
from keras.models import Model
|
||||||
from keras.engine import training
|
from keras.engine import training
|
||||||
import keras
|
|
||||||
from keras.layers import (
|
from keras.layers import (
|
||||||
ZeroPadding2D,
|
ZeroPadding2D,
|
||||||
Input,
|
Input,
|
||||||
@ -28,8 +28,8 @@ if tf_version == 1:
|
|||||||
Dense,
|
Dense,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
from tensorflow.keras.models import Model
|
||||||
from tensorflow.python.keras.engine import training
|
from tensorflow.python.keras.engine import training
|
||||||
from tensorflow import keras
|
|
||||||
from tensorflow.keras.layers import (
|
from tensorflow.keras.layers import (
|
||||||
ZeroPadding2D,
|
ZeroPadding2D,
|
||||||
Input,
|
Input,
|
||||||
@ -41,15 +41,11 @@ else:
|
|||||||
Flatten,
|
Flatten,
|
||||||
Dense,
|
Dense,
|
||||||
)
|
)
|
||||||
# --------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
# url = "https://drive.google.com/uc?id=1LVB3CdVejpmGHM28BpqqkbZP5hDEcdZY"
|
|
||||||
|
|
||||||
|
|
||||||
def loadModel(
|
def loadModel(
|
||||||
url="https://github.com/serengil/deepface_models/releases/download/v1.0/arcface_weights.h5",
|
url="https://github.com/serengil/deepface_models/releases/download/v1.0/arcface_weights.h5",
|
||||||
):
|
) -> Model:
|
||||||
base_model = ResNet34()
|
base_model = ResNet34()
|
||||||
inputs = base_model.inputs[0]
|
inputs = base_model.inputs[0]
|
||||||
arcface_model = base_model.outputs[0]
|
arcface_model = base_model.outputs[0]
|
||||||
@ -62,7 +58,7 @@ def loadModel(
|
|||||||
embedding = BatchNormalization(momentum=0.9, epsilon=2e-5, name="embedding", scale=True)(
|
embedding = BatchNormalization(momentum=0.9, epsilon=2e-5, name="embedding", scale=True)(
|
||||||
arcface_model
|
arcface_model
|
||||||
)
|
)
|
||||||
model = keras.models.Model(inputs, embedding, name=base_model.name)
|
model = Model(inputs, embedding, name=base_model.name)
|
||||||
|
|
||||||
# ---------------------------------------
|
# ---------------------------------------
|
||||||
# check the availability of pre-trained weights
|
# check the availability of pre-trained weights
|
||||||
@ -84,7 +80,7 @@ def loadModel(
|
|||||||
return model
|
return model
|
||||||
|
|
||||||
|
|
||||||
def ResNet34():
|
def ResNet34() -> Model:
|
||||||
|
|
||||||
img_input = Input(shape=(112, 112, 3))
|
img_input = Input(shape=(112, 112, 3))
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ else:
|
|||||||
|
|
||||||
def loadModel(
|
def loadModel(
|
||||||
url="https://github.com/serengil/deepface_models/releases/download/v1.0/deepid_keras_weights.h5",
|
url="https://github.com/serengil/deepface_models/releases/download/v1.0/deepid_keras_weights.h5",
|
||||||
):
|
) -> Model:
|
||||||
|
|
||||||
myInput = Input(shape=(55, 47, 3))
|
myInput = Input(shape=(55, 47, 3))
|
||||||
|
|
||||||
|
@ -13,8 +13,14 @@ logger = Logger(module="basemodels.DlibResNet")
|
|||||||
class DlibResNet:
|
class DlibResNet:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
# this is not a must dependency
|
## this is not a must dependency. do not import it in the global level.
|
||||||
import dlib # 19.20.0
|
try:
|
||||||
|
import dlib
|
||||||
|
except ModuleNotFoundError as e:
|
||||||
|
raise ImportError(
|
||||||
|
"Dlib is an optional dependency, ensure the library is installed."
|
||||||
|
"Please install using 'pip install dlib' "
|
||||||
|
) from e
|
||||||
|
|
||||||
self.layers = [DlibMetaData()]
|
self.layers = [DlibMetaData()]
|
||||||
|
|
||||||
@ -49,7 +55,7 @@ class DlibResNet:
|
|||||||
|
|
||||||
# return None # classes must return None
|
# return None # classes must return None
|
||||||
|
|
||||||
def predict(self, img_aligned):
|
def predict(self, img_aligned: np.ndarray) -> np.ndarray:
|
||||||
|
|
||||||
# functions.detectFace returns 4 dimensional images
|
# functions.detectFace returns 4 dimensional images
|
||||||
if len(img_aligned.shape) == 4:
|
if len(img_aligned.shape) == 4:
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
|
from typing import Any
|
||||||
from deepface.basemodels.DlibResNet import DlibResNet
|
from deepface.basemodels.DlibResNet import DlibResNet
|
||||||
|
|
||||||
|
|
||||||
def loadModel():
|
def loadModel() -> Any:
|
||||||
return DlibResNet()
|
return DlibResNet()
|
||||||
|
@ -47,7 +47,7 @@ def scaling(x, scale):
|
|||||||
return x * scale
|
return x * scale
|
||||||
|
|
||||||
|
|
||||||
def InceptionResNetV2(dimension=128):
|
def InceptionResNetV2(dimension=128) -> Model:
|
||||||
|
|
||||||
inputs = Input(shape=(160, 160, 3))
|
inputs = Input(shape=(160, 160, 3))
|
||||||
x = Conv2D(32, 3, strides=2, padding="valid", use_bias=False, name="Conv2d_1a_3x3")(inputs)
|
x = Conv2D(32, 3, strides=2, padding="valid", use_bias=False, name="Conv2d_1a_3x3")(inputs)
|
||||||
@ -1618,12 +1618,9 @@ def InceptionResNetV2(dimension=128):
|
|||||||
return model
|
return model
|
||||||
|
|
||||||
|
|
||||||
# url = 'https://drive.google.com/uc?id=1971Xk5RwedbudGgTIrGAL4F7Aifu7id1'
|
|
||||||
|
|
||||||
|
|
||||||
def loadModel(
|
def loadModel(
|
||||||
url="https://github.com/serengil/deepface_models/releases/download/v1.0/facenet_weights.h5",
|
url="https://github.com/serengil/deepface_models/releases/download/v1.0/facenet_weights.h5",
|
||||||
):
|
) -> Model:
|
||||||
model = InceptionResNetV2()
|
model = InceptionResNetV2()
|
||||||
|
|
||||||
# -----------------------------------
|
# -----------------------------------
|
||||||
|
@ -1,14 +1,23 @@
|
|||||||
import os
|
import os
|
||||||
import gdown
|
import gdown
|
||||||
|
import tensorflow as tf
|
||||||
from deepface.basemodels import Facenet
|
from deepface.basemodels import Facenet
|
||||||
from deepface.commons import functions
|
from deepface.commons import functions
|
||||||
from deepface.commons.logger import Logger
|
from deepface.commons.logger import Logger
|
||||||
|
|
||||||
logger = Logger(module="basemodels.Facenet512")
|
logger = Logger(module="basemodels.Facenet512")
|
||||||
|
|
||||||
|
tf_version = int(tf.__version__.split(".", maxsplit=1)[0])
|
||||||
|
|
||||||
|
if tf_version == 1:
|
||||||
|
from keras.models import Model
|
||||||
|
else:
|
||||||
|
from tensorflow.keras.models import Model
|
||||||
|
|
||||||
|
|
||||||
def loadModel(
|
def loadModel(
|
||||||
url="https://github.com/serengil/deepface_models/releases/download/v1.0/facenet512_weights.h5",
|
url="https://github.com/serengil/deepface_models/releases/download/v1.0/facenet512_weights.h5",
|
||||||
):
|
) -> Model:
|
||||||
|
|
||||||
model = Facenet.InceptionResNetV2(dimension=512)
|
model = Facenet.InceptionResNetV2(dimension=512)
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ else:
|
|||||||
|
|
||||||
def loadModel(
|
def loadModel(
|
||||||
url="https://github.com/swghosh/DeepFace/releases/download/weights-vggface2-2d-aligned/VGGFace2_DeepFace_weights_val-0.9034.h5.zip",
|
url="https://github.com/swghosh/DeepFace/releases/download/weights-vggface2-2d-aligned/VGGFace2_DeepFace_weights_val-0.9034.h5.zip",
|
||||||
):
|
) -> Model:
|
||||||
base_model = Sequential()
|
base_model = Sequential()
|
||||||
base_model.add(
|
base_model.add(
|
||||||
Convolution2D(32, (11, 11), activation="relu", name="C1", input_shape=(152, 152, 3))
|
Convolution2D(32, (11, 11), activation="relu", name="C1", input_shape=(152, 152, 3))
|
||||||
|
@ -27,7 +27,7 @@ else:
|
|||||||
|
|
||||||
def loadModel(
|
def loadModel(
|
||||||
url="https://github.com/serengil/deepface_models/releases/download/v1.0/openface_weights.h5",
|
url="https://github.com/serengil/deepface_models/releases/download/v1.0/openface_weights.h5",
|
||||||
):
|
) -> Model:
|
||||||
myInput = Input(shape=(96, 96, 3))
|
myInput = Input(shape=(96, 96, 3))
|
||||||
|
|
||||||
x = ZeroPadding2D(padding=(3, 3), input_shape=(96, 96, 3))(myInput)
|
x = ZeroPadding2D(padding=(3, 3), input_shape=(96, 96, 3))(myInput)
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import os
|
import os
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import cv2 as cv
|
import cv2 as cv
|
||||||
import gdown
|
import gdown
|
||||||
@ -25,7 +27,7 @@ class SFaceModel:
|
|||||||
|
|
||||||
self.layers = [_Layer()]
|
self.layers = [_Layer()]
|
||||||
|
|
||||||
def predict(self, image):
|
def predict(self, image: np.ndarray) -> np.ndarray:
|
||||||
# Preprocess
|
# Preprocess
|
||||||
input_blob = (image[0] * 255).astype(
|
input_blob = (image[0] * 255).astype(
|
||||||
np.uint8
|
np.uint8
|
||||||
@ -39,7 +41,7 @@ class SFaceModel:
|
|||||||
|
|
||||||
def load_model(
|
def load_model(
|
||||||
url="https://github.com/opencv/opencv_zoo/raw/main/models/face_recognition_sface/face_recognition_sface_2021dec.onnx",
|
url="https://github.com/opencv/opencv_zoo/raw/main/models/face_recognition_sface/face_recognition_sface_2021dec.onnx",
|
||||||
):
|
) -> Any:
|
||||||
|
|
||||||
home = functions.get_deepface_home()
|
home = functions.get_deepface_home()
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ else:
|
|||||||
# ---------------------------------------
|
# ---------------------------------------
|
||||||
|
|
||||||
|
|
||||||
def baseModel():
|
def baseModel() -> Sequential:
|
||||||
model = Sequential()
|
model = Sequential()
|
||||||
model.add(ZeroPadding2D((1, 1), input_shape=(224, 224, 3)))
|
model.add(ZeroPadding2D((1, 1), input_shape=(224, 224, 3)))
|
||||||
model.add(Convolution2D(64, (3, 3), activation="relu"))
|
model.add(Convolution2D(64, (3, 3), activation="relu"))
|
||||||
@ -83,17 +83,12 @@ def baseModel():
|
|||||||
return model
|
return model
|
||||||
|
|
||||||
|
|
||||||
# url = 'https://drive.google.com/uc?id=1CPSeum3HpopfomUEK1gybeuIVoeJT_Eo'
|
|
||||||
|
|
||||||
|
|
||||||
def loadModel(
|
def loadModel(
|
||||||
url="https://github.com/serengil/deepface_models/releases/download/v1.0/vgg_face_weights.h5",
|
url="https://github.com/serengil/deepface_models/releases/download/v1.0/vgg_face_weights.h5",
|
||||||
):
|
) -> Model:
|
||||||
|
|
||||||
model = baseModel()
|
model = baseModel()
|
||||||
|
|
||||||
# -----------------------------------
|
|
||||||
|
|
||||||
home = functions.get_deepface_home()
|
home = functions.get_deepface_home()
|
||||||
output = home + "/.deepface/weights/vgg_face_weights.h5"
|
output = home + "/.deepface/weights/vgg_face_weights.h5"
|
||||||
|
|
||||||
@ -101,13 +96,8 @@ def loadModel(
|
|||||||
logger.info("vgg_face_weights.h5 will be downloaded...")
|
logger.info("vgg_face_weights.h5 will be downloaded...")
|
||||||
gdown.download(url, output, quiet=False)
|
gdown.download(url, output, quiet=False)
|
||||||
|
|
||||||
# -----------------------------------
|
|
||||||
|
|
||||||
model.load_weights(output)
|
model.load_weights(output)
|
||||||
|
|
||||||
# -----------------------------------
|
|
||||||
|
|
||||||
# TO-DO: why?
|
|
||||||
vgg_face_descriptor = Model(inputs=model.layers[0].input, outputs=model.layers[-2].output)
|
vgg_face_descriptor = Model(inputs=model.layers[0].input, outputs=model.layers[-2].output)
|
||||||
|
|
||||||
return vgg_face_descriptor
|
return vgg_face_descriptor
|
||||||
|
@ -1,14 +1,25 @@
|
|||||||
|
from typing import Union
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
def findCosineDistance(source_representation, test_representation):
|
def findCosineDistance(
|
||||||
|
source_representation: Union[np.ndarray, list], test_representation: Union[np.ndarray, list]
|
||||||
|
) -> np.float64:
|
||||||
|
if isinstance(source_representation, list):
|
||||||
|
source_representation = np.array(source_representation)
|
||||||
|
|
||||||
|
if isinstance(test_representation, list):
|
||||||
|
test_representation = np.array(test_representation)
|
||||||
|
|
||||||
a = np.matmul(np.transpose(source_representation), test_representation)
|
a = np.matmul(np.transpose(source_representation), test_representation)
|
||||||
b = np.sum(np.multiply(source_representation, source_representation))
|
b = np.sum(np.multiply(source_representation, source_representation))
|
||||||
c = np.sum(np.multiply(test_representation, test_representation))
|
c = np.sum(np.multiply(test_representation, test_representation))
|
||||||
return 1 - (a / (np.sqrt(b) * np.sqrt(c)))
|
return 1 - (a / (np.sqrt(b) * np.sqrt(c)))
|
||||||
|
|
||||||
|
|
||||||
def findEuclideanDistance(source_representation, test_representation):
|
def findEuclideanDistance(
|
||||||
|
source_representation: Union[np.ndarray, list], test_representation: Union[np.ndarray, list]
|
||||||
|
) -> np.float64:
|
||||||
if isinstance(source_representation, list):
|
if isinstance(source_representation, list):
|
||||||
source_representation = np.array(source_representation)
|
source_representation = np.array(source_representation)
|
||||||
|
|
||||||
@ -21,11 +32,11 @@ def findEuclideanDistance(source_representation, test_representation):
|
|||||||
return euclidean_distance
|
return euclidean_distance
|
||||||
|
|
||||||
|
|
||||||
def l2_normalize(x):
|
def l2_normalize(x: np.ndarray) -> np.ndarray:
|
||||||
return x / np.sqrt(np.sum(np.multiply(x, x)))
|
return x / np.sqrt(np.sum(np.multiply(x, x)))
|
||||||
|
|
||||||
|
|
||||||
def findThreshold(model_name, distance_metric):
|
def findThreshold(model_name: str, distance_metric: str) -> float:
|
||||||
|
|
||||||
base_threshold = {"cosine": 0.40, "euclidean": 0.55, "euclidean_l2": 0.75}
|
base_threshold = {"cosine": 0.40, "euclidean": 0.55, "euclidean_l2": 0.75}
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import os
|
import os
|
||||||
|
from typing import Union, Tuple
|
||||||
import base64
|
import base64
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from PIL import Image
|
|
||||||
import requests
|
|
||||||
|
|
||||||
# 3rd party dependencies
|
# 3rd party dependencies
|
||||||
|
from PIL import Image
|
||||||
|
import requests
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import cv2
|
import cv2
|
||||||
import tensorflow as tf
|
import tensorflow as tf
|
||||||
@ -33,7 +34,7 @@ elif tf_major_version == 2:
|
|||||||
# --------------------------------------------------
|
# --------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
def initialize_folder():
|
def initialize_folder() -> None:
|
||||||
"""Initialize the folder for storing weights and models.
|
"""Initialize the folder for storing weights and models.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
@ -52,7 +53,7 @@ def initialize_folder():
|
|||||||
logger.info(f"Directory {home}/.deepface/weights created")
|
logger.info(f"Directory {home}/.deepface/weights created")
|
||||||
|
|
||||||
|
|
||||||
def get_deepface_home():
|
def get_deepface_home() -> str:
|
||||||
"""Get the home directory for storing weights and models.
|
"""Get the home directory for storing weights and models.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@ -64,7 +65,7 @@ def get_deepface_home():
|
|||||||
# --------------------------------------------------
|
# --------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
def loadBase64Img(uri):
|
def loadBase64Img(uri: str) -> np.ndarray:
|
||||||
"""Load image from base64 string.
|
"""Load image from base64 string.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -80,7 +81,7 @@ def loadBase64Img(uri):
|
|||||||
return img_bgr
|
return img_bgr
|
||||||
|
|
||||||
|
|
||||||
def load_image(img):
|
def load_image(img: Union[str, np.ndarray]) -> Tuple[np.ndarray, str]:
|
||||||
"""
|
"""
|
||||||
Load image from path, url, base64 or numpy array.
|
Load image from path, url, base64 or numpy array.
|
||||||
Args:
|
Args:
|
||||||
@ -91,15 +92,18 @@ def load_image(img):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# The image is already a numpy array
|
# The image is already a numpy array
|
||||||
if type(img).__module__ == np.__name__:
|
if isinstance(img, np.ndarray):
|
||||||
return img, None
|
return img, "numpy array"
|
||||||
|
|
||||||
if isinstance(img, Path):
|
if isinstance(img, Path):
|
||||||
img = str(img)
|
img = str(img)
|
||||||
|
|
||||||
|
if not isinstance(img, str):
|
||||||
|
raise ValueError(f"img must be numpy array or str but it is {type(img)}")
|
||||||
|
|
||||||
# The image is a base64 string
|
# The image is a base64 string
|
||||||
if img.startswith("data:image/"):
|
if img.startswith("data:image/"):
|
||||||
return loadBase64Img(img), None
|
return loadBase64Img(img), "base64 encoded string"
|
||||||
|
|
||||||
# The image is a url
|
# The image is a url
|
||||||
if img.startswith("http"):
|
if img.startswith("http"):
|
||||||
@ -128,13 +132,13 @@ def load_image(img):
|
|||||||
|
|
||||||
|
|
||||||
def extract_faces(
|
def extract_faces(
|
||||||
img,
|
img: Union[str, np.ndarray],
|
||||||
target_size=(224, 224),
|
target_size: tuple = (224, 224),
|
||||||
detector_backend="opencv",
|
detector_backend: str = "opencv",
|
||||||
grayscale=False,
|
grayscale: bool = False,
|
||||||
enforce_detection=True,
|
enforce_detection: bool = True,
|
||||||
align=True,
|
align: bool = True,
|
||||||
):
|
) -> list:
|
||||||
"""Extract faces from an image.
|
"""Extract faces from an image.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -252,7 +256,7 @@ def extract_faces(
|
|||||||
return extracted_faces
|
return extracted_faces
|
||||||
|
|
||||||
|
|
||||||
def normalize_input(img, normalization="base"):
|
def normalize_input(img: np.ndarray, normalization: str = "base") -> np.ndarray:
|
||||||
"""Normalize input image.
|
"""Normalize input image.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -310,7 +314,7 @@ def normalize_input(img, normalization="base"):
|
|||||||
return img
|
return img
|
||||||
|
|
||||||
|
|
||||||
def find_target_size(model_name):
|
def find_target_size(model_name: str) -> tuple:
|
||||||
"""Find the target size of the model.
|
"""Find the target size of the model.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -346,17 +350,18 @@ def find_target_size(model_name):
|
|||||||
|
|
||||||
@deprecated(version="0.0.78", reason="Use extract_faces instead of preprocess_face")
|
@deprecated(version="0.0.78", reason="Use extract_faces instead of preprocess_face")
|
||||||
def preprocess_face(
|
def preprocess_face(
|
||||||
img,
|
img: Union[str, np.ndarray],
|
||||||
target_size=(224, 224),
|
target_size=(224, 224),
|
||||||
detector_backend="opencv",
|
detector_backend="opencv",
|
||||||
grayscale=False,
|
grayscale=False,
|
||||||
enforce_detection=True,
|
enforce_detection=True,
|
||||||
align=True,
|
align=True,
|
||||||
):
|
) -> Union[np.ndarray, None]:
|
||||||
"""Preprocess face.
|
"""
|
||||||
|
Preprocess only one face
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
img (numpy array): the input image.
|
img (str or numpy): the input image.
|
||||||
target_size (tuple, optional): the target size. Defaults to (224, 224).
|
target_size (tuple, optional): the target size. Defaults to (224, 224).
|
||||||
detector_backend (str, optional): the detector backend. Defaults to "opencv".
|
detector_backend (str, optional): the detector backend. Defaults to "opencv".
|
||||||
grayscale (bool, optional): whether to convert to grayscale. Defaults to False.
|
grayscale (bool, optional): whether to convert to grayscale. Defaults to False.
|
||||||
@ -364,7 +369,7 @@ def preprocess_face(
|
|||||||
align (bool, optional): whether to align the face. Defaults to True.
|
align (bool, optional): whether to align the face. Defaults to True.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
numpy array: the preprocessed face.
|
loaded image (numpt): the preprocessed face.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
ValueError: if face is not detected and enforce_detection is True.
|
ValueError: if face is not detected and enforce_detection is True.
|
||||||
|
@ -12,7 +12,8 @@ class Logger:
|
|||||||
except Exception as err:
|
except Exception as err:
|
||||||
self.dump_log(
|
self.dump_log(
|
||||||
f"Exception while parsing $DEEPFACE_LOG_LEVEL."
|
f"Exception while parsing $DEEPFACE_LOG_LEVEL."
|
||||||
f"Expected int but it is {log_level} ({str(err)})"
|
f"Expected int but it is {log_level} ({str(err)})."
|
||||||
|
"Setting app log level to info."
|
||||||
)
|
)
|
||||||
self.log_level = logging.INFO
|
self.log_level = logging.INFO
|
||||||
|
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
import os
|
import os
|
||||||
import bz2
|
import bz2
|
||||||
import gdown
|
import gdown
|
||||||
|
import numpy as np
|
||||||
from deepface.commons import functions
|
from deepface.commons import functions
|
||||||
from deepface.commons.logger import Logger
|
from deepface.commons.logger import Logger
|
||||||
|
|
||||||
logger = Logger(module="detectors.DlibWrapper")
|
logger = Logger(module="detectors.DlibWrapper")
|
||||||
|
|
||||||
|
|
||||||
def build_model():
|
def build_model() -> dict:
|
||||||
|
"""
|
||||||
|
Build a dlib hog face detector model
|
||||||
|
Returns:
|
||||||
|
model (Any)
|
||||||
|
"""
|
||||||
home = functions.get_deepface_home()
|
home = functions.get_deepface_home()
|
||||||
|
|
||||||
# this is not a must dependency. do not import it in the global level.
|
# this is not a must dependency. do not import it in the global level.
|
||||||
@ -46,8 +51,16 @@ def build_model():
|
|||||||
return detector
|
return detector
|
||||||
|
|
||||||
|
|
||||||
def detect_face(detector, img, align=True):
|
def detect_face(detector: dict, img: np.ndarray, align: bool = True) -> list:
|
||||||
|
"""
|
||||||
|
Detect and align face with dlib
|
||||||
|
Args:
|
||||||
|
face_detector (Any): dlib face detector object
|
||||||
|
img (np.ndarray): pre-loaded image
|
||||||
|
align (bool): default is true
|
||||||
|
Returns:
|
||||||
|
list of detected and aligned faces
|
||||||
|
"""
|
||||||
# this is not a must dependency. do not import it in the global level.
|
# this is not a must dependency. do not import it in the global level.
|
||||||
try:
|
try:
|
||||||
import dlib
|
import dlib
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
from typing import Any, Union
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from deepface.detectors import (
|
from deepface.detectors import (
|
||||||
@ -13,7 +14,14 @@ from deepface.detectors import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def build_model(detector_backend):
|
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
|
global face_detector_obj # singleton design pattern
|
||||||
|
|
||||||
backends = {
|
backends = {
|
||||||
@ -44,7 +52,20 @@ def build_model(detector_backend):
|
|||||||
return face_detector_obj[detector_backend]
|
return face_detector_obj[detector_backend]
|
||||||
|
|
||||||
|
|
||||||
def detect_face(face_detector, detector_backend, img, align=True):
|
def detect_face(
|
||||||
|
face_detector: Any, detector_backend: str, img: np.ndarray, align: bool = True
|
||||||
|
) -> tuple:
|
||||||
|
"""
|
||||||
|
Detect a single face from a given image
|
||||||
|
Args:
|
||||||
|
face_detector (Any): pre-built face detector object
|
||||||
|
detector_backend (str): detector name
|
||||||
|
img (np.ndarray): pre-loaded image
|
||||||
|
alig (bool): enable or disable alignment after detection
|
||||||
|
Returns
|
||||||
|
result (tuple): tuple of face (np.ndarray), face region (list)
|
||||||
|
, confidence score (float)
|
||||||
|
"""
|
||||||
obj = detect_faces(face_detector, detector_backend, img, align)
|
obj = detect_faces(face_detector, detector_backend, img, align)
|
||||||
|
|
||||||
if len(obj) > 0:
|
if len(obj) > 0:
|
||||||
@ -60,7 +81,20 @@ def detect_face(face_detector, detector_backend, img, align=True):
|
|||||||
return face, region, confidence
|
return face, region, confidence
|
||||||
|
|
||||||
|
|
||||||
def detect_faces(face_detector, detector_backend, img, align=True):
|
def detect_faces(
|
||||||
|
face_detector: Any, detector_backend: str, img: np.ndarray, align: bool = True
|
||||||
|
) -> list:
|
||||||
|
"""
|
||||||
|
Detect face(s) from a given image
|
||||||
|
Args:
|
||||||
|
face_detector (Any): pre-built face detector object
|
||||||
|
detector_backend (str): detector name
|
||||||
|
img (np.ndarray): pre-loaded image
|
||||||
|
alig (bool): enable or disable alignment after detection
|
||||||
|
Returns
|
||||||
|
result (list): tuple of face (np.ndarray), face region (list)
|
||||||
|
, confidence score (float)
|
||||||
|
"""
|
||||||
backends = {
|
backends = {
|
||||||
"opencv": OpenCvWrapper.detect_face,
|
"opencv": OpenCvWrapper.detect_face,
|
||||||
"ssd": SsdWrapper.detect_face,
|
"ssd": SsdWrapper.detect_face,
|
||||||
@ -83,18 +117,32 @@ def detect_faces(face_detector, detector_backend, img, align=True):
|
|||||||
raise ValueError("invalid detector_backend passed - " + detector_backend)
|
raise ValueError("invalid detector_backend passed - " + detector_backend)
|
||||||
|
|
||||||
|
|
||||||
def get_alignment_angle_arctan2(left_eye, right_eye):
|
def get_alignment_angle_arctan2(
|
||||||
|
left_eye: Union[list, tuple], right_eye: Union[list, tuple]
|
||||||
|
) -> float:
|
||||||
"""
|
"""
|
||||||
The left_eye is the eye to the left of the viewer,
|
Find the angle between eyes
|
||||||
i.e., right eye of the person in the image.
|
Args:
|
||||||
The top-left point of the frame is (0, 0).
|
left_eye: coordinates of left eye with respect to the you
|
||||||
|
right_eye: coordinates of right eye with respect to the you
|
||||||
|
Returns:
|
||||||
|
angle (float)
|
||||||
"""
|
"""
|
||||||
return float(np.degrees(
|
return float(np.degrees(np.arctan2(right_eye[1] - left_eye[1], right_eye[0] - left_eye[0])))
|
||||||
np.arctan2(right_eye[1] - left_eye[1], right_eye[0] - left_eye[0])
|
|
||||||
))
|
|
||||||
|
|
||||||
|
|
||||||
def alignment_procedure(img, left_eye, right_eye):
|
def alignment_procedure(
|
||||||
|
img: np.ndarray, left_eye: Union[list, tuple], right_eye: Union[list, tuple]
|
||||||
|
) -> np.ndarray:
|
||||||
|
"""
|
||||||
|
Rotate given image until eyes are on a horizontal line
|
||||||
|
Args:
|
||||||
|
img (np.ndarray): pre-loaded image
|
||||||
|
left_eye: coordinates of left eye with respect to the you
|
||||||
|
right_eye: coordinates of right eye with respect to the you
|
||||||
|
Returns:
|
||||||
|
result (np.ndarray): aligned face
|
||||||
|
"""
|
||||||
angle = get_alignment_angle_arctan2(left_eye, right_eye)
|
angle = get_alignment_angle_arctan2(left_eye, right_eye)
|
||||||
img = Image.fromarray(img)
|
img = Image.fromarray(img)
|
||||||
img = np.array(img.rotate(angle))
|
img = np.array(img.rotate(angle))
|
||||||
|
@ -1,11 +1,18 @@
|
|||||||
|
from typing import Any, Union
|
||||||
import cv2
|
import cv2
|
||||||
|
import numpy as np
|
||||||
from deepface.detectors import FaceDetector
|
from deepface.detectors import FaceDetector
|
||||||
|
|
||||||
# Link -> https://github.com/timesler/facenet-pytorch
|
# Link -> https://github.com/timesler/facenet-pytorch
|
||||||
# Examples https://www.kaggle.com/timesler/guide-to-mtcnn-in-facenet-pytorch
|
# Examples https://www.kaggle.com/timesler/guide-to-mtcnn-in-facenet-pytorch
|
||||||
|
|
||||||
|
|
||||||
def build_model():
|
def build_model() -> Any:
|
||||||
|
"""
|
||||||
|
Build a fast mtcnn face detector model
|
||||||
|
Returns:
|
||||||
|
model (Any)
|
||||||
|
"""
|
||||||
# this is not a must dependency. do not import it in the global level.
|
# this is not a must dependency. do not import it in the global level.
|
||||||
try:
|
try:
|
||||||
from facenet_pytorch import MTCNN as fast_mtcnn
|
from facenet_pytorch import MTCNN as fast_mtcnn
|
||||||
@ -25,7 +32,7 @@ def build_model():
|
|||||||
return face_detector
|
return face_detector
|
||||||
|
|
||||||
|
|
||||||
def xyxy_to_xywh(xyxy):
|
def xyxy_to_xywh(xyxy: Union[list, tuple]) -> list:
|
||||||
"""
|
"""
|
||||||
Convert xyxy format to xywh format.
|
Convert xyxy format to xywh format.
|
||||||
"""
|
"""
|
||||||
@ -35,8 +42,16 @@ def xyxy_to_xywh(xyxy):
|
|||||||
return [x, y, w, h]
|
return [x, y, w, h]
|
||||||
|
|
||||||
|
|
||||||
def detect_face(face_detector, img, align=True):
|
def detect_face(face_detector: Any, img: np.ndarray, align: bool = True) -> list:
|
||||||
|
"""
|
||||||
|
Detect and align face with mtcnn
|
||||||
|
Args:
|
||||||
|
face_detector (Any): mtcnn face detector object
|
||||||
|
img (np.ndarray): pre-loaded image
|
||||||
|
align (bool): default is true
|
||||||
|
Returns:
|
||||||
|
list of detected and aligned faces
|
||||||
|
"""
|
||||||
resp = []
|
resp = []
|
||||||
|
|
||||||
detected_face = None
|
detected_face = None
|
||||||
|
@ -1,9 +1,16 @@
|
|||||||
|
from typing import Any
|
||||||
|
import numpy as np
|
||||||
from deepface.detectors import FaceDetector
|
from deepface.detectors import FaceDetector
|
||||||
|
|
||||||
# Link - https://google.github.io/mediapipe/solutions/face_detection
|
# Link - https://google.github.io/mediapipe/solutions/face_detection
|
||||||
|
|
||||||
|
|
||||||
def build_model():
|
def build_model() -> Any:
|
||||||
|
"""
|
||||||
|
Build a mediapipe face detector model
|
||||||
|
Returns:
|
||||||
|
model (Any)
|
||||||
|
"""
|
||||||
# this is not a must dependency. do not import it in the global level.
|
# this is not a must dependency. do not import it in the global level.
|
||||||
try:
|
try:
|
||||||
import mediapipe as mp
|
import mediapipe as mp
|
||||||
@ -18,7 +25,16 @@ def build_model():
|
|||||||
return face_detection
|
return face_detection
|
||||||
|
|
||||||
|
|
||||||
def detect_face(face_detector, img, align=True):
|
def detect_face(face_detector: Any, img: np.ndarray, align: bool = True) -> list:
|
||||||
|
"""
|
||||||
|
Detect and align face with mediapipe
|
||||||
|
Args:
|
||||||
|
face_detector (Any): mediapipe face detector object
|
||||||
|
img (np.ndarray): pre-loaded image
|
||||||
|
align (bool): default is true
|
||||||
|
Returns:
|
||||||
|
list of detected and aligned faces
|
||||||
|
"""
|
||||||
resp = []
|
resp = []
|
||||||
|
|
||||||
img_width = img.shape[1]
|
img_width = img.shape[1]
|
||||||
|
@ -1,15 +1,31 @@
|
|||||||
|
from typing import Any
|
||||||
import cv2
|
import cv2
|
||||||
|
import numpy as np
|
||||||
from deepface.detectors import FaceDetector
|
from deepface.detectors import FaceDetector
|
||||||
|
|
||||||
|
|
||||||
def build_model():
|
def build_model() -> Any:
|
||||||
|
"""
|
||||||
|
Build a mtcnn face detector model
|
||||||
|
Returns:
|
||||||
|
model (Any)
|
||||||
|
"""
|
||||||
from mtcnn import MTCNN
|
from mtcnn import MTCNN
|
||||||
|
|
||||||
face_detector = MTCNN()
|
face_detector = MTCNN()
|
||||||
return face_detector
|
return face_detector
|
||||||
|
|
||||||
|
|
||||||
def detect_face(face_detector, img, align=True):
|
def detect_face(face_detector: Any, img: np.ndarray, align: bool = True) -> list:
|
||||||
|
"""
|
||||||
|
Detect and align face with mtcnn
|
||||||
|
Args:
|
||||||
|
face_detector (mtcnn.MTCNN): mtcnn face detector object
|
||||||
|
img (np.ndarray): pre-loaded image
|
||||||
|
align (bool): default is true
|
||||||
|
Returns:
|
||||||
|
list of detected and aligned faces
|
||||||
|
"""
|
||||||
|
|
||||||
resp = []
|
resp = []
|
||||||
|
|
||||||
|
@ -1,16 +1,28 @@
|
|||||||
import os
|
import os
|
||||||
|
from typing import Any
|
||||||
import cv2
|
import cv2
|
||||||
|
import numpy as np
|
||||||
from deepface.detectors import FaceDetector
|
from deepface.detectors import FaceDetector
|
||||||
|
|
||||||
|
|
||||||
def build_model():
|
def build_model() -> dict:
|
||||||
|
"""
|
||||||
|
Build a opencv face&eye detector models
|
||||||
|
Returns:
|
||||||
|
model (Any)
|
||||||
|
"""
|
||||||
detector = {}
|
detector = {}
|
||||||
detector["face_detector"] = build_cascade("haarcascade")
|
detector["face_detector"] = build_cascade("haarcascade")
|
||||||
detector["eye_detector"] = build_cascade("haarcascade_eye")
|
detector["eye_detector"] = build_cascade("haarcascade_eye")
|
||||||
return detector
|
return detector
|
||||||
|
|
||||||
|
|
||||||
def build_cascade(model_name="haarcascade"):
|
def build_cascade(model_name="haarcascade") -> Any:
|
||||||
|
"""
|
||||||
|
Build a opencv face&eye detector models
|
||||||
|
Returns:
|
||||||
|
model (Any)
|
||||||
|
"""
|
||||||
opencv_path = get_opencv_path()
|
opencv_path = get_opencv_path()
|
||||||
if model_name == "haarcascade":
|
if model_name == "haarcascade":
|
||||||
face_detector_path = opencv_path + "haarcascade_frontalface_default.xml"
|
face_detector_path = opencv_path + "haarcascade_frontalface_default.xml"
|
||||||
@ -38,7 +50,16 @@ def build_cascade(model_name="haarcascade"):
|
|||||||
return detector
|
return detector
|
||||||
|
|
||||||
|
|
||||||
def detect_face(detector, img, align=True):
|
def detect_face(detector: dict, img: np.ndarray, align: bool = True) -> list:
|
||||||
|
"""
|
||||||
|
Detect and align face with opencv
|
||||||
|
Args:
|
||||||
|
face_detector (Any): opencv face detector object
|
||||||
|
img (np.ndarray): pre-loaded image
|
||||||
|
align (bool): default is true
|
||||||
|
Returns:
|
||||||
|
list of detected and aligned faces
|
||||||
|
"""
|
||||||
resp = []
|
resp = []
|
||||||
|
|
||||||
detected_face = None
|
detected_face = None
|
||||||
|
@ -1,21 +1,31 @@
|
|||||||
def build_model():
|
from typing import Any
|
||||||
from retinaface import RetinaFace # this is not a must dependency
|
import numpy as np
|
||||||
|
from retinaface import RetinaFace
|
||||||
|
from retinaface.commons import postprocess
|
||||||
|
|
||||||
|
|
||||||
|
def build_model() -> Any:
|
||||||
|
"""
|
||||||
|
Build a retinaface detector model
|
||||||
|
Returns:
|
||||||
|
model (Any)
|
||||||
|
"""
|
||||||
face_detector = RetinaFace.build_model()
|
face_detector = RetinaFace.build_model()
|
||||||
return face_detector
|
return face_detector
|
||||||
|
|
||||||
|
|
||||||
def detect_face(face_detector, img, align=True):
|
def detect_face(face_detector: Any, img: np.ndarray, align: bool = True) -> list:
|
||||||
|
"""
|
||||||
from retinaface import RetinaFace # this is not a must dependency
|
Detect and align face with retinaface
|
||||||
from retinaface.commons import postprocess
|
Args:
|
||||||
|
face_detector (Any): retinaface face detector object
|
||||||
# ---------------------------------
|
img (np.ndarray): pre-loaded image
|
||||||
|
align (bool): default is true
|
||||||
|
Returns:
|
||||||
|
list of detected and aligned faces
|
||||||
|
"""
|
||||||
resp = []
|
resp = []
|
||||||
|
|
||||||
# --------------------------
|
|
||||||
|
|
||||||
obj = RetinaFace.detect_faces(img, model=face_detector, threshold=0.9)
|
obj = RetinaFace.detect_faces(img, model=face_detector, threshold=0.9)
|
||||||
|
|
||||||
if isinstance(obj, dict):
|
if isinstance(obj, dict):
|
||||||
|
@ -2,6 +2,7 @@ import os
|
|||||||
import gdown
|
import gdown
|
||||||
import cv2
|
import cv2
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
import numpy as np
|
||||||
from deepface.detectors import OpenCvWrapper
|
from deepface.detectors import OpenCvWrapper
|
||||||
from deepface.commons import functions
|
from deepface.commons import functions
|
||||||
from deepface.commons.logger import Logger
|
from deepface.commons.logger import Logger
|
||||||
@ -11,7 +12,12 @@ logger = Logger(module="detectors.SsdWrapper")
|
|||||||
# pylint: disable=line-too-long
|
# pylint: disable=line-too-long
|
||||||
|
|
||||||
|
|
||||||
def build_model():
|
def build_model() -> dict:
|
||||||
|
"""
|
||||||
|
Build a ssd detector model
|
||||||
|
Returns:
|
||||||
|
model (Any)
|
||||||
|
"""
|
||||||
|
|
||||||
home = functions.get_deepface_home()
|
home = functions.get_deepface_home()
|
||||||
|
|
||||||
@ -51,8 +57,16 @@ def build_model():
|
|||||||
return detector
|
return detector
|
||||||
|
|
||||||
|
|
||||||
def detect_face(detector, img, align=True):
|
def detect_face(detector: dict, img: np.ndarray, align: bool = True) -> list:
|
||||||
|
"""
|
||||||
|
Detect and align face with ssd
|
||||||
|
Args:
|
||||||
|
face_detector (Any): ssd face detector object
|
||||||
|
img (np.ndarray): pre-loaded image
|
||||||
|
align (bool): default is true
|
||||||
|
Returns:
|
||||||
|
list of detected and aligned faces
|
||||||
|
"""
|
||||||
resp = []
|
resp = []
|
||||||
|
|
||||||
detected_face = None
|
detected_face = None
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from typing import Any
|
||||||
|
import numpy as np
|
||||||
from deepface.detectors import FaceDetector
|
from deepface.detectors import FaceDetector
|
||||||
from deepface.commons.logger import Logger
|
from deepface.commons.logger import Logger
|
||||||
|
|
||||||
@ -14,8 +16,12 @@ WEIGHT_URL = "https://drive.google.com/uc?id=1qcr9DbgsX3ryrz2uU8w4Xm3cOrRywXqb"
|
|||||||
LANDMARKS_CONFIDENCE_THRESHOLD = 0.5
|
LANDMARKS_CONFIDENCE_THRESHOLD = 0.5
|
||||||
|
|
||||||
|
|
||||||
def build_model():
|
def build_model() -> Any:
|
||||||
"""Build YOLO (yolov8n-face) model"""
|
"""
|
||||||
|
Build a yolo detector model
|
||||||
|
Returns:
|
||||||
|
model (Any)
|
||||||
|
"""
|
||||||
import gdown
|
import gdown
|
||||||
import os
|
import os
|
||||||
|
|
||||||
@ -41,7 +47,16 @@ def build_model():
|
|||||||
return YOLO(weight_path)
|
return YOLO(weight_path)
|
||||||
|
|
||||||
|
|
||||||
def detect_face(face_detector, img, align=False):
|
def detect_face(face_detector: Any, img: np.ndarray, align: bool = False) -> list:
|
||||||
|
"""
|
||||||
|
Detect and align face with yolo
|
||||||
|
Args:
|
||||||
|
face_detector (Any): yolo face detector object
|
||||||
|
img (np.ndarray): pre-loaded image
|
||||||
|
align (bool): default is true
|
||||||
|
Returns:
|
||||||
|
list of detected and aligned faces
|
||||||
|
"""
|
||||||
resp = []
|
resp = []
|
||||||
|
|
||||||
# Detect faces
|
# Detect faces
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
|
from typing import Any
|
||||||
import cv2
|
import cv2
|
||||||
|
import numpy as np
|
||||||
import gdown
|
import gdown
|
||||||
from deepface.detectors import FaceDetector
|
from deepface.detectors import FaceDetector
|
||||||
from deepface.commons import functions
|
from deepface.commons import functions
|
||||||
@ -7,7 +9,13 @@ from deepface.commons.logger import Logger
|
|||||||
|
|
||||||
logger = Logger(module="detectors.YunetWrapper")
|
logger = Logger(module="detectors.YunetWrapper")
|
||||||
|
|
||||||
def build_model():
|
|
||||||
|
def build_model() -> Any:
|
||||||
|
"""
|
||||||
|
Build a yunet detector model
|
||||||
|
Returns:
|
||||||
|
model (Any)
|
||||||
|
"""
|
||||||
# pylint: disable=C0301
|
# pylint: disable=C0301
|
||||||
url = "https://github.com/opencv/opencv_zoo/raw/main/models/face_detection_yunet/face_detection_yunet_2023mar.onnx"
|
url = "https://github.com/opencv/opencv_zoo/raw/main/models/face_detection_yunet/face_detection_yunet_2023mar.onnx"
|
||||||
file_name = "face_detection_yunet_2023mar.onnx"
|
file_name = "face_detection_yunet_2023mar.onnx"
|
||||||
@ -20,7 +28,18 @@ def build_model():
|
|||||||
return face_detector
|
return face_detector
|
||||||
|
|
||||||
|
|
||||||
def detect_face(detector, image, align=True, score_threshold=0.9):
|
def detect_face(
|
||||||
|
detector: Any, image: np.ndarray, align: bool = True, score_threshold: float = 0.9
|
||||||
|
) -> list:
|
||||||
|
"""
|
||||||
|
Detect and align face with yunet
|
||||||
|
Args:
|
||||||
|
face_detector (Any): yunet face detector object
|
||||||
|
img (np.ndarray): pre-loaded image
|
||||||
|
align (bool): default is true
|
||||||
|
Returns:
|
||||||
|
list of detected and aligned faces
|
||||||
|
"""
|
||||||
# FaceDetector.detect_faces does not support score_threshold parameter.
|
# FaceDetector.detect_faces does not support score_threshold parameter.
|
||||||
# We can set it via environment variable.
|
# We can set it via environment variable.
|
||||||
score_threshold = os.environ.get("yunet_score_threshold", score_threshold)
|
score_threshold = os.environ.get("yunet_score_threshold", score_threshold)
|
||||||
@ -78,12 +97,8 @@ def detect_face(detector, image, align=True, score_threshold=0.9):
|
|||||||
detected_face = image[int(y) : int(y + h), int(x) : int(x + w)]
|
detected_face = image[int(y) : int(y + h), int(x) : int(x + w)]
|
||||||
img_region = [x, y, w, h]
|
img_region = [x, y, w, h]
|
||||||
if align:
|
if align:
|
||||||
detected_face = yunet_align_face(detected_face, x_re, y_re, x_le, y_le)
|
detected_face = FaceDetector.alignment_procedure(
|
||||||
|
detected_face, (x_re, y_re), (x_le, y_le)
|
||||||
|
)
|
||||||
resp.append((detected_face, img_region, confidence))
|
resp.append((detected_face, img_region, confidence))
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
|
||||||
# x_re, y_re, x_le, y_le stands for the coordinates of right eye, left eye
|
|
||||||
def yunet_align_face(img, x_re, y_re, x_le, y_le):
|
|
||||||
img = FaceDetector.alignment_procedure(img, (x_re, y_re), (x_le, y_le))
|
|
||||||
return img
|
|
||||||
|
@ -16,7 +16,7 @@ tf_version = int(tf.__version__.split(".", maxsplit=1)[0])
|
|||||||
if tf_version == 1:
|
if tf_version == 1:
|
||||||
from keras.models import Model, Sequential
|
from keras.models import Model, Sequential
|
||||||
from keras.layers import Convolution2D, Flatten, Activation
|
from keras.layers import Convolution2D, Flatten, Activation
|
||||||
elif tf_version == 2:
|
else:
|
||||||
from tensorflow.keras.models import Model, Sequential
|
from tensorflow.keras.models import Model, Sequential
|
||||||
from tensorflow.keras.layers import Convolution2D, Flatten, Activation
|
from tensorflow.keras.layers import Convolution2D, Flatten, Activation
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ elif tf_version == 2:
|
|||||||
|
|
||||||
def loadModel(
|
def loadModel(
|
||||||
url="https://github.com/serengil/deepface_models/releases/download/v1.0/age_model_weights.h5",
|
url="https://github.com/serengil/deepface_models/releases/download/v1.0/age_model_weights.h5",
|
||||||
):
|
) -> Model:
|
||||||
|
|
||||||
model = VGGFace.baseModel()
|
model = VGGFace.baseModel()
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ def loadModel(
|
|||||||
# --------------------------
|
# --------------------------
|
||||||
|
|
||||||
|
|
||||||
def findApparentAge(age_predictions):
|
def findApparentAge(age_predictions) -> np.float64:
|
||||||
output_indexes = np.array(list(range(0, 101)))
|
output_indexes = np.array(list(range(0, 101)))
|
||||||
apparent_age = np.sum(age_predictions * output_indexes)
|
apparent_age = np.sum(age_predictions * output_indexes)
|
||||||
return apparent_age
|
return apparent_age
|
||||||
|
@ -15,7 +15,7 @@ tf_version = int(tf.__version__.split(".", maxsplit=1)[0])
|
|||||||
if tf_version == 1:
|
if tf_version == 1:
|
||||||
from keras.models import Sequential
|
from keras.models import Sequential
|
||||||
from keras.layers import Conv2D, MaxPooling2D, AveragePooling2D, Flatten, Dense, Dropout
|
from keras.layers import Conv2D, MaxPooling2D, AveragePooling2D, Flatten, Dense, Dropout
|
||||||
elif tf_version == 2:
|
else:
|
||||||
from tensorflow.keras.models import Sequential
|
from tensorflow.keras.models import Sequential
|
||||||
from tensorflow.keras.layers import (
|
from tensorflow.keras.layers import (
|
||||||
Conv2D,
|
Conv2D,
|
||||||
@ -33,7 +33,7 @@ labels = ["angry", "disgust", "fear", "happy", "sad", "surprise", "neutral"]
|
|||||||
|
|
||||||
def loadModel(
|
def loadModel(
|
||||||
url="https://github.com/serengil/deepface_models/releases/download/v1.0/facial_expression_model_weights.h5",
|
url="https://github.com/serengil/deepface_models/releases/download/v1.0/facial_expression_model_weights.h5",
|
||||||
):
|
) -> Sequential:
|
||||||
|
|
||||||
num_classes = 7
|
num_classes = 7
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ tf_version = int(tf.__version__.split(".", maxsplit=1)[0])
|
|||||||
if tf_version == 1:
|
if tf_version == 1:
|
||||||
from keras.models import Model, Sequential
|
from keras.models import Model, Sequential
|
||||||
from keras.layers import Convolution2D, Flatten, Activation
|
from keras.layers import Convolution2D, Flatten, Activation
|
||||||
elif tf_version == 2:
|
else:
|
||||||
from tensorflow.keras.models import Model, Sequential
|
from tensorflow.keras.models import Model, Sequential
|
||||||
from tensorflow.keras.layers import Convolution2D, Flatten, Activation
|
from tensorflow.keras.layers import Convolution2D, Flatten, Activation
|
||||||
# -------------------------------------
|
# -------------------------------------
|
||||||
@ -28,7 +28,7 @@ labels = ["Woman", "Man"]
|
|||||||
|
|
||||||
def loadModel(
|
def loadModel(
|
||||||
url="https://github.com/serengil/deepface_models/releases/download/v1.0/gender_model_weights.h5",
|
url="https://github.com/serengil/deepface_models/releases/download/v1.0/gender_model_weights.h5",
|
||||||
):
|
) -> Model:
|
||||||
|
|
||||||
model = VGGFace.baseModel()
|
model = VGGFace.baseModel()
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ tf_version = int(tf.__version__.split(".", maxsplit=1)[0])
|
|||||||
if tf_version == 1:
|
if tf_version == 1:
|
||||||
from keras.models import Model, Sequential
|
from keras.models import Model, Sequential
|
||||||
from keras.layers import Convolution2D, Flatten, Activation
|
from keras.layers import Convolution2D, Flatten, Activation
|
||||||
elif tf_version == 2:
|
else:
|
||||||
from tensorflow.keras.models import Model, Sequential
|
from tensorflow.keras.models import Model, Sequential
|
||||||
from tensorflow.keras.layers import Convolution2D, Flatten, Activation
|
from tensorflow.keras.layers import Convolution2D, Flatten, Activation
|
||||||
# --------------------------
|
# --------------------------
|
||||||
@ -26,7 +26,7 @@ labels = ["asian", "indian", "black", "white", "middle eastern", "latino hispani
|
|||||||
|
|
||||||
def loadModel(
|
def loadModel(
|
||||||
url="https://github.com/serengil/deepface_models/releases/download/v1.0/race_model_single_batch.h5",
|
url="https://github.com/serengil/deepface_models/releases/download/v1.0/race_model_single_batch.h5",
|
||||||
):
|
) -> Model:
|
||||||
|
|
||||||
model = VGGFace.baseModel()
|
model = VGGFace.baseModel()
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ def test_standard_represent():
|
|||||||
embedding_objs = DeepFace.represent(img_path)
|
embedding_objs = DeepFace.represent(img_path)
|
||||||
for embedding_obj in embedding_objs:
|
for embedding_obj in embedding_objs:
|
||||||
embedding = embedding_obj["embedding"]
|
embedding = embedding_obj["embedding"]
|
||||||
logger.info(f"Function returned {len(embedding)} dimensional vector")
|
logger.debug(f"Function returned {len(embedding)} dimensional vector")
|
||||||
assert len(embedding) == 2622
|
assert len(embedding) == 2622
|
||||||
logger.info("✅ test standard represent function done")
|
logger.info("✅ test standard represent function done")
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user