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

Handled cases when no landmark in some of the frame in videos. #13

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,10 @@ libreface/Facial_Expression_Recognition/weights/
weights_libreface/
build/
dist/
temp/
tmp/
test_instruction.txt
test_issue11.py
/data
*.egg-info/*
*.DS_Store
8 changes: 4 additions & 4 deletions README_pypi.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Libreface
:alt: Static Badge


.. |badge2| image:: https://img.shields.io/badge/python-%3D%3D3.8-green
.. |badge2| image:: https://img.shields.io/badge/python-%3D%3D3.9-green
:alt: Static Badge


Expand All @@ -29,7 +29,7 @@ We conduct extensive experiments of pre-training and distillation to demonstrate
Dependencies
============

- Python 3.8
- Python 3.9
- You should have `cmake` installed in your system.
- **For Linux users** - :code:`sudo apt-get install cmake`. If you run into trouble, consider upgrading to the latest version (`instructions`_).
- **For Mac users** - :code:`brew install cmake`.
Expand All @@ -39,11 +39,11 @@ Dependencies

Installation
============
You can first create a new Python 3.8 environment using `conda` and then install this package using `pip` from the PyPI hub:
You can first create a new Python 3.9 environment using `conda` and then install this package using `pip` from the PyPI hub:

.. code-block:: bash

conda create -n libreface_env python=3.8
conda create -n libreface_env python=3.9
conda activate libreface_env
pip install --upgrade libreface

Expand Down
22 changes: 15 additions & 7 deletions libreface/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ def get_facial_attributes_video(video_path,
cur_video_name = ".".join(video_path.split("/")[-1].split(".")[:-1])
aligned_frames_path_list, headpose_list, landmarks_3d_list = get_aligned_video_frames(frames_df, temp_dir=os.path.join(temp_dir, cur_video_name))
# frames_df["aligned_frame_path"] = aligned_frames_path_list
if frames_df.empty:
raise RuntimeError(f"No face detected in the video, get_facial_attributes fails.")
frames_df = frames_df.drop("path_to_frame", axis=1)
frames_df["headpose"] = headpose_list
frames_df["landmarks_3d"] = landmarks_3d_list
Expand Down Expand Up @@ -118,13 +120,19 @@ def save_facial_attributes_video(video_path,
batch_size = 256,
num_workers = 2,
weights_download_dir:str = "./weights_libreface"):
frames_df = get_facial_attributes_video(video_path,
model_choice=model_choice,
temp_dir=temp_dir,
device=device,
batch_size=batch_size,
num_workers=num_workers,
weights_download_dir=weights_download_dir)
try:
frames_df = get_facial_attributes_video(video_path,
model_choice=model_choice,
temp_dir=temp_dir,
device=device,
batch_size=batch_size,
num_workers=num_workers,
weights_download_dir=weights_download_dir)

except Exception as e:
print(e)
print(f"Since no face is detected, can't save the file")
return False
save_path = uniquify_file(output_save_path)
frames_df.to_csv(save_path, index=False)
print(f"Facial attributes of the video saved to {save_path}")
Expand Down
21 changes: 17 additions & 4 deletions libreface/detect_mediapipe_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,8 @@ def get_aligned_image(image_path, temp_dir = "./tmp", verbose=False):
# Draw face landmarks of each face.
# print(f'Face landmarks of {name}:')
if not results.multi_face_landmarks:
print("Processing landmarks did not result on anything...")
raise RuntimeError(f"No face landmarks")
# print("Processing landmarks did not result on anything...")
img_h, img_w, img_c = image.shape
face_3d = []
face_2d = []
Expand Down Expand Up @@ -348,12 +349,24 @@ def get_aligned_video_frames(frames_df, temp_dir="./tmp"):
aligned_frames_paths = []
head_pose_list = []
landmark_list = []
for _, row in tqdm(frames_df.iterrows(), desc="Aligning face for video frames..."):
aligned_image_path, head_pose, landmark_dict = get_aligned_image(row["path_to_frame"], temp_dir)
#track the errored frames
indexes_to_drop = []
for index, row in tqdm(frames_df.iterrows(), desc="Aligning face for video frames..."):
try:
aligned_image_path, head_pose, landmark_dict = get_aligned_image(row["path_to_frame"], temp_dir)
except Exception as e:
indexes_to_drop.append(index)
continue
aligned_frames_paths.append(aligned_image_path)
head_pose_list.append(head_pose)
landmark_list.append(landmark_dict)

#drop all the errored frames
frames_df.drop(index=indexes_to_drop,inplace=True)
frames_df.reset_index(drop=True, inplace=True)
if len(indexes_to_drop)!=0 :
print(f"Dropped {len(indexes_to_drop)} frames because no landmarks detected by mediapipe in the frame.")
if frames_df.empty:
print("No face detected in the provided video")
return aligned_frames_paths, head_pose_list, landmark_list

if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion requirements_new.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ gdown==5.2.0
importlib-metadata==8.4.0
importlib-resources==6.4.5
imutils==0.5.4
mediapipe==0.9.3
mediapipe==0.10.5
oauthlib>=3.0.0
opencv-python==4.10.0.84
pandas==2.0.3
Expand Down
12 changes: 7 additions & 5 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
URL = 'https://boese0601.github.io/libreface'
EMAIL = '[email protected]'
AUTHOR = 'IHP-Lab'
REQUIRES_PYTHON = '>=3.8'
REQUIRES_PYTHON = '>=3.9'


# What packages are required for this module to be executed?
Expand Down Expand Up @@ -52,15 +52,15 @@ def list_reqs(fname='requirements_new.txt'):
# with open(PACKAGE_DIR / 'VERSION') as f:
# _version = f.read().strip()

about['__version__'] = "0.0.19"
about['__version__'] = "0.0.26"


# Where the magic happens:
setup(
name=NAME,
version=about['__version__'],
description='LibreFace model for facial analysis',
long_descripation_content_type='text/x-rst',
long_description_content_type='text/x-rst',
long_description=long_description,
author=AUTHOR,
author_email=EMAIL,
Expand All @@ -73,14 +73,16 @@ def list_reqs(fname='requirements_new.txt'):
include_package_data=True,
license=license,
entry_points={
'console_scripts': 'libreface=libreface.commandline:main_func'
'console_scripts': [
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you change this to a list? Was it not working without the [] list?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this change was made during the previous issues with testpypi,
Now after addressing the issue I believe changing this to a list won't have any difference with the previous version,
but at least it passes all the tests after this change so I just remain it there as it is.

'libreface=libreface.commandline:main_func'
]
},
classifiers=[
# Trove classifiers
# Full list: https://pypi.python.org/pypi?%3Aaction=list_classifiers
'Programming Language :: Python',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy'
],
Expand Down
10 changes: 5 additions & 5 deletions test_libreface.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,29 @@
import time

# inference on single image and store results to a variable
detected_facial_attributes = libreface.get_facial_attributes_image(image_path = "sample_disfa.png",
detected_facial_attributes = libreface.get_facial_attributes_image(image_path = "examples/sample_disfa.png",
temp_dir = "./temp",
device = "cpu")

# inference on a single image and save results in a csv file
libreface.save_facial_attributes_image(image_path = "sample_disfa.png",
libreface.save_facial_attributes_image(image_path = "examples/sample_disfa.png",
output_save_path = "sample_image_results.csv",
temp_dir = "./temp",
device = "cpu")

# inference on a video and store the results to a pandas dataframe
detected_facial_attributes_df = libreface.get_facial_attributes_video(video_path = "sample_disfa.avi",
detected_facial_attributes_df = libreface.get_facial_attributes_video(video_path = "examples/sample_disfa.avi",
temp_dir = "./temp",
device = "cpu")

# ## inference on a video and save the results framewise in a csv file
libreface.save_facial_attributes_video(video_path = "sample_disfa.avi",
libreface.save_facial_attributes_video(video_path = "examples/sample_disfa.avi",
output_save_path = "sample_video_results.csv",
temp_dir = "./temp",
device = "cpu")

## inference on any image or video type and store results accordingly to a variable or save results
detected_facial_attributes = libreface.get_facial_attributes(file_path = "sample_disfa.avi",
detected_facial_attributes = libreface.get_facial_attributes(file_path = "examples/sample_disfa.avi",
output_save_path = "sample_results.csv",
temp_dir = "./temp",
device = "cpu")