How MobileNet V2 Serves as the Backbone in PFLD: Architecture and Implementation
MobileNet V2 functions as the feature extraction backbone in PFLD by generating hierarchical feature maps (feature2 through feature6) using depthwise separable convolutions with residual connections, which simultaneously feed the main landmark regression head and an auxiliary pose estimation branch.
The PFLD (Progressive Face Landmark Detection) repository by guoqiangqi implements a lightweight facial landmark detector that leverages MobileNet V2 as its backbone architecture. Written in TensorFlow 1.x, the model uses depthwise separable convolutions to extract multi-scale features while maintaining a compact parameter count of approximately 2 million. Understanding how MobileNet V2 is integrated as the backbone reveals how the architecture balances computational efficiency with the accuracy required for 196-dimensional facial landmark prediction.
MobileNet V2 Backbone Implementation in model2.py
The core backbone logic resides in model2.py, where the mobilenet_v2 function constructs the convolutional stack. This implementation follows the standard MobileNet V2 inverted residual structure, utilizing slim.convolution2d for pointwise projections and slim.separable_convolution2d for depthwise filtering.
Core Architecture Definition
The function signature and initial layers establish the input preprocessing and early feature extraction:
def mobilenet_v2(input, weight_decay, batch_norm_params):
# Initial expansion: 96×96×3 → 112×112×3 (via padding/stride logic)
conv_1 = slim.convolution2d(input, 32, [3, 3], stride=2, scope='conv_1')
...
The full implementation spans lines 10 through 210 of model2.py【model2.py#L10‑L210】. Within this block, the function progressively builds inverted residual bottlenecks, each consisting of expansion convolutions, depthwise separable filtering, and linear projection convolutions.
Hierarchical Feature Map Outputs
MobileNet V2 in PFLD exposes five distinct hierarchical feature levels that serve as the multi-scale backbone representations. These tensors are captured in a dictionary returned by the mobilenet_v2 function and consumed by downstream heads.
| Feature key | Spatial resolution (relative to input 96×96) | Channel depth |
|---|---|---|
feature2 |
48 × 48 | 16 |
feature3 (pfld) |
24 × 24 | 24 |
feature4 |
12 × 12 | 32 |
feature5 |
6 × 6 | 96 |
feature6 |
3 × 3 | 320 |
The feature3 tensor is specifically aliased as pfld within the backbone code, indicating its role as the primary feature level for the main landmark regression task. Residual connections within the MobileNet V2 blocks—such as block_3_2 = conv3_1 + conv3_2—preserve gradient flow during training, enabling effective feature reuse across these hierarchical levels.
Integration with PFLD Heads
The backbone does not operate in isolation; it feeds two distinct functional branches within the create_model function (lines 393‑438 of model2.py)【model2.py#L393‑L438】.
Main Landmark Regression Head
The pfld_inference function consumes the feature dictionary returned by mobilenet_v2. It specifically extracts the pfld feature map (24×24×24) and performs additional convolutions to regress 98 facial landmarks (196 dimensional output representing x,y coordinates). The implementation concatenates multi-scale features (multi_scale concatenation) to enhance localization accuracy.
Auxiliary Pose Estimation Branch
Simultaneously, the backbone provides an intermediate tensor labeled auxiliary_input within pfld_inference. This tensor feeds a secondary branch dedicated to estimating head pose (Euler angles). The create_model function wires this as follows:
# Inside create_model (model2.py L393-438)
pfld_input = features['auxiliary_input']
net_aux = slim.convolution2d(pfld_input, 128, [3, 3], stride=2, scope='pfld_conv1')
...
euler_angles_pre = slim.fully_connected(fc1, num_outputs=3,
activation_fn=None, scope='pfld_fc2')
This dual-head architecture allows the MobileNet V2 backbone to support multi-task learning, where the shared low-level features benefit both landmark detection and pose estimation.
Practical Implementation Example
To construct a PFLD model with the MobileNet V2 backbone in TensorFlow 1.x:
import tensorflow as tf
from model2 import create_model
# Placeholder for a batch of RGB face images (96×96)
image_ph = tf.placeholder(tf.float32, shape=[None, 96, 96, 3], name='input')
# Placeholder for ground-truth landmarks (196 = 98 points × 2)
landmark_ph = tf.placeholder(tf.float32, shape=[None, 196], name='landmark')
# Dummy args object mimicking command-line arguments
class Args:
weight_decay = 1e-4
args = Args()
# Build the graph (phase_train=True for training)
landmarks_pred, loss_landmarks, euler_pred = create_model(
image_ph, landmark_ph, phase_train=True, args=args)
# The returned tensors can now be fed into an optimizer, exported, etc.
Running this snippet instantiates the MobileNet V2 backbone via pfld_inference, produces the multi-scale feature hierarchy, and attaches both the landmark regression and pose estimation heads.
Summary
- MobileNet V2 Backbone: Implemented in
model2.py(lines 10‑210), the backbone uses depthwise separable convolutions and inverted residual blocks to extract features from 96×96 input images. - Hierarchical Outputs: The backbone returns five feature levels (
feature2throughfeature6) with resolutions ranging from 48×48 down to 3×3, enabling multi-scale landmark detection. - Dual-Head Architecture: The
pfldfeature map (24×24×24) feeds the main 196-dimensional landmark regression head, whileauxiliary_inputsupports a secondary pose estimation branch predicting 3 Euler angles. - Lightweight Design: The architecture maintains approximately 2 million parameters, making it suitable for real-time facial landmark detection on resource-constrained devices.
Frequently Asked Questions
What input resolution does the MobileNet V2 backbone expect in PFLD?
The backbone processes RGB face images at 96×96 pixels, as defined in the input placeholder shapes within model2.py. The initial convolution layer applies a stride of 2, immediately reducing the spatial dimensions to 48×48 while expanding the channel depth to 32, initiating the feature extraction hierarchy.
How does the auxiliary pose branch connect to the MobileNet V2 backbone?
The auxiliary branch accesses an intermediate tensor labeled auxiliary_input produced within the pfld_inference function. This tensor represents a feature map from an early stage of the backbone (distinct from the final pfld output) and is passed to a separate convolutional subnetwork that regresses three Euler angles representing head pose, as implemented in create_model (lines 393‑438).
Why was MobileNet V2 chosen as the backbone for PFLD?
MobileNet V2 was selected because its inverted residual structure and depthwise separable convolutions provide an optimal trade-off between computational cost and representational power. The architecture generates rich hierarchical features (from 48×48 down to 3×3 resolutions) necessary for precise 98-point landmark localization, while keeping the total parameter count near 2 million, enabling real-time inference on mobile and edge devices.
What are the channel dimensions of the feature maps extracted by the backbone?
The MobileNet V2 backbone in PFLD produces feature maps with the following channel depths: feature2 has 16 channels, feature3 (aliased as pfld) has 24 channels, feature4 has 32 channels, feature5 has 96 channels, and feature6 has 320 channels. These varying depths accommodate the increasing complexity of representations at deeper network stages while maintaining efficient information flow through the inverted residual blocks.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →