Skip to content

Commit

Permalink
Merge pull request #1 from NatLee/feat/merge-predicts-functions
Browse files Browse the repository at this point in the history
[update] merge predicting funcs
  • Loading branch information
NatLee authored Dec 31, 2024
2 parents e1417a0 + 05dbc80 commit c312684
Show file tree
Hide file tree
Showing 6 changed files with 254 additions and 92 deletions.
43 changes: 37 additions & 6 deletions deepface/models/demography/Age.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# stdlib dependencies
from typing import List

from typing import List, Union

# 3rd party dependencies
import numpy as np
Expand Down Expand Up @@ -40,11 +41,40 @@ def __init__(self):
self.model = load_model()
self.model_name = "Age"

def predict(self, img: np.ndarray) -> np.float64:
# model.predict causes memory issue when it is called in a for loop
# age_predictions = self.model.predict(img, verbose=0)[0, :]
age_predictions = self.model(img, training=False).numpy()[0, :]
return find_apparent_age(age_predictions)
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:
np.ndarray (n,)
"""
# 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
age_predictions = self.model.predict_on_batch(imgs)

# Calculate apparent ages
apparent_ages = np.array(
[find_apparent_age(age_prediction) for age_prediction in age_predictions]
)

return apparent_ages


def predicts(self, imgs: List[np.ndarray]) -> np.ndarray:
"""
Expand All @@ -70,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
37 changes: 32 additions & 5 deletions deepface/models/demography/Gender.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# stdlib dependencies
from typing import List

from typing import List, Union

# 3rd party dependencies
import numpy as np
Expand Down Expand Up @@ -40,10 +41,35 @@ def __init__(self):
self.model = load_model()
self.model_name = "Gender"

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 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:
np.ndarray (n, 2)
"""
# 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 predicts(self, imgs: List[np.ndarray]) -> np.ndarray:
"""
Expand All @@ -64,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

0 comments on commit c312684

Please sign in to comment.