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.