Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[update] embed into deepface module #3

Merged
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
11 changes: 2 additions & 9 deletions deepface/models/demography/Age.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,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 @@ -64,9 +63,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 @@ -76,9 +72,6 @@ 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


Expand Down
12 changes: 2 additions & 10 deletions deepface/models/demography/Emotion.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,15 @@ def _preprocess_image(self, img: np.ndarray) -> np.ndarray:
img_gray = cv2.resize(img_gray, (48, 48))
return img_gray

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 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:
Single prediction as np.ndarray (n_emotions,) [emotion_probs] or
Multiple predictions as np.ndarray (n, n_emotions)
np.ndarray (n, n_emotions)
where n_emotions is the number of emotion categories
"""
# Convert to numpy array if input is list
Expand All @@ -83,9 +82,6 @@ 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

# Preprocess each image
processed_imgs = np.array([self._preprocess_image(img) for img in imgs])
Expand All @@ -96,13 +92,9 @@ def predict(self, img: Union[np.ndarray, List[np.ndarray]]) -> Union[np.ndarray,
# Batch prediction
predictions = self.model.predict_on_batch(processed_imgs)

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



def load_model(
url=WEIGHTS_URL,
) -> Sequential:
Expand Down
11 changes: 2 additions & 9 deletions deepface/models/demography/Gender.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,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 @@ -64,16 +63,10 @@ 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


Expand Down
11 changes: 2 additions & 9 deletions deepface/models/demography/Race.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,15 @@ def __init__(self):
self.model = load_model()
self.model_name = "Race"

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 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:
Single prediction as np.ndarray (n_races,) [race_probs] or
Multiple predictions as np.ndarray (n, n_races)
np.ndarray (n, n_races)
where n_races is the number of race categories
"""
# Convert to numpy array if input is list
Expand All @@ -65,16 +64,10 @@ 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


Expand Down
158 changes: 91 additions & 67 deletions deepface/modules/demography.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from deepface.modules import modeling, detection, preprocessing
from deepface.models.demography import Gender, Race, Emotion


