PIL Image transform

Ben C spamspam at spam.eggs
Fri Aug 11 19:43:57 EDT 2006


On 2006-08-11, Dean Card <mailer at forums.com> wrote:
>> This looks like a correct description of the sources:
>>
>> In Image.py:
>>
>> elif method == PERSPECTIVE:
>>    # change argument order to match implementation
>>    data = (data[2], data[0], data[1],
>>            data[5], data[3],
>>            data[4],
>>            data[6],
>>            data[7])
>>
>> and then in Geometry.c:
>>
>> static int
>> perspective_transform(double* xin, double* yin, int x, int y, void*
>>        data)
>> {
>>    double* a = (double*) data;
>>    double a0 = a[0]; double a1 = a[1]; double a2 = a[2];
>>    double a3 = a[3]; double a4 = a[4]; double a5 = a[5];
>>    double a6 = a[6]; double a7 = a[7];
>>
>>    xin[0] = (a0 + a1*x + a2*y) / (a6*x + a7*y + 1);
>>    yin[0] = (a3 + a4*x + a5*y) / (a6*x + a7*y + 1);
>>
>>    return 1;
>> }
>>
>> Something like this is almost what you what:
>>
>> im = im.transform(im.size, Image.PERSPECTIVE, (1, 0, 0, 0, 1, 0, -0.004, 
>> 0))
>>
>> But the problem really is that the top row of the image is at at y of
>> 0-- I think you want the origin of the image to be in the centre for
>> this to work properly.
>>
>> Is there a way to do that in PIL?
>
>
> thanks for the reply.  I have been able to use the Image.PERSPECTIVE 
> transform via trial and error to get it to work properly for each transform. 
> What I am really looking for I guess is a way to calculate the 8 int tuple 
> to match the perspective change I am going for.  For a given image there may 
> be 5 elements that need to be 'painted' on with perspective.  A database 
> table will include the transform tuples based on the source image.  So, by 
> passing a starting image and a pattern image, the starting image can be 
> covered with.  Perhaps the best way to explain is visually....
>
> http://seanberry.com/perspective.png
>
> What I need to know is how you take a surface like (P1, P5, P6, P2) and 
> describe it with the 8 int tuple?

I think you want to work out normalized normals for each face of your
cube, in 3D. This part is easy (or at least well-known) for any given
set of Euler angles (rotation about each axis) or for an angle about an
arbitrary axis.

A normal can be visualized as a perpendicular spike sticking out of the
centre of each face (for the sake of simplicity assume the centre of the
cube is at the origin).

A normal is "normalized" if dot(n, n) == 1.

So, anyway, for a given face, you work out a normal with 3 components,
n[0], n[1] and n[2].

Then I think it's likely that each of (a, b), (d, e) and (g, h) should
be set to different combinations of two out of the three (maybe with
some minus signs in here and there).

Something like this:

(a, b)  <=  (n[2], n[1])
(d, e)  <=  (n[0], n[2])
(g, h)  <=  (n[0], n[1])

Leaving c and f as zero.

If I get the time I'll try and work it out properly and explain it.



More information about the Python-list mailing list