I utilized matplotlib.pyplot's ginput function to define points on images and get the triangulation. This part was horrible... I kept trying to make around 40-50+ points while clicking the photos side by side but every time I finished, they would be off by 1... Eventually I figured out you could use the keyboard to click instead of the mouse (which I believe double clicks every now and then). Anyways, here are my photos with landmarks and their resulting Delaunay triangulations.
Jack keypoints
61 keypoints
Jack triangulation
Delaunay triangulation on Jack
Derek triangulation
Delaunay triangulation on Derek
Derek keypoints
61 keypoints
The midway face was calculated by finding an affine transformation matrix that mapped from the Delaunay triangles back to the source image, then we use inverse warping along with our affine matrix to find the source pixels colors that would be interpolated into the final morphed image. Lots of math happened behind the scenes here but simply, we used triangles to solve for our affine matrix and eventually map all the coordinates from our final image back to the source images to sample the right colors. Here is the result:
Original Jack
Base image
Midway Face
Warp_frac = .5
Original Derek
Base image
I built a gif detailing the morph sequence of the two faces over 45 frames. Warp_frac and dissolved_frac start at 0 and build up to 1 in increments of 1/45. Here is the gif:
Morph Sequence
Derek -> Jerek/Dack -> Jack
I used the Danes dataset for this part of the project. To get consistent keypoints on their photos and mine in this part, I made use of the dlib module to get 72 facial keypoints on all the photos in a short amount of time. Then, I calculated the average shape of their faces by taking the mean of their facial keypoint vectors. I then warped all of their faces to this average shape (since no one has an average face, some of these look unnatural). After that, I just took an average of all their warped faces to find what the average face looks like for their group. Then, I applied the average shape warp to a photo of mine to see what it would look like as well as morphing the average face into a photo of mine's facial geometry. Here are the results:
Warped Danes photo
23-1m.bmp
Warped Danes photo
31-1m.bmp
Warped Danes photo
33-1m.bmp
Warped Danes photo
38-1m.bmp
Warped Danes photo
39-1m.bmp
Warped Danes photo
40-1m.bmp
Mean Face
Mean Face Warped to Jack Geometry
Jack Warped to Mean Face Geometry
In this part, I subtracted Jack's facial keypoint vector from the average keypoint vector to get their difference, then multiplied this diff vector by 2 and added it back to the mean vector and warped Jack's face to this geometry. This is basically exaggerating the characteristics/keypoints of the photo that are disparate from the average face. Operation: mean vector + 2 * (jack vector - mean vector) = 2 * jack vector - mean vector ;;; (i.e. jack's vector is much greater than average face's)
Jack Caricature
In this part, I chose to morph Jack's face with an average baby face I found online (credit: here). I used the dlib library to make the same ordering/number of facial keypoints of both photos. Then I used these vectors to morph Jack's face to the average baby: shape, color, and finally appearance. Here are the results:
Average Baby Face
Baby Jack
Jack
Baby Shape Jack
Baby Jack Gif
Baby Color Jack