Face Morphing

Defining Correspondences:

In order to create the warp between images, I first have to define the correspondences on each image which will allow me to map certain characteristic areas of my face to my friend's. I picked 30 points around the face, nose, eyes and lips, as well as the corners of the image (for triangulation purposes). Once I have a list of points for each image, I got the average of each set of points that define my midway shape. I computed the Delaunay triangulation of these midway points so that I can morph my images into that shape.

Triangulation of the midway shape over the image of my friend:

Image

Computing the "Mid-way Face":

Once I have my triangulation, I loop through all the triangles. For each triangle, I get the coordinates of the corresponding triangle in my image and compute the affine transformation matrix by calculating multiplying the midway points matrix with the inverse of my image's points matrix. I find the corresponding pixels in my image by multiplying the inverse of the affine transformation matrix with the mask of the triangle and indexing into my image. I do the same for my friend's image, and add the average of both resulting triangles of pixels to the triangle in my new midway image.

My face:

Image

My friend's face:

Image

Our Mid-Way Face :

Image

The Morph Sequence:

In order to get a morph sequence from my face all the way to my friend's, I chose a range from 0 to 1 with a step of 0.05. For each fraction, I generated a warped image where the midway points are now weighted by the fraction: midway(x,y) = my_face(x,y) * frac + friend_face(x,y) * (1 - frac) . We do the same kind of weighting when adding the pixels from both images to the triangles. Finally, I create a gif with my list of images.

Morph sequence from my face to my friend's face:

Image

The "Mean face" of a population:

I used images from the FEI Face Database to create the average face of a database of Brazilian faces. I started by looping through the points of each image to get the average correspondence points to create the triangulation of the average shape of the dataset. Then, I looped through the images and warped them into the average shape just like I did previously expect I am only using one image (so there is no fraction now). Finally, I looped through these warped images and averaged them by summing and diving each by the number of images.

Some of the images of the dataset warped into the average shape:

Image
Image
Image

Average face of the FEI Face Database:

Image

Caricatures: Extrapolating from the Mean:

In order to create a caricature of my face, I warped my picture into the average shape of the database found above... not flattering.

Image

Then I warped the average face found above into my face's shape:

Image

Bells and Whistles:

I decided to try to change my ethnicity from Middle Eastern to Chinese, so I got the average image of a chinese female (from https://pmsol3.wordpress.com/2009/10/10/world-of-facial-averages-east-southeast-asia-pacific-islander/). I warped my face into the shape of that image just like I did above.

Avergage Chinese Female Image:

Image

My face warped into the average shape:

Image