# pylint: disable=trailing-whitespace
def analyze(
img_path: Union[str, np.ndarray],
actions: Union[tuple, list] = ("emotion", "age", "gender", "race"),
Expand Down Expand Up @@ -130,83 +130,107 @@ def analyze(
anti_spoofing=anti_spoofing,
)

# Anti-spoofing check
if anti_spoofing:
for img_obj in img_objs:
if img_obj.get("is_real", True) is False:
raise ValueError("Spoof detected in the given image.")

# Prepare the input for the model
valid_faces = []
face_regions = []
face_confidences = []

for img_obj in img_objs:
if anti_spoofing is True and img_obj.get("is_real", True) is False:
raise ValueError("Spoof detected in the given image.")

# Extract the face content
img_content = img_obj["face"]
img_region = img_obj["facial_area"]
img_confidence = img_obj["confidence"]
# Check if the face content is empty
if img_content.shape[0] == 0 or img_content.shape[1] == 0:
continue

# rgb to bgr
# Convert the image to RGB format from BGR
img_content = img_content[:, :, ::-1]

# resize input image
# Resize the image to the target size for the model
img_content = preprocessing.resize_image(img=img_content, target_size=(224, 224))

obj = {}
# facial attribute analysis
pbar = tqdm(
range(0, len(actions)),
desc="Finding actions",
disable=silent if len(actions) > 1 else True,
)
for index in pbar:
action = actions[index]
pbar.set_description(f"Action: {action}")

if action == "emotion":
emotion_predictions = modeling.build_model(
task="facial_attribute", model_name="Emotion"
).predict(img_content)
sum_of_predictions = emotion_predictions.sum()

obj["emotion"] = {}
for i, emotion_label in enumerate(Emotion.labels):
emotion_prediction = 100 * emotion_predictions[i] / sum_of_predictions
obj["emotion"][emotion_label] = emotion_prediction

obj["dominant_emotion"] = Emotion.labels[np.argmax(emotion_predictions)]

elif action == "age":
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
obj["age"] = int(apparent_age)

elif action == "gender":
gender_predictions = modeling.build_model(
task="facial_attribute", model_name="Gender"
).predict(img_content)
obj["gender"] = {}
for i, gender_label in enumerate(Gender.labels):
gender_prediction = 100 * gender_predictions[i]
obj["gender"][gender_label] = gender_prediction
valid_faces.append(img_content)
face_regions.append(img_obj["facial_area"])
face_confidences.append(img_obj["confidence"])

obj["dominant_gender"] = Gender.labels[np.argmax(gender_predictions)]
# If no valid faces are found, return an empty list
if not valid_faces:
return []

elif action == "race":
race_predictions = modeling.build_model(
task="facial_attribute", model_name="Race"
).predict(img_content)
sum_of_predictions = race_predictions.sum()
# Convert the list of valid faces to a numpy array
faces_array = np.array(valid_faces)
resp_objects = [{} for _ in range(len(valid_faces))]

obj["race"] = {}
# For each action, predict the corresponding attribute
pbar = tqdm(
range(0, len(actions)),
desc="Finding actions",
disable=silent if len(actions) > 1 else True,
)

for index in pbar:
action = actions[index]
pbar.set_description(f"Action: {action}")

if action == "emotion":
# Build the emotion model
model = modeling.build_model(task="facial_attribute", model_name="Emotion")
emotion_predictions = model.predict(faces_array)

for idx, predictions in enumerate(emotion_predictions):
sum_of_predictions = predictions.sum()
resp_objects[idx]["emotion"] = {}

for i, emotion_label in enumerate(Emotion.labels):
emotion_prediction = 100 * predictions[i] / sum_of_predictions
resp_objects[idx]["emotion"][emotion_label] = emotion_prediction

resp_objects[idx]["dominant_emotion"] = Emotion.labels[np.argmax(predictions)]

elif action == "age":
# Build the age model
model = modeling.build_model(task="facial_attribute", model_name="Age")
age_predictions = model.predict(faces_array)

for idx, age in enumerate(age_predictions):
resp_objects[idx]["age"] = int(age)

elif action == "gender":
# Build the gender model
model = modeling.build_model(task="facial_attribute", model_name="Gender")
gender_predictions = model.predict(faces_array)

for idx, predictions in enumerate(gender_predictions):
resp_objects[idx]["gender"] = {}

for i, gender_label in enumerate(Gender.labels):
gender_prediction = 100 * predictions[i]
resp_objects[idx]["gender"][gender_label] = gender_prediction

resp_objects[idx]["dominant_gender"] = Gender.labels[np.argmax(predictions)]

elif action == "race":
# Build the race model
model = modeling.build_model(task="facial_attribute", model_name="Race")
race_predictions = model.predict(faces_array)

for idx, predictions in enumerate(race_predictions):
sum_of_predictions = predictions.sum()
resp_objects[idx]["race"] = {}

for i, race_label in enumerate(Race.labels):
race_prediction = 100 * race_predictions[i] / sum_of_predictions
obj["race"][race_label] = race_prediction

obj["dominant_race"] = Race.labels[np.argmax(race_predictions)]

# -----------------------------
# mention facial areas
obj["region"] = img_region
# include image confidence
obj["face_confidence"] = img_confidence

resp_objects.append(obj)
race_prediction = 100 * predictions[i] / sum_of_predictions
resp_objects[idx]["race"][race_label] = race_prediction

resp_objects[idx]["dominant_race"] = Race.labels[np.argmax(predictions)]

# Add the face region and confidence to the response objects
for idx, resp_obj in enumerate(resp_objects):
resp_obj["region"] = face_regions[idx]
resp_obj["face_confidence"] = face_confidences[idx]

return resp_objects