CS180 Project 3: Face Morphing
https://inst.eecs.berkeley.edu/~cs180/fa24/hw/proj3/index.html
Author: Nicolas Rault-Wang (nraultwang at berkeley.edu)
Credit to Notion for this template.
Part 1: Defining Correspondences
I used the suggested tool (link here) to create my correspondence point pairs. Each pair represents a pair of similar features in both images. For example, the centers of the left eye could be one such feature. Using these points, we can smoothly interpolate the local features from one image into the corresponding set of local features in another image.
Part 2: Computing the "Mid-way Face"
Step 2.1: Derivation of the Affine Transformation
To compute the affine warp between two arbitrary 2D triangles we will derive the affine warp from a standard triangle into an arbitrary 2D triangle . Then, given two affine warps and from the standard triangle into two arbitrary triangles, the composition will warp the first arbitrary triangle into the second arbitrary triangle.
Since an affine warp has 6 degrees of freedom, it requires 6 constraints to fully specify the transformation. The following 3 correspondences will provide us exactly 6 such constraints:
To simplify, we will lift these heterogeneous triangle coordinates into homogeneous coordinates .
Then, can simultaneously solve the affine transformation
for each the correspondence with the system:
Thus, we have the affine warp from the standard to arbitrary triangle:
Step 2.2: Backwards warp
The following steps describe our backwards warp methodology for computing an average frame between and weighted by a given . For the steps below, let and respectively be points in the source image and destination image forming the th correspondence pair .
- Transform images and into the same shape then manually create correspondence pairs for .
- Form a set of interpolated correspondence points by
- Call
scipy.spatial.Delaunay
to create a Delaunay triangulation of .- Each triangle in the average frame is defined by an array of three vertices .
- Thus, from the vector indices, we see that corresponds to the triangles in image and triangles in image .
- Use the Affine Transformation described in the previous section to compute the affine warps from to and from to .
- Call
scipy.draw.polygon
on the vertices of to obtain the set of pixel coordinates forming the interior and boundary of in
- Apply to to obtain , a set of points in image .
- Note that while the coordinates of each point in are the all integers, coordinates in not necessarily at integer coordinates.
- Thus, we must interpolate the color values at points in
- Use
scipy.interpolate.RegularGridInterpolator
to interpolate the color value each from the pixels in the image matrix for (at integer coordinates).
- Repeat steps 6-7 for image in a similar way using and .
- Compute the color value at each point from a weighted average of the interpolated colors values at and .
- Repeat steps 2-9 for every triangle in the triangulation computed in step 3.
Part 3: The Morph Sequence
Step 3.1: Frame Creation
Each frame in the morph sequence is created with the procedure described in Part 2. For a smooth warp effect, frame is created with , where is the total number of frames.
Step 3.2: Gif Creation
A call to ffmpeg
can create a .gif
from a sequence of images.
# Format string for my ffmpeg commands:
cmd = f'yes | ffmpeg -framerate {framerate} -i "{tmpdir}/%0{n}d.png" {save_dir}/{movie_name}.gif'
# Example of complete command:
“yes | ffmpeg -framerate 30 -i "tmp_frames/%08d.png" movies/part_6.fnameA_pt1-me.png.fnameB_pt1-jer.png.nframes_90.framerate_30.gif"
Part 4: The "Mean face " of a population
4.1: Computing the Mean Faces
I used the IMM Face Database for parts 4-5, which consists of 6 different expressions from 40 subjects; each expression has 58 manually labeled keypoints.
M. B. Stegmann, B. K. Ersb¿ll, and R. Larsen. FAME – a flexible appearance modelling
environment. IEEE Trans. on Medical Imaging, 22(10):1319{1331, 2003
To create the “mean face” for a particular expression type, I first extracted and cleaned the keypoints for each subjects. Then, I computed the average keypoint positions and applied my part 2 to warp each subject into this average shape. Finally, I averaged the color values from each subject to obtain the mean facial expression. The results are pictured below.
4.1.1: Examples of Warping Individuals into the Mean Geometry
4.2: Warping Myself into the Mean Faces
4.2.1: Me Warped in the Mean Geometry
4.2.2: Mean Face Warped into My Geometry
Part 5. Caricatures: Extrapolating from the Mean
To extrapolate from the mean shape, I created morphed images of myself with and . The resulting extrapolated shapes rapidly deteriorate in quality with large magnitudes of . (Note: in the plots below, please interpret “alpha” as .)
Bells & Whistles
I chose to implement the morph sequence task. To do this, I started with my function make_animation_frames(imgA, imgB)
, which creates a morph animation from imgA
to imgB
. Then, I applied it to create a smooth morph effect across consecutive images in a sequence img_0, img_1, im_2, ..., img_N
. This required labeling correspondence pairs between each img_k, img_(k+1)
. Also, by setting img_N = img_0
, my animations could loop infinitely and seamlessly.