Morphing Power
Project 3

This project was coded mostly in MatLab, the exception was one function, 'mytsearch,' that was written in C and compiled to work from the MatLab environment.

Labeling

The first step in a successful warp is identifying the common points between the two images. This process is where a lot of the fine tuning can occur, as to where and how many labels you use. The labels must match for each of the images. For example if label 10 in image A correlates to the right eye of the image, then it is essential for label 10 in image B to be the right eye. I decided to use more than the recommended 43 labels for each face, I ended up using 50 labels for a little more detail.

For selecting the labels, I wrote a function that walked the user, point by point, through the process. In addition to the face labels, I added labels around the outside of the image to help with the morph, this makes the computation a little longer for each step, but it results in an overall smoother morph.

Triangulation

The next step in the morphing process is to define triangles between all of the labels. For each set of images a median label is computed, and thrown in to MatLab's 'delaunay' function which computes the DeLaunay triangles for the labels. These triangles give the frame work for the morph.

The Morph

The actual morph function gets a little complicated, I will try to explain it the most logically without the use of pictures. The first process is to compute afine transformations for each of the triangles. The triangles in image A will correlate to the same triangles in image B, the morph involves warping the two images in to a common 'geometry,' so that their modified triangles end up overlapping each other. These transformations can be defined by the following system:

        a * x + b * y + c = x'
        d * x + e * y + f = y'

                 or

        [x]   [ a b c ]   [x']
        [y] * [ d e f ] = [y']
        [1]   [ 0 0 1 ]   [1 ]

In common English, given the input coordinates (x,y) the output is translated to the new points (x' , y') buy the afine transformation matrix. This transform ends up being a shift and a translation.

Once a transform is computed for every triangle, at every point in your output image a correlating pixel in the source image is found using the afine transformation. Two different warped images end up being computed, one forcing image A to the common geometry, and one forcing image B to the common geometry. The intensity of each pixel from each of the warped images are averaged together according to a dissolve rate, and the output morph is computed. Now this is repeated over and over again, with different weights on the dissolve and on how to compute the common geometry. On the time line, images that are closer to image A will be closer to image A's geometry then image B. This process is repeated over and over again to give the smooth warp from one image to another.

Average Face

The concept behind this is to find the 'average' face in a set of pictures. This ends up being fairly simple once you have the above morph figured out.

Taking all of the labels, you can compute a 'mean geometry,' a set of triangles that is evenly influenced by all of the faces. Once this average geometry is found, each of the images are warped to fit this geometry, and then all of the warps are blended together to give the output image. This works better than just taking a blending of all of the images due to the fact that all of the images are not the same format, this way all of the information is normalized, and then blended.

The Bearding Function

This ends up being a rather elegant process. The target stays the same from the stand point of a morph, but the 'beard' is morphed to fit the geometry of the target. First a user must define what the beard is, which produces a mask to be used by the morphing function. Then just that part is warped to the target geometry. This warped beard is just blended (I used a Poisson blend from project 2) back on the the target image. You really could do this for most features, you could add glasses, you could change eye color, you could transfer earrings. The options are vast!

I ran in to a little bit of a problem using my own image for the beard source. I was sort of 'frowning' which made rather interesting results when pushed on to a smiling face. To overcome this, I also selected the lips in the beard, so that only the 'hair' is used. You can see the results are fairly impressive.

Computation Time

One singe morph, using two 1166x1400 images : 1 mins 40 seconds
Average Face: 13 minutes

Reflection

This was a very amusing program to work on. The first output, which was a 50/50 morph from my face to Skanda's, was ridiculous. The half Indian, half Caucasian with a beard and odd looking glasses would make anyone laugh. Wrapping my head around the 'inverse' transformation took a little bit, but looking back, it makes perfect sense now. As you could see, I really enjoyed playing around with the morph function, I can foresee using it in the future just simply for fun.

Good Morphs:
-Super cool outputs
-Fun applications
Bad Morphs:
-wrestling with compilers and MatLab (ate up about 6 hours) UGG!
-Labeling.... and more labeling.... and more labeling.
Go back to the Project Home Page