Project 3: Face Morphing

By Sriharsha Guduguntla

Project 3 entails morphing one image into another image and using a population of images to see if you can morph your own image to the average face of the population and vice versa. I also created caricatures of my face based on the average face of the population. At the end, I did the bells and whistles assignments and made a music video of my family changing over the years and how we all have glown up over the years.

Defining Correspondences

I manually labeled 60 different correspondence points and constructed Delaunay triangles as shown below of the average shape.

Sai with Average Delaunay

George with Average Delaunay

Computing the "Mid-way Face"

I created a morph sequence of my face with George Clooney's face. I used 48 frames of the sequence to construct my gif. To create the morph sequence, I took the Delaunay triangles from the previous part and looped through all the triangles and warped each triangle in the original images into the average shape, after which I inferred the rgb color values by simply rounding the float rgb values to the nearest integer. I originally thought of using interp2d, but this result turned out to work decently well for me as well, so I stuck with it. For the actual affine warping of the triangles, I computed an affine transformation matrix for each triangle and used the polygon function to create a mask of all the points in the triangle and applied the inverse transformation matrix on all the points in the triangle to perform the warp. I had two hyperparameters in the range [0,1] as recommended in the spec, warp_frac and dissolve_frac which I simply scaled according to the current timestep in my morph sequence.

Original Images (sai on the left, george on the right)

Sai X George Midway

Sai X George Morph Animated GIF with 48 frames

Sai X George Morph Sequence Frame by Frame

The "Mean face" of a population

Calculated the average Danish face of 37 different images of Danish people and then warped my face into the geometry of the average face and warped the average face into the geometry of my face. To do the warping, I simply used my morph functions from the previous part following the same steps outlined above.

Danes Avg Face

Sai with Average Delaunay

Avg Danish Face with Average Delaunay

Sai X Avg Danish Face Morph Sequence Frame by Frame

Sai X Avg Danish Face Morph Animated GIF with 48 frames

Avg Danish Face Warped into Sai Face geometry

Sai Face Warped into Avg Danish geometry

Caricatures: Extrapolating from the mean

To create caricatures of my face using the average Danish face, I just increased the warp_frac to be bigger than 1 to extrapolate from (1, infinity) and I also decreased the warp_frac to be smaller than 0 to extrapolate from (-infinity, 0). As you can see in the images below, when extrapolating such that I create a "hyper-danish" face, my face is warped such that my nose is thinner and my lips are not as wide. This is to accentuate the features in the average Danish face. However, when I extrapolate in the opposite direction and create an "anti-Danish" face, the face has a wide nose like I do and wide lips which accentuate my facial features.

warp_frac > 1

warp_frac < 1

Bells & Whistles

For my bells & whistles portion, I created a music video of a morph sequence of my family (parents and younger brother) as we evolved over the years (gladly glew up). Thought it would be interesting to see how we all changed and how all our features have become more different over time. There is one image in the video where the morph is not smooth and has a visible triangle. This is due to the selection of my correspondence points. I tried to select the correct points multiple times but seeing that I chose 60 points for each of the images, the chances of human error are very high, so I acknowledge this, but for demonstration purposes, I decided to leave as is.