(for higher quality and more faces, see videos below)
I morphed two images into each other via the following steps:
- I used cpselect in matlab to select 55 corresponding points in my two images.
- I added 4 corner points to simplify coding.
- I wrote the specified function computeAffine.m; separating out the translation into different matrices was key.
- I wrote code-calling code runruncode.m to create the 61 frames; this code used the function morph.m, which at first ran slowly but I sped up after realizing that I should compute the affine transform at each triangle, not each point.
- Mencoder was used to check the movie.
|00 (rys) ||25||40||60 (saboutal) |
The 61 pictures.
I scanned in many pictures of myself growing up, weaned out the ones where I looked truly dorky (let's just say there was a 8th - 13th grade period we don't need to know about), and ended up with 10 images. These I selected head shots from, then scaled the resulting crops to 600x600, and used cpselect to mark 43 points in each. When I ran the morph through them, the images shifted about too much. Thus I computed the projective transform from the average points to each image's points, and used imtransform to correct each image. This, however, squished all the faces to be the same aspect ratio - and I was looking to show the evolution of face shape! I repented of my error and switched to an affine transform. The code is runagemorph.m and runagemorphcaller.m.
(use mplayer or equivalent)
The original woodcut, above, from The Official M.C. Escher Website, was registered with 701 points, input_points and base_points. This took several hours. Cpselect crashed and burned at ~250 points (and ceased to be real-time responsive well before then). I resolved this problem by writing my own image registration tool in Perl/Tk; the source is here. The tool worked better than cpselect because 1) it is fast, and 2) it numbers the points in each image independently in order, so you can click a few points in one image, then go over to the other and click on those corresponding points in order.
(switches direction halfway through)
A picture of part of the selecting:
I computed the mean face by creating the delaunay triangulation on the average of all points, then adding each face's contribution by repeated calls to the morph function. As arguments I passed in the average points and a "0" for warp_frac, and 1/i for adding in the i'th image.
| || || |
| Mean face || rys warped to avg || avg warped to rys |