Steve on Image Processing

Spatial transformations: Defining and applying custom transforms 20

Posted by Steve Eddins,

Blog reader David A. asked me a while back about how to transform an image based on some mathematical function. For example, the online paper "Visualizing complex analytic functions using domain coloring," by Hans Lundmark, has an example of defining a spatial transformation by assuming that the input and output spaces are complex planes, and that the inverse mapping is given by:

Check out Figure 3 in the paper to see what this does to an image.

You can use maketform to create a custom spatial transformation by supplying your own function handle to perform the inverse mapping. Your function handle has to take two input arguments. The first input argument is a P-by-ndims matrix of points, one per row. (imtransform applies two-dimensional spatial transformations, so I'll be using P-by-2 matrices here.) The second argument, called tdata, can be used to pass auxiliary information to your function handle. My examples will just ignore this second argument.

Let's start with a very simple example just to illustrate the mechanics. Make an inverse mapping that just swaps the horizontal and vertical coordinates:

% inverse mapping function
f = @(x, unused) fliplr(x);

% maketform arguments
ndims_in = 2;
ndims_out = 2;
forward_mapping = [];
inverse_mapping = f;
tdata = [];
tform = maketform('custom', ndims_in, ndims_out, ...
    forward_mapping, inverse_mapping, tdata);

body = imread('liftingbody.png');
body2 = imtransform(body, tform);

subplot(1,2,1)
imshow(body)
subplot(1,2,2)
imshow(body2)

As we might have guessed, this custom transform just transposes the image.

For my other examples I'll use a picture of someone I know well:

face = imread('http://blogs.mathworks.com/images/steve/74/face.jpg');
clf
imshow(face)

There is a fun little book called Beyond Photography: The Digital Darkroom, by Gerard Holzmann. This book has lots examples of spatial transformations based on simple mathematical expressions. Here's one that uses the square root of the polar radial component.

Note that the call to imtransform below sets up the input image to be located in the square from -1 to 1 in both directions. The output image grid is set up to be the same square.

r = @(x) sqrt(x(:,1).^2 + x(:,2).^2);
w = @(x) atan2(x(:,2), x(:,1));
f = @(x) [sqrt(r(x)) .* cos(w(x)), sqrt(r(x)) .* sin(w(x))];
g = @(x, unused) f(x);

tform2 = maketform('custom', 2, 2, [], g, []);
face2 = imtransform(face, tform2, 'UData', [-1 1], 'VData', [-1 1], ...
    'XData', [-1 1], 'YData', [-1 1]);
imshow(face2)

This example uses the square of polar radial component.

f = @(x) [r(x).^2 .* cos(w(x)), r(x).^2 .* sin(w(x))];
g = @(x, unused) f(x);

tform3 = maketform('custom', 2, 2, [], g, []);
face3 = imtransform(face, tform3, 'UData', [-1 1], 'VData', [-1 1], ...
    'XData', [-1 1], 'YData', [-1 1]);
imshow(face3)

Finally, let's try the complex-plane function used in Lundmark's article. I'll construct the inverse mapping function in several steps: First, convert output-space Cartesian coordinates to complex values; square the complex values; and then produce new input-space Cartesian coordinates from the squared complex values.

f = @(x) complex(x(:,1), x(:,2));
g = @(z) z.^2;
h = @(w) [real(w), imag(w)];
q = @(x, unused) h(g(f(x)));

tform4 = maketform('custom', 2, 2, [], q, []);
face4 = imtransform(face, tform4, 'UData', [-1 1], 'VData', [-1 1], ...
    'XData', [-1 1], 'YData', [-1 1]);
imshow(face4)

If you want see to more examples of this kind of mathematical image fun, take a look at "Exploring a Conformal Mapping" in the Image Processing Toolbox product demos area.


Get the MATLAB code

Published with MATLAB® 7.2

20 CommentsOldest to Newest

Matthew – Well, wizarding powers aside, I’m really more of an engineer than a scientist. So far, no ill effects are apparent.

These are most helpful in implementing in MATLAB the algorithms specified in “Beyond Photography”. Probably due to my beginner status in using the Image Processing Toolbox, I was unable to get the the transformation where
r -> r but
theta -> theta + r/3
This is on page 44 in “Beyond Photography”.

Tim—You could try something like this:

r = @(x) hypot(x(:,1), x(:,2))
theta = @(x) atan2(x(:,2), x(:,1))
f = @(x) [r(x) .* cos(theta(x) + r(x)/3), ...
    r(x) .* sin(theta(x) + r(x)/3)];
g = @(x, unused) f(x);

and then form a custom tform as shown in this post.

Hello Steve,

I am working on a project where I need to simulate non-linear deformations in the images. Since these are MR images, the deformations can’t be as severe as the examples given above. Currently, I am using the following code to create the deformations.

a = 0.95; b = 1.05;
Tform_values = a + ((b-a) * rand(1,30));
for i = 1:30
f = @(x) ((x(:,:).^Tform_values(i)));
g = @(x, unused) f(x);
tform3 = maketform(‘custom’, 2, 2, [], g, []);
img_stack_Tformed(:,:,i) = imtransform(img_stack_org(:,:,i),tform3,’size’,size(img_stack_org(:,:,i)));
end

What I am not able to understand is how it the spatial transformation created using the function f given below. I am not sure whether the created transform is non-linear. Any information regarding this will be really helpful.

Thanks,

Shiva

Shiva—If you look at the various blogs posts in the spatial transforms category, you’ll find some descriptions of how they work. The Image Processing Toolbox functions imtransform and maketform use inverse mapping, which is described in the posts.

Whether it is linear depends on whether you are talking about the warping function, or the process of warping an image. Image warping is linear, meaning that warping the image (aF + bG) is the same as a*warp_of_F + b*warp_of_G.

Dear Steve,
thx for your answer. I can use the imtransform now. However, I have no idea on how to extract the data point from the deformation grid. Could you help?

Douglas—I don’t know what you mean by “extract the data point from the deformation grid.” Can you be more specific?

Hi Steve,

Im working on a facial aging project. I just commented about the same on another post of yours. I realize that this post shows some of those geometrical changes that Im looking out for. so could you please help me out n it. If you check out the before/after photos in the paper (link below) u’ll get an idea of what i want….i wanted to avoid using RBF etc..I had to complete this in 3-4 days..Its extremely urgent. Please help!

heres the link to the paper im trying to implement

http://www.dca.fee.unicamp.br/~leopini/private/pubs/Greyce-2007WesternNYImageProcessingWorksop.pdf

RZ—Sure. Rotation and translation are both affine transformations, and the composition of two affine transformations is also affine. So take a T1 matrix that’s a rotation matrix, a T2 matrix that’s a translation matrix, and multiply them.

hello
i am doing image registration, but when I applied an affine transformation on image, and after applied an inverse transformation the transformed image not returne to original image

Hi Steve,
I’m confused about using custom transform 3D to 2D. I’m trying to extract an arbitrary single slice from being transformed 3D MR data with 3D-2D tranformation. I have 8 transformation parameters for 3D MR = 3-rotation,3-translation and 2-scale(X,Y). In order to reduce transformation time, I decided to use custom and composite (affine+custom) transform as :

TT1 = maketform(‘affine’, T); % T is 4×4 matrix
inverseFcn = @(X,t) [X repmat(t.tdata,[size(X,1) 1])];
TT2 = maketform(‘custom’,3,2,[],inverseFcn,30);
Tc = maketform(‘composite’,TT1,TT2);
R = makeresampler ({‘cubic’,'nearest’,'nearest’}, ‘fill’);
TDIMS_A = [1 2 3];
TDIMS_B = [1 2];
TSIZE_B = [round(size(Vol,1)*scx) round(size(Vol,2)*scy)];
TMAP_B = [];
F = 0;
imT = tformarray(Vol, Tc, R, TDIMS_A, TDIMS_B, TSIZE_B, TMAP_B, F);

I get an error :

Error using ==> maketform>composite at 540
Input TFORM objects have inconsistent dimensions.”

finally, I would be thankful if you could share some suggestions to overcome this inconsistency…

Daer Steve,
I also have a question for you which is somehow related to the topic of this post:
I am trying to implement the global axial bending tranformation for a 3D image along the Y axis. The transformation looks like the following:
X=x;
Y=-sin(theta)*(z-1/k);
Z=cos(theta)*(z-1/k);

where theta=k*y (thata changes with y). Besically I would like to applay the transformation

[0, -sin(theta),0; 0 cos(theta),0; sin(theta)/k), -cos(theta)/k), 1]

to each plane (y,z) of the 3-dimensional image. However, I eperienced that this cannot be done with

makatform(‘afine’

but a

‘custom’

transformaation should be defined. Do you have any idea on how to do it?

Mary—This post was about defining and applying custom tforms. What information is missing for you?

These postings are the author's and don't necessarily represent the opinions of MathWorks.