Face analysis¶
dynaface.facial ¶
Face analysis: find a face, place its landmarks, crop it and run the measures.
load_face_image() loads a photo from a file or URL. For images you already hold as RGB NumPy arrays, such as video frames, create an AnalyzeFace and call its load_image().
AnalyzeFace ¶
AnalyzeFace(
measures: Optional[List[MeasureBase]] = None,
tilt_threshold: float = DEFAULT_TILT_THRESHOLD,
)
Bases: ImageAnalysis
Analyzes a face: finds it in an image, places its 98 landmarks, crops it to a standard size and runs the measures on it.
Load the models with dynaface.models.init_models() first. Then call load_image() with an RGB image and analyze() for the measurements. The image with the measures drawn on it is in render_img, and save() writes it to a file.
Attributes:
| Name | Type | Description |
|---|---|---|
pd |
float
|
The assumed distance between the pupils, in millimeters (63 by default), used to convert pixels to millimeters. Set it on the class, as AnalyzeFace.pd, to calibrate. |
measures |
List[MeasureBase]
|
The measures that analyze() runs. |
landmarks |
List[Tuple[int, int]]
|
The 98 WFLW landmark positions, in pixels of the current image. |
pose |
Pose
|
The pose that load_image() detected or was told to use. |
render_img |
NDArray[uint8]
|
The image the measures draw on. |
Initialize the AnalyzeFace object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
measures
|
Optional[List[MeasureBase]]
|
Facial measures to be used. Defaults to None. |
None
|
tilt_threshold
|
float
|
Maximum allowable tilt threshold. Defaults to DEFAULT_TILT_THRESHOLD. |
DEFAULT_TILT_THRESHOLD
|
get_all_items ¶
get_all_items() -> List[str]
List the outputs to show or export: the enabled items of the enabled measures, without display-only items.
analyze() returns every output whether or not its item is enabled, so use this list to choose which ones to show.
Returns:
| Type | Description |
|---|---|
List[str]
|
List[str]: Output names, such as "fai" and "oce.l". |
is_no_face ¶
is_no_face() -> bool
Check if no face is detected.
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
True if no face is detected, False otherwise. |
load_image ¶
load_image(
img: NDArray[Any],
crop: Optional[bool] = True,
pupils: Optional[
Tuple[Tuple[int, int], Tuple[int, int]]
] = None,
force_pose: Optional[Pose] = Pose.DETECT,
) -> bool
Load an RGB image, find the face, place its landmarks and crop it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img
|
NDArray[Any]
|
The image, as an RGB array. |
required |
crop
|
bool
|
Whether to crop the face to the standard 1024 by 1024 size. Lateral faces are always cropped. |
True
|
pupils
|
Optional[Tuple[Tuple[int, int], Tuple[int, int]]]
|
Currently unused; the crop is always placed using the pupils found in this image. |
None
|
force_pose
|
Optional[Pose]
|
Pose.DETECT to classify the pose as frontal or lateral, or a Pose to use instead. |
DETECT
|
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
True once the image is loaded. |
draw_landmarks ¶
draw_landmarks(
size: float = 0.25,
color: Tuple[int, int, int] = (0, 255, 255),
numbers: bool = False,
only: Optional[Iterable[int]] = None,
) -> None
Draw landmarks (and optionally their indices) on the image.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
size
|
float
|
Visual scale factor for landmark dots and number labels. |
0.25
|
color
|
Tuple[int, int, int]
|
BGR color for drawing. |
(0, 255, 255)
|
numbers
|
bool
|
If True, draw the landmark index next to each point. |
False
|
only
|
Iterable[int] | None
|
If provided, draw ONLY these landmark indices. If None, draw all landmarks. |
None
|
measure ¶
measure(
pt1: Tuple[int, int],
pt2: Tuple[int, int],
color: Tuple[int, int, int] = (255, 0, 0),
thickness: int = 3,
render: bool = True,
dir: str = "r",
) -> float
Measures the Euclidean distance between two points (pt1 and pt2) and optionally renders an arrow and text.
measure_curve ¶
measure_curve(
pt1: Tuple[int, int],
pt2: Tuple[int, int],
sagittal_x: NDArray[Any],
sagittal_y: NDArray[Any],
color: Tuple[int, int, int] = (255, 0, 0),
thickness: int = 3,
render: bool = True,
dir: str = "r",
) -> float
Measures the curved distance along a sagittal line between two points (pt1 and pt2) and optionally renders the curve and text.
draw_curve ¶
draw_curve(
segment: NDArray[Any],
color: Tuple[int, int, int],
thickness: int,
) -> None
Draws a curve connecting a segment of points.
analyze_next_pt ¶
analyze_next_pt(txt: str) -> Tuple[int, int]
Determines the next position for analysis text based on current position.
analyze ¶
analyze() -> Optional[Dict[str, Any]]
Run the enabled measures on the face, drawing them on render_img.
Returns:
| Type | Description |
|---|---|
Optional[Dict[str, Any]]
|
Optional[Dict[str, Any]]: Each output's name mapped to its value, such as {"fai": 0.70, "oce.l": 30.12, ...}, or None if the image has no landmarks. A value that couldn't be determined is NaN. |
calculate_face_rotation ¶
calculate_face_rotation() -> float
Calculates the face rotation in degrees.
crop_lateral ¶
crop_lateral() -> None
Crop to 1024×1024 for lateral analysis, guaranteeing that ALL landmarks are visible vertically, plus configurable top/bottom padding.
- Scale is chosen so (landmark_band + pads) fits within 1024 px height.
- Horizontally, the profile's leading edge (leftmost landmark; the face always faces left here) is placed LATERAL_LEFT_MARGIN_RATIO from the left, so the face uses the space at the left and the sagittal chart overlaid at the right cuts off near the front of the ear.
- If the source is narrow, side padding is allowed (pillarbox) so that vertical padding is never silently squeezed away.
crop_stylegan ¶
crop_stylegan(
pupils: Optional[
Tuple[Tuple[int, int], Tuple[int, int]]
] = None,
) -> None
Processes and crops the image for StyleGAN.
calc_pd ¶
calc_pd() -> None
Measure the pupils on the current landmarks; update pupillary_distance and pix2mm (millimeters per pixel).
get_pupils ¶
get_pupils() -> (
Tuple[Tuple[float, float], Tuple[float, float]]
)
Return the two pupil positions, left first.
Returns:
| Type | Description |
|---|---|
Tuple[Tuple[float, float], Tuple[float, float]]
|
Tuple[Tuple[float, float], Tuple[float, float]]: The left and right pupil landmarks, in pixels. |
dump_state ¶
dump_state() -> List[Any]
Capture this frame's analysis, so a video's frames can be kept and restored with load_state() without detecting the face again.
Returns:
| Type | Description |
|---|---|
List[Any]
|
List[Any]: The original image, head pose, landmarks, pupillary distance, millimeters per pixel and face rotation. |
load_state ¶
load_state(obj: List[Any]) -> None
Restore a frame's analysis captured by dump_state().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
List[Any]
|
The list dump_state() returned. A state saved without a face rotation restores with a rotation of 0. |
required |
find_pupils ¶
find_pupils() -> (
Tuple[Tuple[float, float], Tuple[float, float]]
)
Return the two pupil positions, left first. The same as get_pupils().
Returns:
| Type | Description |
|---|---|
Tuple[Tuple[float, float], Tuple[float, float]]
|
Tuple[Tuple[float, float], Tuple[float, float]]: The left and right pupil landmarks, in pixels. |
calc_bisect ¶
calc_bisect() -> Any
Return the line that bisects the face: perpendicular to the line between the pupils, through its midpoint.
Returns:
| Name | Type | Description |
|---|---|---|
Any |
Any
|
The line's two end points on a 1024 by 1024 image. |
draw_static ¶
draw_static() -> None
Write the pose, such as "Frontal" or "Lateral (left)", at the bottom left of render_img.
util_calc_pd ¶
util_calc_pd(
pupils: Tuple[Tuple[float, float], Tuple[float, float]],
) -> Tuple[float, float]
Measure the distance between the pupils and the millimeters per pixel.
The scale assumes the pupils are AnalyzeFace.pd millimeters apart.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
pupils
|
Tuple[Tuple[float, float], Tuple[float, float]]
|
The two pupil positions, in pixels. |
required |
Returns:
| Type | Description |
|---|---|
Tuple[float, float]
|
Tuple[float, float]: The pupillary distance in pixels, and the millimeters per pixel, which is NaN when the pupils coincide. |
util_get_pupils ¶
util_get_pupils(
landmarks: List[Tuple[int, int]],
) -> Tuple[Tuple[int, int], Tuple[int, int]]
Return the two pupil landmarks, left first.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
landmarks
|
List[Tuple[int, int]]
|
The 98 WFLW landmarks. |
required |
Returns:
| Type | Description |
|---|---|
Tuple[Tuple[int, int], Tuple[int, int]]
|
Tuple[Tuple[int, int], Tuple[int, int]]: The left pupil (landmark 97) and the right pupil (landmark 96). |
load_face_image ¶
load_face_image(
filename: str,
crop: bool = True,
measures: Optional[List[MeasureBase]] = None,
tilt_threshold: float = DEFAULT_TILT_THRESHOLD,
) -> AnalyzeFace
Load a face image from a file or URL and get it ready to analyze.
Load the models with dynaface.models.init_models() first.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str
|
A path to an image file, or an http or https URL. |
required |
crop
|
bool
|
Whether to crop the face to the standard 1024 by 1024 size. |
True
|
measures
|
Optional[List[MeasureBase]]
|
The measures to run. Defaults to all_measures(). |
None
|
tilt_threshold
|
float
|
Straighten faces tilted more than this many degrees. A negative value, the default, never straightens. |
DEFAULT_TILT_THRESHOLD
|
Returns:
| Name | Type | Description |
|---|---|---|
AnalyzeFace |
AnalyzeFace
|
The face, ready for analyze(). |