Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 4 additions & 10 deletions deepface/models/demography/Age.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from typing import List, Union


# 3rd party dependencies
import numpy as np

Expand Down Expand Up @@ -42,16 +41,15 @@ def __init__(self):
self.model = load_model()
self.model_name = "Age"

def predict(self, img: Union[np.ndarray, List[np.ndarray]]) -> Union[np.float64, np.ndarray]:
def predict(self, img: Union[np.ndarray, List[np.ndarray]]) -> np.ndarray:
"""
Predict apparent age(s) for single or multiple faces
Args:
img: Single image as np.ndarray (224, 224, 3) or
List of images as List[np.ndarray] or
Batch of images as np.ndarray (n, 224, 224, 3)
Returns:
Single age as np.float64 or
Multiple ages as np.ndarray (n,)
np.ndarray (n,)
"""
# Convert to numpy array if input is list
if isinstance(img, list):
Expand All @@ -66,9 +64,6 @@ def predict(self, img: Union[np.ndarray, List[np.ndarray]]) -> Union[np.float64,
if len(imgs.shape) == 3:
# Single image - add batch dimension
imgs = np.expand_dims(imgs, axis=0)
is_single = True
else:
is_single = False

# Batch prediction
age_predictions = self.model.predict_on_batch(imgs)
Expand All @@ -78,11 +73,9 @@ def predict(self, img: Union[np.ndarray, List[np.ndarray]]) -> Union[np.float64,
[find_apparent_age(age_prediction) for age_prediction in age_predictions]
)

# Return single value for single image
if is_single:
return apparent_ages[0]
return apparent_ages


def predicts(self, imgs: List[np.ndarray]) -> np.ndarray:
"""
Predict apparent ages of multiple faces
Expand All @@ -107,6 +100,7 @@ def predicts(self, imgs: List[np.ndarray]) -> np.ndarray:
return apparent_ages



def load_model(
url=WEIGHTS_URL,
) -> Model:
Expand Down
58 changes: 49 additions & 9 deletions deepface/models/demography/Emotion.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# stdlib dependencies
from typing import List, Union

# 3rd party dependencies
import numpy as np
import cv2
Expand Down Expand Up @@ -43,16 +46,53 @@ def __init__(self):
self.model = load_model()
self.model_name = "Emotion"

def predict(self, img: np.ndarray) -> np.ndarray:
img_gray = cv2.cvtColor(img[0], cv2.COLOR_BGR2GRAY)
def _preprocess_image(self, img: np.ndarray) -> np.ndarray:
"""
Preprocess single image for emotion detection
Args:
img: Input image (224, 224, 3)
Returns:
Preprocessed grayscale image (48, 48)
"""
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_gray = cv2.resize(img_gray, (48, 48))
img_gray = np.expand_dims(img_gray, axis=0)

# model.predict causes memory issue when it is called in a for loop
# emotion_predictions = self.model.predict(img_gray, verbose=0)[0, :]
emotion_predictions = self.model(img_gray, training=False).numpy()[0, :]

return emotion_predictions
return img_gray

def predict(self, img: Union[np.ndarray, List[np.ndarray]]) -> np.ndarray:
"""
Predict emotion probabilities for single or multiple faces
Args:
img: Single image as np.ndarray (224, 224, 3) or
List of images as List[np.ndarray] or
Batch of images as np.ndarray (n, 224, 224, 3)
Returns:
np.ndarray (n, n_emotions)
where n_emotions is the number of emotion categories
"""
# Convert to numpy array if input is list
if isinstance(img, list):
imgs = np.array(img)
else:
imgs = img

# Remove batch dimension if exists
imgs = imgs.squeeze()

# Check input dimension
if len(imgs.shape) == 3:
# Single image - add batch dimension
imgs = np.expand_dims(imgs, axis=0)

# Preprocess each image
processed_imgs = np.array([self._preprocess_image(img) for img in imgs])

# Add channel dimension for grayscale images
processed_imgs = np.expand_dims(processed_imgs, axis=-1)

# Batch prediction
predictions = self.model.predict_on_batch(processed_imgs)

return predictions


def load_model(
Expand Down
14 changes: 4 additions & 10 deletions deepface/models/demography/Gender.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from typing import List, Union


# 3rd party dependencies
import numpy as np

Expand Down Expand Up @@ -42,16 +41,15 @@ def __init__(self):
self.model = load_model()
self.model_name = "Gender"

def predict(self, img: Union[np.ndarray, List[np.ndarray]]) -> Union[np.ndarray, np.ndarray]:
def predict(self, img: Union[np.ndarray, List[np.ndarray]]) -> np.ndarray:
"""
Predict gender probabilities for single or multiple faces
Args:
img: Single image as np.ndarray (224, 224, 3) or
List of images as List[np.ndarray] or
Batch of images as np.ndarray (n, 224, 224, 3)
Returns:
Single prediction as np.ndarray (2,) [female_prob, male_prob] or
Multiple predictions as np.ndarray (n, 2)
np.ndarray (n, 2)
"""
# Convert to numpy array if input is list
if isinstance(img, list):
Expand All @@ -66,18 +64,13 @@ def predict(self, img: Union[np.ndarray, List[np.ndarray]]) -> Union[np.ndarray,
if len(imgs.shape) == 3:
# Single image - add batch dimension
imgs = np.expand_dims(imgs, axis=0)
is_single = True
else:
is_single = False

# Batch prediction
predictions = self.model.predict_on_batch(imgs)

# Return single prediction for single image
if is_single:
return predictions[0]
return predictions


def predicts(self, imgs: List[np.ndarray]) -> np.ndarray:
"""
Predict apparent ages of multiple faces
Expand All @@ -97,6 +90,7 @@ def predicts(self, imgs: List[np.ndarray]) -> np.ndarray:
return self.model.predict_on_batch(imgs_)



def load_model(
url=WEIGHTS_URL,
) -> Model:
Expand Down
38 changes: 33 additions & 5 deletions deepface/models/demography/Race.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# stdlib dependencies
from typing import List, Union

# 3rd party dependencies
import numpy as np

Expand Down Expand Up @@ -37,10 +40,35 @@ def __init__(self):
self.model = load_model()
self.model_name = "Race"

def predict(self, img: np.ndarray) -> np.ndarray:
# model.predict causes memory issue when it is called in a for loop
# return self.model.predict(img, verbose=0)[0, :]
return self.model(img, training=False).numpy()[0, :]
def predict(self, img: Union[np.ndarray, List[np.ndarray]]) -> np.ndarray:
"""
Predict race probabilities for single or multiple faces
Args:
img: Single image as np.ndarray (224, 224, 3) or
List of images as List[np.ndarray] or
Batch of images as np.ndarray (n, 224, 224, 3)
Returns:
np.ndarray (n, n_races)
where n_races is the number of race categories
"""
# Convert to numpy array if input is list
if isinstance(img, list):
imgs = np.array(img)
else:
imgs = img

# Remove batch dimension if exists
imgs = imgs.squeeze()

# Check input dimension
if len(imgs.shape) == 3:
# Single image - add batch dimension
imgs = np.expand_dims(imgs, axis=0)

# Batch prediction
predictions = self.model.predict_on_batch(imgs)

return predictions


def load_model(
Expand All @@ -62,7 +90,7 @@ def load_model(

# --------------------------

race_model = Model(inputs=model.input, outputs=base_model_output)
race_model = Model(inputs=model.inputs, outputs=base_model_output)

# --------------------------

Expand Down
Loading