Bilinear transformation coordinates

for simulating perspective image transformations with ImageMagick 

ImageMagick is an extremely powerful and flexible set of image manipulation utilities. I am not about to expound on everything it can do; this is about a particular request for calculating distortion parameters.

The library Leptonica is another set of powerful image processing tools, including some that ImageMagick didn't describe. Among them are several kinds of image transformations.

An affine transformation is one that preserves parallel lines. Translation, rotation, scaling and shearing are the component types of affine transformations. ImageMagick, as well as the PDF format, handle affine transformations very easily. But not everything is an affine transformation.

A perspective transformation is one that maps one arbitrary quadrilateral onto another. For example, if you look at a building face-on, the facade appears to be a rectangle; but if you are not directly in front of it but angled to one side, then it appears to be a trapezoid. Perspective transformations are not affine, and worse, they are relatively expensive to compute. But there's a fairly good alternative...

A bilinear transformation is another 4-point mapping like the perspective mapping. Technically, according to what I've been told, it maps one arbitrary circle onto another arbitrary circle, but I don't really understand how. This is a little hard to picture, but the point is that when the distortion is not very large, a bilinear transformation looks a lot like a perspective transformation -- and it's easier to compute, because there is no division involved.

A bilinear transformation is defined by these two equations:

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

There are eight constants here, parameters that must be supplied to the transformation. They can be computed when given the eight points of the two quadrilaterals, using some matrix math.

The Leptonica library has all that math defined and coded.

The Leptonica library, unfortunately, is very complex and I had trouble compiling it. So I ripped out what I needed, put it into one file, wrote a simple routine that reads the points from stdin and outputs the coordinates to stdout, and compiled it. The resulting package is here.

Sample input and output from the tool:

C:> type testdat
source1=1,1
source2=1,11
source3=11,1
source4=11,11
dest1=1,1
dest2=1,11
dest3=11,3
dest4=11,8

C:> blnrtool.exe <testdat
source0=1.000000,1.000000
source1=1.000000,11.000000
source2=11.000000,1.000000
source3=11.000000,11.000000
dest0=1.000000,1.000000
dest1=1.000000,11.000000
dest2=11.000000,3.000000
dest3=11.000000,8.000000
Output coefficients:
a=1.000000 b=0.000000 c=-0.000000 d=-0.000000
e=0.250000 f=1.050000 g=-0.050000 h=-0.250000

C:>