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!
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.
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:
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.
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.
As an extra bit of fun, below is a face-morphing music video of me and 14 others in the class!
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 😁