How to Prepare and Use the WFLW Dataset for PFLD Training: Complete Setup Guide

To prepare and use the WFLW dataset for PFLD training, download the WFLW images and annotation files, extract them into the repository's data/ directory structure, and execute python data/SetPreparation.py to generate processed train_data/ and test_data/ folders containing normalized images and list.txt label files.

The guoqiangqi/pfld repository provides a stand‑alone preprocessing pipeline that converts raw WFLW resources into the exact format consumed by the TensorFlow training script. This guide walks through the mandatory directory layout, the internal mechanics of the preparation script, and how to verify the output before launching train_model.py.

Downloading WFLW Images and Annotations

Before running any code, you must obtain the original dataset files. The WFLW (Wider Facial Landmarks in-the-wild) dataset provides 10,000 faces with 98 manually annotated landmarks.

Downloading WFLW Images

The image archive contains 7,500 training and 2,500 test face images.

  • Google Drive: https://drive.google.com/file/d/1hzBd48JIdWTJSsATBEB_eFVvPL1bx6UC/view?usp=sharing
  • Baidu Drive: https://pan.baidu.com/s/1paoOpusuyafHY154lqXYrA

Download WFLW_images.zip and preserve it for extraction in the next step.

Downloading Annotation Files

The annotation tarball provides the 98-point landmark coordinates, face bounding boxes, and attribute flags (pose, expression, illumination, etc.).

  • Direct link: https://wywu.github.io/projects/LAB/support/WFLW_annotations.tar.gz

This archive contains list_98pt_rect_attr_train.txt and list_98pt_rect_attr_test.txt, which SetPreparation.py parses line-by-line.

Setting Up the Directory Structure

The preparation script expects a rigid folder hierarchy under the repository root. Misplacing the archives will cause FileNotFoundError during execution.

Create the following layout:

pfld/
├── data/
   ├── WFLW_images/                    # Extracted image folder

   └── ... (10,000 .jpg files)
   └── WFLW_annotations/
       └── list_98pt_rect_attr_train_test/
           ├── list_98pt_rect_attr_test.txt
           └── list_98pt_rect_attr_train.txt
├── data/SetPreparation.py
└── ...

Execute these commands from the repository root to unpack the downloads:


# Create expected directories

mkdir -p data/WFLW_images
mkdir -p data/WFLW_annotations/list_98pt_rect_attr_train_test

# Extract archives

unzip WFLW_images.zip -d data/WFLW_images
tar -xzf WFLW_annotations.tar.gz -C data/WFLW_annotations/list_98pt_rect_attr_train_test

The script references these paths directly at lines 199–204 of data/SetPreparation.py:

imageDirs = './data/WFLW_images'
Mirror_file = './data/Mirror98.txt'
train_file = './data/WFLW_annotations/list_98pt_rect_attr_train_test/list_98pt_rect_attr_train.txt'
test_file = './data/WFLW_annotations/list_98pt_rect_attr_train_test/list_98pt_rect_attr_test.txt'

Running the WFLW Preparation Script

With the data in place, run the preprocessing script to generate training-ready tensors:

python data/SetPreparation.py

This executes the full pipeline defined in SetPreparation.py, performing three core operations:

1. Parsing Annotations with ImageDate

The ImageDate class (lines 28–44) splits each line of the annotation text file into:

  • Landmarks: 98 points (x, y) normalized by image width/height.
  • Bounding box: Face rectangle (x, y, w, h).
  • Attributes: 6 binary flags (pose, expression, illumination, make-up, occlusion, blur).
  • Euler angles: Pre-computed pitch, yaw, roll (or placeholders).

2. Image Processing and Augmentation

The load_data function (lines 59–98) handles:

  • Cropping: Extracts a square region 1.2× the tight bounding box.
  • Resizing: Scales the crop to image_size (default 112×112 pixels).
  • Data augmentation (training set only):
    • Random rotation between -20° and +20° (repeated 10× per image).
    • Horizontal mirroring using the indices defined in data/Mirror98.txt.

3. Generating Output Files

The save_data function (lines 146–170) writes:

  • Processed images: Saved as PNG files in train_data/imgs/ and test_data/imgs/.
  • Label lines: Each line contains:
    1. Relative image path.
    2. 196 normalized landmark coordinates (98×2).
    3. 6 attribute integers.
    4. 3 Euler angles (pitch, yaw, roll) calculated by calculate_pitch_yaw_roll in euler_angles_utils.py.

The get_dataset_list function aggregates these lines and writes train_data/list.txt and test_data/list.txt, which are the direct inputs to the training script.

Verifying the WFLW Dataset Preparation

After execution, confirm the output structure:

tree train_data test_data -L 2 | head -n 20

Expected output:


train_data/
├── imgs/
│   ├── 0_0.png
│   ├── 0_1.png
│   └── ...
└── list.txt
test_data/
├── imgs/
│   ├── 0_0.png
│   └── ...
└── list.txt

Inspect a sample label line to ensure correct formatting:

head -n 1 train_data/list.txt

The line should contain 207 space-separated fields: 1 path + 196 landmarks + 6 attributes + 3 angles.

Integrating with PFLD Training

The train_model.py script expects the list.txt files generated above. In the repository code, the data loader reads each line and splits it into tensors:


# Simplified excerpt from the training data pipeline

def parse_line(line):
    parts = line.strip().split()
    img_path = parts[0]
    landmarks = np.array(parts[1:1+196], dtype=np.float32).reshape(98, 2)
    attributes = np.array(parts[1+196:1+196+6], dtype=np.int32)
    euler_angles = np.array(parts[-3:], dtype=np.float32)  # pitch, yaw, roll

    return img_path, landmarks, attributes, euler_angles

Pass the generated paths to the training script:

python train_model.py --train_list train_data/list.txt --test_list test_data/list.txt

Summary

  • Download the WFLW images and annotation files from the official mirrors (Google Drive, Baidu Drive, or the project website).
  • Extract archives into data/WFLW_images and data/WFLW_annotations/list_98pt_rect_attr_train_test to match the hardcoded paths in SetPreparation.py.
  • Execute python data/SetPreparation.py to parse annotations, crop faces to 112×112, apply augmentation (rotation, mirroring), compute Euler angles via euler_angles_utils.py, and write train_data/list.txt and test_data/list.txt.
  • Verify that list.txt contains 207 fields per line (path, 196 landmarks, 6 attributes, 3 angles) before launching train_model.py.

Frequently Asked Questions

What is the exact directory structure required for WFLW dataset preparation?

The SetPreparation.py script expects images at ./data/WFLW_images and annotation text files at ./data/WFLW_annotations/list_98pt_rect_attr_train_test/list_98pt_rect_attr_train.txt (and test). Create these folders under the repository root and extract the downloaded ZIP and TAR archives into them before running the script.

How does the SetPreparation.py script handle data augmentation?

During processing of the training split, the script generates 10 augmented variants per source image. It applies random rotations between -20 and +20 degrees and optionally mirrors the image horizontally using the landmark indices defined in data/Mirror98.txt. The test split is processed without augmentation to ensure consistent evaluation.

What format does the generated list.txt file follow?

Each line in list.txt contains 207 space-separated values: the relative path to the processed PNG image, 196 floating-point numbers representing the 98 normalized (x,y) landmark coordinates, 6 integer attribute flags (pose, expression, illumination, make-up, occlusion, blur), and 3 floating-point Euler angles (pitch, yaw, roll) pre-computed by euler_angles_utils.py.

Can I skip the preprocessing and use raw WFLW images directly for training?

No. The PFLD training pipeline in train_model.py expects normalized 112×112 crops, pre-computed Euler angles, and specific attribute flags that are only generated by SetPreparation.py. Running the preprocessing step once creates reusable list.txt files that eliminate the computational overhead of on-the-fly angle calculation during training epochs.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →