Getting Started with Dynaface¶
This notebook installs Dynaface, measures a face in a photo and shows the results. It runs in Colab or in a local Jupyter notebook.
%pip install -q --upgrade dynaface
import dynaface
print(f"Dynaface version: {dynaface.__version__}")
Dynaface version: 2.0.3
This helper displays an image inline. Dynaface works with RGB images, which is also what Matplotlib expects.
%matplotlib inline
import matplotlib.pyplot as plt
from IPython.display import display
def show(image, size=5):
"""Display an RGB image inline."""
fig, ax = plt.subplots(figsize=(size, size))
ax.imshow(image)
ax.axis("off")
display(fig)
plt.close(fig)
In Colab, you may have to restart the runtime after the install.
Dynaface uses Python logging. To see its messages, set the log level you want.
import logging
import sys
log_level = logging.INFO
# Remove any existing handlers
for handler in logging.root.handlers[:]:
logging.root.removeHandler(handler)
# Set up a new handler that logs to the console at the chosen level
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(log_level)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
console_handler.setFormatter(formatter)
# Add the handler to the root logger
logging.root.setLevel(log_level)
logging.root.addHandler(console_handler)
Dynaface uses three AI models. The first time, the following code downloads them (about 400 MB). It then loads them, using a GPU or Apple silicon when one is available.
from dynaface import facial, measures, models
device = models.detect_device()
print(f"Detected device: {device}")
path = models.download_models()
models.init_models(path, device)
Detected device: cpu
Load an image. Any RGB image held in a NumPy array works, such as a frame from a video. OpenCV decodes images as BGR, so convert them to RGB first.
import cv2
import numpy as np
import requests
image_url = "https://www.heatonresearch.com/images/jeff/about-jeff-heaton-2020.jpg"
response = requests.get(image_url, timeout=30)
image = cv2.imdecode(np.frombuffer(response.content, dtype=np.uint8), cv2.IMREAD_COLOR)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
show(image)
Analyze the face. load_image finds the face and crops it to a standard size, and analyze runs each measure and returns the results by name.
from dynaface.measures_frontal import AnalyzeLandmarks
# Use every measure except AnalyzeLandmarks, which returns the x and y position of
# all 98 landmarks.
all_measures = [m for m in measures.all_measures() if not isinstance(m, AnalyzeLandmarks)]
face = facial.AnalyzeFace(measures=all_measures)
face.load_image(image, crop=True)
results = face.analyze()
for name, value in results.items():
shown = f"{value:.2f}" if isinstance(value, float) else value
print(f"{name:>14} {shown}")
2026-10-26 08:51:21,580 - INFO - Headpose: yaw:5.284163951873779, pitch:9.84992504119873, roll:-0.08932098746299744
fai 1.83
oce.l 35.40
oce.r 36.62
brow.d 0.63
dental_area 502.33
dental_left 254.41
dental_right 247.91
dental_ratio 0.97
dental_diff 6.50
eye.left 114.55
eye.right 119.86
eye.diff 5.31
eye.ratio 0.96
id 36.10
ml 61.74
nose.alar 35.14
nose.nostril 17.74
oe 86.74
tilt 0.58
px2mm 0.32
pd 199.01
pitch 9.85
roll -0.09
yaw 5.28
hue 15
sat 40
brightness 80
Display the cropped face with the measures drawn on it.
show(face.render_img, size=7)