Project 3: Face Morphing

Overview

In this project, I morph myself smoothly to Daniel Wu's face and present it in a gif. Also, I calculate the mean of male faces in the dane dataset and morph my face to it. Then, I use that mean face to create a caricature of myself.

Defining Correspondences

I use plt.ginput to select the key points and make sure the points on the source and target images are selected in the same order. Then I calculate the mean distance [(s_1 + t_1) / 2] of the corresponding points and form triangulation on those mean points. Below are the triangulations based on the mean points and the key points.

Key points and triangles of Me
Key points and triangles of Daniel Wu

Computing the "Mid-way Face"

Now I want to do two transformations: 1. Transform triangles of me to triangles of points calculated by warp fraction (call it midway face); 2. Transform triangles of Daniel to the triangles of the midway face. I need to compute the affine transformation matrix for each corresponding triangle involved. Using the 6 vertices of coresponding triangles, I can write out a linear system and solve it to get the matrix. Then I need to map all the pixels inside the triangle to the pixels of the midway face using the calculated transformation matrix. However, I do the inverse mapping so that there will be no gap between the pixels of the midway face. Now I get the points in the input image because of the input mapping, and use interpolation (RectBivariateSpline) to determine the color of the pixel of the midway face. After obtaining two midway faces (one from me and one from Daniel), I cross-dissolve the image to get the final midway face. See the result below with dissolve_frac = 0.5.

Me
Daniel Wu
Midway face

I'm much more handsome, am I, huh?

The Morph Sequence

Similar to the steps above, I first warp my source and target images into an intermediate shape configuration calculated by weighted average of the key points. Then I cross-dissolve the images to get the midway face. The warp_frac I choose is linspace(0.0, 1.0, 45), and the dissolve_frac I choose is warp_frac ** 2. I use 45 frames and each takes 1/30 second. Below is the interesting gif for morphing!

Morph

The "Mean face" of a population

I choose the dane dataset, and I parse the files to get the key points in all images where male person presents full frontal face and neutral expression. I calculate the mean face shape by averaging the key points over all images. Then I morph every face to that mean face shape. Below are some examples.

01-1m_mid
05-1m_mid
09-1m_mid
13-1m_mid

Then I compute the average face of the male population by summing all those images and take the average of the color values. Below is the average face. Looks handsome!

pop_mean_face_1m

Finally, I warp my face into the average face's geometry and the average face into my face's geometry. To do that, I need to reshape my face and the average face and draw new sequence of key points of my face. Then, the morphing happens! Below is the result:

morphed my face
morphed average face

The photo alignment can be better to improve the result. But I think this result is already good.

Caricatures: Extrapolating from the mean

Now I extrapolate the key points of my face from the points of the population mean I get in the last step. I use alpha = 2, alpha = 3, and alpha = -2. See result below.

alpha = 2
alpha = 3
alpha = -2

Bells and Whistles

Make me happy

I am very serious in the picture. I want to use the smiling male population of the dane dataset to morph my face. Below are the images where I morph just the shape, just the appearance, and both. For morphing the shape, I calculate the mean key points of the sample and morph my face to the mean face. For morphing the appearance, I just cross-dissolve my face and the mean face.

morph just the shape
morph just the appearance
both

Now I am happy!

automatic morphing

What makes me even happier is the automatic morphing. In fact, all we need is automatic key-point selecting! This is done by dlib. Use its shape_predictor_68_face_landmarks predictor. Tada! Here are the key points selected and I don't need to draw them myself anymore!

key points automatically selected
key points automatically selected

I also create a gif with 60 frames for this.

automatic morphing

Reference

Image of Daniel Wu from https://warnerbros.fandom.com/wiki/Daniel_Wu

Dane dataset from https://web.archive.org/web/20210305094647/http://www2.imm.dtu.dk/~aam/datasets/datasets.html