Use Python to calculate the facial width to height ratio (fWHR)

Posted by Ties de Kok - Nov 22, 2017

There is a rise of papers that calculate the Facial Width-to-Height ratio (fWHR) as a proxy for the personal/physical traits (“facial masculinity”) of executives such as CEOs.

There is no perfect definition on what the fWHR captures, but most papers interpret the fWHR to be associated with traits such as aggression, risk-seeking, and egocentrism. For a more comprehensive discussion I recommend reading Lefevre, et al. (2013) and Jia, van Lent, and Zeng (2014), available here:

How do these papers calculate the fWHR?

The common procedure to calculate the fWHR is to manually determine the bizygomatic width and the upper-face height based on a picture of the person. This procedure has several difficulties:

  1. Manual calculation is very labor intensive leading to small samples sizes. This is especially problematic if cross-validation is desired as multiple raters need to calculate the fWHR for the same picture.
  2. There are multiple definitions available as to what the correct points of the face are that need to be used to calculate the fWHR. For example, some papers determine the upper horizontal line by placing it below the eyebrows, whereas other papers place it above the eyebrows.
  3. The calculated fWHR is sensitive to misalignment of the face in the picture, calculating the fWHR of one person based on multiple images in different scenarios is likely to result in different values for the fWHR. In a real-life scenario, it is preferred to use multiple images of the same person, and aggregate the calculated fWHR to yield one fWHR for each person. This procedure is largely unfeasible if the fWHR is calculated manually because it substantially increases the amount of labor per observation.

Automatically calculate the fWHR using Python

Step 1: face and facial feature recognition 

The first step to be able to automatically calculate the fWHR is to detect the face and facial features required to determine the corners of the “fWHR box”.

Recent developments in machine learning have greatly advanced our ability to use trained algorithms to detect faces (“face recognition”) and to automatically find facial features such as the eyes, mouth, and nose.

One recent Python packages (named “Face Recognition”) in particular has received a lot of attention because it provides an easy-to-use higher level interface build on the state-of-the-art dlib face recognition algorithm build using deep learning. The dlib algorithm is able to detect faces in pictures with an impressive 99.38% benchmark accuracy. Both can be found at the following links:

The “Face Recognition” package allows us to identify faces and to get the locations and outlines of each person’s eyes, nose, mouth and chin:

Step 2: calculate the fWHR

I have created a Jupyter Notebook containing experimental code that will use the “Face Recognition” package to automatically calculate the fWHR.

As provided it has the following features:

  1. Images can be entered through a URL or by providing the path to a local image
  2. Using the top argument it is possible to use the eyelid or eyebrow as point for the top line
  3. By default it will show the box used to calculate the fWHR ratio, this is controlled by the show argument
  4. It will use the different facial characteristics to determine whether a picture is unsuitable for calculating the fWHR, allowing to automatically feed multiple images without pre-classifying them as suitable:

The code is available on GitHub:

How does it work?

The “Face Recognition” package determines the following points “under the hood”:

My codes uses these points to determine the different corner points of the fWHR box:

Note, this code requires the “Face Recognition” package which currently only works on UNIX systems.

Once the corner points have been determined, it is a matter of performing a basic calculation to get the fWHR: