Feat/batch predict age and gender
Tickets
https://github.com/serengil/deepface/issues/441 https://github.com/serengil/deepface/issues/678 https://github.com/serengil/deepface/issues/1069 https://github.com/serengil/deepface/issues/1101
What has been done
With this PR, new predicts function to support batch predictions.
How to test
Use this class, user can load model and predict in batch.
class AgeGenderModel():
"""
Age and gender model
"""
def __init__(self):
self.target_size = (224, 224)
self.age_model, self.gender_model = self.load()
def load(self) -> Tuple:
age_model = modeling.build_model(task="facial_attribute", model_name="Age")
gender_model = modeling.build_model(task="facial_attribute", model_name="Gender")
return age_model, gender_model
def process_data(self, data: np.ndarray) -> np.ndarray:
"""
Process input image data
"""
img_content = data[:, :, ::-1] # rgb to bgr
img_content = preprocessing.resize_image(
img=img_content,
target_size=self.target_size
)
return img_content
def predict(self, data: np.ndarray) -> Tuple[np.ndarray, np.ndarray]:
"""
Predict age and gender for one input image
"""
img_content = self.process_data(data)
age = self.age_model.predict(img_content)
gender = self.gender_model.predict(img_content)
return gender, age
def predicts(self, data: List[np.ndarray]) -> Tuple[List, List]:
"""
Predict age and gender for batch input images
"""
img_contents = [self.process_data(img_content) for img_content in data]
ages = self.age_model.predicts(img_contents)
genders = self.gender_model.predicts(img_contents)
return genders, ages
Time Costs for 10 Images:
Original for-loop prediction: 1.91108 seconds
Loading split Age and Gender models: 0.00002 seconds
Batch prediction: 0.58243 seconds
Single prediction: 0.03749 seconds
Here's my test script:
from deepface import DeepFace
import cv2
import time
# Load one face
img = cv2.imread("./test.png")
# Make it as a list
imgs = [img] * 10
# For-loop predict
start = time.time()
print("=====For-loop Predict=====")
for img in imgs:
objs = DeepFace.analyze(
img_path=img,
actions=['age', 'gender'],
)
print(f"Time: {time.time() - start:.5f}s")
# Load models
print("=====Load Split Models=====")
start = time.time()
model = AgeGenderModel()
print(f"Time: {time.time() - start:.5f}s")
# Batch Predict
start = time.time()
genders, ages = model.predicts(imgs)
print("=====Batch Predict=====")
print(genders, ages)
print(f"Time: {time.time() - start:.5f}s")
# Single Predict
start = time.time()
gender, age = model.predict(img)
print("=====Single Predict=====")
print(gender, age)
print(f"Time: {time.time() - start:.5f}s")
predicts is placed in age and gender clients to keep the DeepFace.analyze function logic.
Thank you for taking time to go through this feedback. :)
Bump Really needs this feature.
I don't support having another predicts function. Instead, you can add that logic under predict.
1- predict accepts both single image and list of images as
img: Union[np.ndarray, List[np.ndarray]]
2- in predict function, you can check the type of img, and redirect it to your logic if it is list as
if isinstance(img, np.ndarray):
# put old predict logic here
elif isinstance(img, np.ndarray):
# put your batch processing logic here
3- this new logic is worth to have its own unit tests. possibly, you can add some unit tests here.
4- return type of predict should be Union[np.float64, np.ndarray]
5- You should also update the interface in DeepFace.py
Actions failed because of linting - link
************* Module deepface.models.demography.Age
pylint: Command line or configuration file:1: UserWarning: 'Exception' is not a proper value for the 'overgeneral-exceptions' option. Use fully qualified name (maybe 'builtins.Exception' ?) instead. This will cease to be checked at runtime in 3.1.0.
deepface/models/demography/Age.py:70:0: C0303: Trailing whitespace (trailing-whitespace)
************* Module deepface.models.demography.Emotion
deepface/models/demography/Emotion.py:88:0: C0303: Trailing whitespace (trailing-whitespace)
I am not available to review it until early Feb.
Tests failed
The test seems passed. If you're okay, it's ready to merge.
LGTM
thank you for your contribution
Thank you so much @serengil !
@serengil Many thanks for your reviews!