Facial analysis has evolved significantly from simple bounding box object detectors. With modern convolutional and transformer-based architectures, extracting sub-millimeter anatomical landmarks in real-time runs comfortably inside browser runtimes and lightweight Python microservices.
Aesthetic metric calculations, such as facial thirds, canthal tilts, and facial width-to-height ratios (fWHR), have gained significant interest across social platforms. To a computer vision engineer, these are simply deterministic geometric operations executed on normalized coordinate matrices.
In this walkthrough, we will build a working Python pipeline using MediaPipe Face Mesh and NumPy to extract, normalize, and calculate geometric feature vectors from a single 2D image, while examining the optical challenges inherent in 2D facial measurement.
Setting Up the Pipeline
We will use Google's MediaPipe library, which infers a 468-point 3D facial surface geometry in a single forward pass without requiring dedicated GPU acceleration.
First, install the necessary dependencies:
pip install opencv-python mediapipe numpy
Extracting Dense Landmark Coordinates
The core pipeline loads an RGB image, executes landmark regression, and converts normalized coordinates ([0.0, 1.0]) into pixel-space matrices:
import cv2
import mediapipe as mp
import numpy as np
class FacialGeometryExtractor:
def __init__(self):
self.mp_face_mesh = mp.solutions.face_mesh
self.face_mesh = self.mp_face_mesh.FaceMesh(
static_image_mode=True,
max_num_faces=1,
refine_landmarks=True,
min_detection_confidence=0.5
)
def extract_landmarks(self, image_bgr):
h, w, _ = image_bgr.shape
image_rgb = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB)
results = self.face_mesh.process(image_rgb)
if not results.multi_face_landmarks:
return None
# Extract 468 points as a (468, 3) NumPy array
landmarks = np.array([
[pt.x * w, pt.y * h, pt.z * w]
for pt in results.multi_face_landmarks[0].landmark
])
return landmarks
Calculating Core Geometric Metrics
Once raw landmark coordinates are available, we calculate key structural vectors.
1. Canthal Tilt Angle
Canthal tilt measures the inclination angle between the inner corner (endocanthion) and the outer corner (exocanthion) of the eye:
def compute_canthal_tilt(inner_eye, outer_eye):
"""
Computes angle in degrees relative to the horizontal axis.
Positive indicates positive canthal tilt.
"""
dx = outer_eye[0] - inner_eye[0]
dy = outer_eye[1] - inner_eye[1]
# Invert dy since image coordinate origin (0,0) is top-left
angle_rad = np.arctan2(-dy, dx)
return np.degrees(angle_rad)
2. Facial Width-to-Height Ratio (fWHR)
fWHR is an extensively researched metric in evolutionary psychology, measuring bizygomatic width against midface height:
def compute_fwhr(left_zygoma, right_zygoma, brow_midpoint, upper_lip):
bizygomatic_width = np.linalg.norm(right_zygoma[:2] - left_zygoma[:2])
midface_height = np.linalg.norm(upper_lip[:2] - brow_midpoint[:2])
if midface_height == 0:
return 0.0
return bizygomatic_width / midface_height
3. Vertical Thirds Proportions
To evaluate vertical harmony, we calculate distances between the trichion (or upper forehead boundary), glabella (between eyebrows), subnasale (base of nose), and menton (chin tip):
def compute_vertical_thirds(forehead_top, glabella, subnasale, menton):
upper_third = np.linalg.norm(glabella[:2] - forehead_top[:2])
middle_third = np.linalg.norm(subnasale[:2] - glabella[:2])
lower_third = np.linalg.norm(menton[:2] - subnasale[:2])
total = upper_third + middle_third + lower_third
if total == 0:
return (0.33, 0.33, 0.33)
return (
upper_third / total,
middle_third / total,
lower_third / total
)
Pose Normalization and Affine Alignment
Unconstrained selfies rarely exhibit perfect frontal orientation. Roll, pitch, and yaw introduce substantial noise into Euclidean distance measurements.
Before calculating distances, production implementations of an online PSL scale calculator typically run affine normalization passes to rotate the face so the interpupillary line is strictly horizontal. By scaling the bounding box relative to the interpupillary distance (IPD), the feature vectors become scale- and rotation-invariant.
def align_face_roll(image, left_pupil, right_pupil):
d_x = right_pupil[0] - left_pupil[0]
d_y = right_pupil[1] - left_pupil[1]
angle = np.degrees(np.arctan2(d_y, d_x))
center = (
int((left_pupil[0] + right_pupil[0]) / 2),
int((left_pupil[1] + right_pupil[1]) / 2)
)
rot_matrix = cv2.getRotationMatrix2D(center, angle, scale=1.0)
aligned = cv2.warpAffine(
image,
rot_matrix,
(image.shape[1], image.shape[0]),
flags=cv2.INTER_CUBIC
)
return aligned
The Mathematical Limits of 2D Perspective Projection
While the code runs reliably, machine learning engineers must account for the fundamental limitations of 2D landmark modeling:
- Focal Length Distortion: Smartphone front cameras utilize wide-angle lenses (24mm to 28mm full-frame equivalent). At 35cm selfie distances, barrel perspective distortion widens the central midface by 15% to 30% compared to telephoto lenses (85mm).
- Pitch Flattening: Tilting the head slightly downward reduces the perceived 2D height of the lower third, introducing significant measurement variance.
- Illusion of Absolute Beauty: Beyond optical noise, clinical aesthetic literature demonstrates that rigid mathematical constants like the golden ratio fail to correlate with real-world human charm and social appeal. Real attraction is dynamic, driven by micro-expressions, posture, and voice rather than static 2D coordinates.
Architecture Considerations for Biometric Web Apps
If you deploy a facial geometry parser into production, architectural decisions are critical:
- Ephemeral Processing: Avoid storing user uploads in databases or S3 buckets. Process tensors in memory and purge raw payloads immediately.
- Client-Side WASM / TF.js: Executing MediaPipe directly in the user's browser via WebAssembly removes server compute costs while guaranteeing zero server-side biometric data retention.
Conclusion
With modern open-source models, building a functional facial landmark parser takes fewer than 100 lines of Python.
However, good engineering requires knowing the limits of the model. 2D landmarking delivers reproducible geometric data points, but optical physics and human perception ensure that a living, expressive face will always remain more complex than a matrix of coordinates.
Top comments (0)