pixmorph — morph two pix(5) images


pixmorph [-w width] [-n height] picA.pix picB.pix linesfile warpfrac dissolvefrac > out.pix


pixmorph performs feature-based image metamorphosis between "picA.pix" and "picB.pix". The feature correspondences are specified in the file "linesfile", which can be created using a utility such as morphedit.tcl (see morphedit(1)).

The output image is computed in the following fashion. First, for each pixel in the output image, we choose a set A of pixels (and associated weights) from "picA.pix" and another set B of pixels from "picB.pix" (how these sets and weights are chosen will be described momentarily). The pixel values from A are then averaged (using the associated weights) to determine the contribution cA from the original image; the contribution cB is computed similarly. Then, the values cA and cB are interpolated by the value dissolvefrac to compute the final value of the output pixel.

Now, the contribution cA from the original image is intended to be the value from picA.pix that gets "warped to" the location in question. It is this computation (more specifically, the computation of A and associated weights) that is the heart of the morphing algorithm, and is described briefly here.

First, the linesfile is processed. The linesfile is of the form a b p n lineseg1_initial lineseg1_final lineseg2_initial lineseg2_final linesegn_initial linesegn_final , where n equals the number of line segments, and a, b, and p are constants that alter the nature of the morph. A line segment is represented as a list of four real numbers (and is interpreted as a directed line segment). For example, 0.1 2.0 0.2 2 0.714844 0.560547 0.988281 0.277344 0.347656 0.646484 0.654297 0.896484 0.341797 0.611328 0.757812 0.265625 0.628906 0.519531 0.925781 0.763672 is a valid lines file. Typically, the pairs linesegi_initial linesegi_final have been placed by the user in the lines file to match up particular features of picA.pix and picB.pix (the feature at linesegi_initial in picA.pix corresponds to the feature at linesegi_final in picB.pix). For instance, lineseg1_initial might be a line segment running down the length of the nose of a person displayed in picA.pix; then lineseg1_final would be a line segment running down the length of the nose of the person featured in picB.pix. See morphedit(1) for more information about creating a lines file.

Now, for each line segment pair (s,t), we perform the following procedure: We interpolate between s and t by factor warpfrac to yield the interpolated line segment s'. From the change in position, scale, and orientation of a line segment from its initial position s to its interpolated counterpart s' we may deduce a linear transformation in the image space. More specifically, if the line segment s must undergo translation, stretching, and rotation to yield s', we compute a linear transformation T of the image space that performs the same translation, stretching, and rotation. (So T applied to s yields s'.) The inverse T* of this transformation maps s' to s; for instance, T* will take an endpoint of s' to the corresponding endpoint of s, and will preserve the relationship of every other point to the line segment. We apply this inverse T* to the coordinates (x,y) to find an appropriate pixel in the original image. Along with this, we compute a weight based on the length of the line segment s along with its distance from (x,y). This weight is equal to ( (length ** p) / (a + dist) ) ** b (where ** denotes exponentiation, length is the length of s, dist is the distance from s to (x,y), and a, b, p are constants chosen by the user and stored in the lines file).

The set A of pixels is then collected by performing these computations for each line segment, and the resulting contribution cA is then computed by averaging over A with the appropriate weights.

In practice, a = 0.1, b = 2.0, and p = 0.2 seems to work well.

In general, the user will wish to set warpfrac = dissolvefrac. Typically, a morph animation will be produced by computing a sequence of images using pixmorph, each with slightly greater warpfrac (and dissolvefrac) (see the example). For a clearer and more thorough explanation, see T. Beier and S. Neely, Feature-Based Image Metamorphosis, "SIGGRAPH 1992 Computer Graphics Proceedings (volume 26 number 2)", (Chicago, July 26-31, 1992), pp 35-42, which presents the algorithm used by pixmorph.



Tells pixmorph that the input images have width WIDTH.


Tells pixmorph that the input images have height HEIGHT.


pixmorph face1.pix face2.pix lf 0.0 0.0 > frame0.pix

pixmorph face1.pix face2.pix lf 0.2 0.2 > frame1.pix

pixmorph face1.pix face2.pix lf 0.4 0.4 > frame2.pix

pixmorph face1.pix face2.pix lf 0.6 0.6 > frame3.pix

pixmorph face1.pix face2.pix lf 0.8 0.8 > frame4.pix

pixmorph face1.pix face2.pix lf 1.0 1.0 > frame5.pix

Note that the example above will result in frame0.pix = face1.pix and frame5.pix = face2.pix.

pixmorph face1.pix face2.pix lf 0.5 0.0 > out.pix

Note that in this example, dissolvefrac = 0. This will warp face1.pix and face2.pix by the appropriate amount, but will ignore the contributions of face2.pix at the cross-dissolve stage. So the final image out.pix will consist entirely of values from face1.pix warped 50% according to the linesfile lf.

pixmorph face1.pix face2.pix lf 0.0 0.5 > out.pix

In this example, warpfrac = 0. This will perform a simple 50% cross-dissolve between face1.pix and face2.pix.


brlcad(1), morphedit(1), pix(5)




This software is Copyright (c) 1996-2016 by the United States Government as represented by U.S. Army Research Laboratory.


Reports of bugs or problems should be submitted via electronic mail to <>.