A few months ago, I tried to implement a simple class in AS 3.0 to do morphing between two images. I think it could be interesting and cool to share it and explain a bit how it works. You can see below a wonderful geek’s example to illustrate the final result ;-) :

The Flash plugin is required to view this object.

Principes

Morphing is an image processing to operate a metamorphosis between two images. I guess until there I teach you nothing ;-) .  A simple way to transform an image to an other is to do cross-dissolving. It is just a pixel by pixel color interpolation to fade from one image to an other. But the result is usually bad because the two images are often not aligned and just cross-dissolving gives a “double-image” effect. If you think of an example of two faces where eyes, mouth, etc are not at the same positions you can easily understand the problem of misaligned regions when you simply blend the two images. In order to overcome this problem and to build a fluid transition you have to firstly warp/distort the two images. Warping determines the way in which the pixels in one image should be mapped to the pixels in the other image. It allows a kind of “shape matching” between the two image at each instant t of the morphing process.

Below is a little schema of the process for t = 0.5 (t is between 0 and 1):

morphing

Warping

Warping is the difficult step of morphing. There are a lot of techniques available. For my part I used a technique based on a triangular mesh because it works well and is easy to implement with the Flash drawing API. Let see how it works:

  • Firstly I find some corresponding points between the two images:

morphpts

  • Then according those fields of points I can build the initial triangular mesh for each images. To achieve that I use the Delaunay triangulation algorithm. Some talented developers have already explained and  implemented it in AS 3.0. You can find one here from Zachary Forest Johnson or  here from  Nicoptère.

mesh

  • Now I have my two initials meshes I can interpolate an intermediate mesh for each intermediate image of the morphing process. The final step is to texture each triangle of the mesh according the triangle transformation and the initial triangle texture.

warping

As I use the Flash drawing API to texture my triangles I just need to find a transformation matrix for each triangles. In fact a way to achieve” triangle texturing” has already been implemented here by the magic André Michelle. It’s the same method is  used in a lot of  Flash 3d engines. This method is just a combination of transformation.  I recently found this well-done paper made by renderhjs and posted on the Flashkit board. You should read if you want to understand the method.

Cross-dissolving

This is the easiest step. Just blend the two warped images in setting the alpha of each images according the t parameter of the morphing process. First image alpha = 1 and the second image (on the first) alpha = t.

Application

Demo Just a little Flex application to edit images meshes and test the morphing

Sources:

Morpher.as The class to compute the morphing intermediate images

MeshTriangle.as The class to build a mesh triangle. Each point of the triangles is referenced by the index of the points in an array of points.

Mesh.as The class which builds a valid mesh object used by the Morpher class. It is built by an array of poinst and an array of MeshTiangle object built with thoses points.

Now you can try by yourself with different images,  and have fun! ;-)

Tags: , , , ,
14 Responses to “Morphing”
  1. Benjamin says:

    Nico aka nicoptère (http://en.nicoptere.net/) has sent me some nice links relative to Delaunay triangulation and morphing:

    http://nodename.com/blog/2008/10/12/have-you-seen-this-man/ (implementation in Flash 10 whit drawTriangles)

    http://www.neuroproductions.be/experiments/fle_delaunay_triangulation/

    Really impressive and thanks to him !

  2. seltar says:

    nice implementation, and well explained! Keep up the good work

  3. [...] Muki Muki » Morphing モーフィングの技術。これはすごく気になってた! [...]

  4. satoru aoki says:

    wow!! thank you!

  5. rats says:

    really nice work…

  6. hovox says:

    very nice , i’ll use it :) thanks :)

  7. hovox says:

    MeshTriangle class is only for your use. May be declare it as private class in Morpher class ?

  8. [...] otro lado, con los enlaces que he puesto a nadie le debería costar mucho sacarlo. Y sobretodo con éste otro, que es donde está todo recopilado y explicado paso a paso. SHARETHIS.addEntry({ title: [...]

  9. Bala says:

    Excellent! Thank you

  10. Matt says:

    Hi Benjamin, Nice work on your morpher class !

    I’ve been trying to get your morpher class to work but I can’t get any output from it. I’m getting BitmapData but it renders as white?? Not sure if I am passing the correct points / triangle data??

    Anyway if you want to help I have attached my test zip project in the website link.

    Any help would be much appreciated. Let me know. Cheers Matt

  11. Matt says:

    Any chance you could post the example source ?

  12. Matt says:

    Hi Ben, not to worry I worked it out. The points need to be sorted by x :: one point I didn’t pick up on. Anyway great work !

  13. kanyal says:

    Hi, can you put whole source code here.

  14. jungbenj says:

    @Kanyal : Hi, I think I put already what you could need in the post. The flex demo interface is nothing really tricky. But let me know if you have some questions :)

  15.  
Leave a Reply