Add DeepFace exploration notebook and Python package

Этот коммит содержится в:
Dominic Kempf 2022-07-12 15:24:26 +02:00
родитель b28e8ab5fe
Коммит 2d3ea26007
8 изменённых файлов: 265 добавлений и 2 удалений

Просмотреть файл

@ -5,11 +5,11 @@ repos:
- id: nbstripout - id: nbstripout
files: ".ipynb" files: ".ipynb"
- repo: https://github.com/psf/black - repo: https://github.com/psf/black
rev: 21.11b0 rev: 22.6.0
hooks: hooks:
- id: black - id: black
- repo: https://github.com/dfm/black_nbconvert - repo: https://github.com/dfm/black_nbconvert
rev: v0.3.0 rev: v0.4.0
hooks: hooks:
- id: black_nbconvert - id: black_nbconvert
- repo: https://github.com/pycqa/flake8 - repo: https://github.com/pycqa/flake8

28
Dockerfile Обычный файл
Просмотреть файл

@ -0,0 +1,28 @@
FROM jupyter/base-notebook:2022-06-06
# Install system dependencies for computer vision packages
USER root
RUN apt update && apt install -y libgl1 libglib2.0-0 libsm6 libxrender1 libxext6
USER $NB_USER
# Copy the repository into the container
COPY --chown=${NB_UID} . /opt/misinformation
# Install the Python package
RUN python -m pip install /opt/misinformation
# Make JupyterLab the default for this application
ENV JUPYTER_ENABLE_LAB=yes
# Export where the data is located
ENV XDG_DATA_HOME=/opt/misinformation/data
# Copy notebooks into the home directory
RUN rm -rf $HOME/work
RUN cp /opt/misinformation/notebooks/*.ipynb $HOME
# Execute the facial recognition notebook once in order to bundle
# the pre-built models (that are downloaded on demand) into the
# Docker image.
RUN python -m pip install nbclick && \
python -m nbclick /opt/misinformation/notebooks/facial_expressions.ipynb

0
data/.keep Обычный файл
Просмотреть файл

8
misinformation/__init__.py Обычный файл
Просмотреть файл

@ -0,0 +1,8 @@
from importlib import metadata
# Export the version defined in project metadata
__version__ = metadata.version(__package__)
del metadata
from misinformation.faces import explore_face_recognition, find_files

89
misinformation/faces.py Обычный файл
Просмотреть файл

@ -0,0 +1,89 @@
import glob
import ipywidgets
import os
from IPython.display import display
from deepface import DeepFace
def find_files(path=None, pattern="*.png", recursive=True, limit=20):
"""Find image files on the file system
:param path:
The base directory where we are looking for the images. Defaults
to None, which uses the XDG data directory if set or the current
working directory otherwise.
:param pattern:
The naming pattern that the filename should match. Defaults to
"*.png". Can be used to allow other patterns or to only include
specific prefixes or suffixes.
:param recursive:
Whether to recurse into subdirectories.
:param limit:
The maximum number of images to be found. Defaults to 20.
To return all images, set to None.
"""
if path is None:
path = os.environ.get("XDG_DATA_HOME", ".")
result = list(glob.glob(f"{path}/{pattern}", recursive=recursive))
if limit is not None:
result = result[:limit]
return result
def facial_expression_analysis(img_path):
return DeepFace.analyze(
img_path=img_path, actions=["age", "gender", "race", "emotion"], prog_bar=False
)
class JSONContainer:
"""Expose a Python dictionary as a JSON document in JupyterLab
rich display rendering.
"""
def __init__(self, data={}):
self._data = data
def _repr_json_(self):
return self._data
def explore_face_recognition(image_paths):
# Set up the facial recognition output widget
output = ipywidgets.Output(layout=ipywidgets.Layout(width="30%"))
# Set up the image selection and display widget
images = [ipywidgets.Image.from_file(p) for p in image_paths]
image_widget = ipywidgets.Tab(
children=images,
titles=[f"#{i}" for i in range(len(image_paths))],
layout=ipywidgets.Layout(width="70%"),
)
# Register the facial recognition logic
def _recognition(_):
data = {}
data["filename"] = image_paths[image_widget.selected_index]
try:
data["deepface_results"] = facial_expression_analysis(data["filename"])
data["deepface_find_face"] = True
except ValueError:
data["deepface_find_face"] = False
output.clear_output()
with output:
display(JSONContainer(data))
# Register the handler and trigger it immediately
image_widget.observe(_recognition, names=("selected_index",), type="change")
with ipywidgets.Output():
_recognition(None)
# Show the combined widget
return ipywidgets.HBox([image_widget, output])

105
notebooks/facial_expressions.ipynb Обычный файл
Просмотреть файл

@ -0,0 +1,105 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "d2c4d40d-8aca-4024-8d19-a65c4efe825d",
"metadata": {},
"source": [
"# Facial Expression recognition with DeepFace"
]
},
{
"cell_type": "markdown",
"id": "51f8888b-d1a3-4b85-a596-95c0993fa192",
"metadata": {},
"source": [
"This notebooks shows some preliminary work on detecting facial expressions with DeepFace. It is mainly meant to explore its capabilities and to decide on future research directions. We package our code into a `misinformation` package that is imported here:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b21e52a5-d379-42db-aae6-f2ab9ed9a369",
"metadata": {},
"outputs": [],
"source": [
"import misinformation"
]
},
{
"cell_type": "markdown",
"id": "949d9f00-b129-477a-bc1d-e68fed73af2d",
"metadata": {},
"source": [
"We select a subset of image files to try facial expression detection on. The `find_files` function finds image files within a given directory:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "afe7e638-f09d-47e7-9295-1c374bd64c53",
"metadata": {},
"outputs": [],
"source": [
"images = misinformation.find_files()"
]
},
{
"cell_type": "markdown",
"id": "e149bfe5-90b0-49b2-af3d-688e41aab019",
"metadata": {},
"source": [
"If you want to fine tune the discovery of image files, you can provide more parameters:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f38bb8ed-1004-4e33-8ed6-793cb5869400",
"metadata": {},
"outputs": [],
"source": [
"?misinformation.find_files"
]
},
{
"cell_type": "markdown",
"id": "d8067ad1-ef8a-4e91-bcc6-f8dbef771854",
"metadata": {},
"source": [
"Next, we display the face recognition results provided by the DeepFace library. Click on the tabs to see the results in the right sidebar:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "992499ed-33f1-4425-ad5d-738cf565d175",
"metadata": {},
"outputs": [],
"source": [
"misinformation.explore_face_recognition(images)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.5"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

29
pyproject.toml Обычный файл
Просмотреть файл

@ -0,0 +1,29 @@
[build-system]
requires = [
"setuptools>=61",
]
build-backend = "setuptools.build_meta"
[project]
name = "misinformation"
version = "0.0.1"
description = "Misinformation campaign analysis"
readme = "README.md"
maintainers = [
{ name = "Inga Ulusoy", email = "ssc@iwr.uni-heidelberg.de" },
{ name = "Dominic Kempf", email = "ssc@iwr.uni-heidelberg.de" },
]
requires-python = ">=3.8"
license = { text = "MIT" }
classifiers = [
"Programming Language :: Python :: 3",
"Operating System :: OS Independent",
"License :: OSI Approved :: MIT License",
]
dependencies = [
"deepface",
"ipywidgets ==8.0.0rc1",
]
[tool.setuptools]
packages = ["misinformation"]

4
setup.py Обычный файл
Просмотреть файл

@ -0,0 +1,4 @@
from setuptools import setup
setup()