Face Morphing

By Nikhil Sharma

In this project, I implemented an algorithm that "morphs" one face into another. This works after manually initially selecting a few dozen points of correspondence between the two images (e.g. eyes to eyes, mouth to mouth, and so on). I selected roughly 50 points per image, and using more points typically yields a better morph (as intuition would suggest).

We then utilize a technique named Delaunay triangulation to split the images into a set of triangles and compute a weighted "average face" between the two images according to some variable weight. Both input faces are then morphed into this "average face" and their color values are averaged as well.

By varying the weights involved and applying a cross-dissolve, we can generate a appropriate sequence of images that can be combined into a seamless morphing video. See for yourself the results below!

Computing the "Mid-Way" Face

Before applying a full cross-dissolve to generate the image morph, the first step was to get a working "mid-way" face, which computes the average face shape using the averages of the selected correspondence points. Below are three images of me, my friend Sahil, and the corresponding midway face between our faces!

Click any of the above images to expand the view.

The Full Morph!

Once this started to work, the next step was easy: the cross-dissolve. The cross-dissolve means recomputing the midway face several times for different weights: rather than compute the true midpoint between each correspondence, compute a weighted average point for each pair using a varying weight parameter. Using an evenly space range of weights and applying an affine transformation for each triangle in the two original images to each midway image was enough to generate a sequence of transforms that I combined to yield a good morph. Here's the result:

The "Mean Face" of a Population

In this part, I downloaded a dataset of the faces of forty Danish people, along with files of annotated correspondence points. I used the same averaging procedure from above to compute the face structure of the "average" Danish person (essentially averaging across the 40 people instead of simply two as before). With this, I warped each of the 40 individuals to this mean face; below are a couple examples of the transformed images; the left and right columns represent before and after images respectively.
After applying the transformations, I computed the average face of the Danish man and woman from this sample by averaging the pixel values across the transformed faces. The results (shown below) turned out much better than I expected!

Here are the three people's faces above morping into the mean Danish face (male or female, accordingly):

Next we'll play with the following image of me:

With this image, you can see displayed below both (1) my face mapped warped into the average geometry and (2) the average geometry warped into my face:

Overall, I can conclusively say I would not look good as a Dane. It seems that the average Dane face is considerably more square than mine, and this coupled with the fact that my face in the image is a smaller fraction of the image than the average Dane face makes it look really strange indeed. Analogous story in the reverse direction.

Caricatures: Extrapolating from the Mean

In the final algorithm in this project, I extrapolated from the mean to generate some caricatures of myself. The central idea is that instead of selecting a weight that finds some intermediary face between two input images, to select a weight that's greater than 1. This achieves the effect of warping an image by pulling it beyond the middle ground between the two images, generating results that are quite horrific indeed! Here they are, with weights of 1.2, 1.5, and 1.8 respectively:

They will look better if you click to expand.

Bells and Whistles

As an extra bit of fun, below is a face-morphing music video of me and 14 others in the class!

Parting Thoughts and Failures

Overall this project was very fun! It's ridiculous to imagine how some simple triangulation and affine transformation can lead to such a rich and fascinating algorithm. Computing the morph with cross-dissolve turned out to be quite tricky, with a lot of room for errors that were hard to detect. In fact, at one point, I had what looked to be a reasonable morph but was simply one image fading into another! Additionally, I thought that the GIF generation process was quite time-consuming to have to do several times over. Overall, I thought it was a very fun exploration into the world of face morphing 😁