This project is for producing a "morph" animation of my face into someone else's face, compute the mean of a population of faces and extrapolate from a population mean to create a caricature of my face.
For part 1, I cropped the image from me and another person (Margarita Bazyluk) and imported the two images. And I used the tool from a last year's student (as described in the project instruction) to label the points on both faces following the same order. Then I imported these two point sets to compute the points in the midway image with this formula "mid_points = (im1Points + im2Points) / 2". After creating the triangle using Delaunay, I got this midway triangle image [figure1_1]. Also I got the triangle diagram on both faces [figure1_2] [figure1_3].
To compute the "Mid-way Face", I followed this steps: (1) computing the average shape (have been done in part 1),
(2) warping both faces into that shape, (3) averaging the colors together. For part 2, since we don't need to show
the morphing process, I just computed the mean value of both points and colors of both images. Also, I set the affine
transformation matrix in compute_affine function, after getting the affine transformation matrix then I computed the
inverse of the affine transformation matrix, finally used RegularGridInterpolator (similar as the griddata) to interpolate
the value of color on the midway image.
I implemented the above approached on each three channels separately, so after getting the blended color on each channel, I then
used np.dstack to get the final midway image[figure2_2].
For morphing process, I defined the morphing function and got the morphing image using "morphed_im = morph(im1, im2, im1_pts, im2_pts, tri, warp_frac, dissolve_frac);" as described in the instruction. I set the warp_fraction and dissolve_fraction as the same value change from 0 to 1. After getting 45 frames, I made the 45 images into a gif format to show the morphing process[figure3].
For part 4, I used the FEI dataset with the points provided correspondingly. I choosed the first 100 faces (1a, 2a, ..., 100a) to compute the average shape(compute the mean points coordinates, getting triangulation). After getting the average shape, I warpped each faces into the average shape, the examples are shown in the following from [figure4_1] to [figure4_8]. After finishing the color blending, I got the average face [figure4_9]. Also, I warped my face into the average shape [figure4_10], inversely, I warped the average shape into my face[figure4_11].
To produce a caricature of my face, I used extrapolation from the population mean I calculated in Part 4. Say "p" is my face, "q" is the average face, the formula is: caricature = q + alpha(p-q). In this case, if alpha = 1, the result of caricature is my face, if alpha = 0, the result of caricature is the average face, if alpha is greater than 1, the result of caricature will have more my_face's features, if alpha is less than 1, the result of caricature will have more the average_face's features. I choosed alpha = 1.5, 1, 0.5, generated the caricature images correspondingly.
For part 1 of Bells and Whistles, I chose a face from difference gender and ethnicity to try morphing.
For part 2 of Bells and Whistles, I made a video morphing five skaters' faces. The video theme is "Romeo and Juliet", which means the
five skaters all have had skating programs using "Romeo and Juliet" theme.
I believe the "Romeo and Juliet" theme is not only about LOVE, it's more about FREEDOM.
For part 3 of Bells and Whistles, I tried a different morphing algorithm, especially a different color blending algorithm. Instead of using t in range(0, 1) as the dissolve_frac, I used sigmoid function to implement t value. the value of t is "1 / (1 + np.exp(- k * (t - 0.5)))", with k = 10. In this case, the morphing process is not evenly and gradually change, it changing speed following the sigmoid function curve instead.