Steve on Image Processing

Spatial transformations: Controlling the input and output grids with imtransform 45

Posted by Steve Eddins,

The function imtransform has several optional parameters that allow you to fine-tune its behavior. Today's topic is about the parameters that let you control where the input image lives in input space, as well as the location and spacing of the output space pixel grid.

Contents

Input image location

imtransform assumes that an M-by-N input image lives in input space inside a rectangle spanning from 0.5 to M+0.5 horizontally, and from 0.5 to N+0.5 vertically.

I = checkerboard(1,4);
imshow(I, 'initialmag', 'fit')
axis on
box on
set(gca, 'XTick', [1 8], 'YTick', [1 8])
xlabel('u axis')
ylabel('v axis')
title('8-by-8 image')

What if you want the input image to be in some other location? Sometimes, for example, it's convenient to place the center of the image at the input-space origin.

% imshow doesn't know about u-v space, just x-y space, so its parameters
% are called XData and YData.
imshow(I, 'XData', [-3.5 3.5], 'YData', [-3.5 3.5], 'initialmag', 'fit')
axis on
box on
set(gca, 'XTick', [-3.5 0 3.5], 'YTick', [-3.5 0 3.5])
xlabel('u axis')
ylabel('v axis')

You can place imtransform's input image where you want in u-v space by specifying the UData and VData parameters. UData is a two-element vector. Its first value is the u-coordinate of the first column of the input image. Its second value is the u-coordinate of the last column. Similarly, VData is a two-element vector containing the v-coordinates of the first and last rows of the input image.

To place the center of an M-by-N image at the origin, specify UData to be [1 N] - (N+1)/2 and VData to be [1 M] - (M+1)/2.

Output space pixel grid

imtransform determines the bounding rectangle of the transformed image in output space and then overlays a pixel grid on that rectangle. The pixels in the output grid have the same size as the input image pixels.

You can modify the grid location and pixel size by specifying the XData, YData, and Size parameters in the call to imtransform.

XData and YData are similar to UData and VData. XData is a two-element vector containing the x-coordinates of the first and last columns of the output image. YData is a two-element vector containing the y-coordinates of the first and last rows of the output image.

The Size parameter is a two-element vector specifying how many rows and columns are in the output space grid.

Example

Here's your task: Position an input image centered at the origin and extending from -1 to 1 in the horizontal and vertical directions. Apply a 45 degree rotation to it. Compute the output image only inside a square extending from -0.8 to 0.8 horizontally and vertically. Also, compute the output image using only one-eighth as many pixels (in each direction) as the image input.

I = imread('pout.tif');
imshow(I)
T = [1 -sin(pi/4) 0; sin(pi/4) 1 0; 0 0 1];
tform = maketform('affine', T);

udata = [-1 1];
vdata = [-1 1];

xdata = [-0.8 0.8];
ydata = [-0.8 0.8];
output_size = round(size(I)/8);

J = imtransform(I, tform, 'UData', udata, 'VData', vdata, ...
    'XData', xdata, 'YData', ydata, 'Size', output_size);

imshow(J)

In an upcoming post I'm going to demonstrate how to define and apply custom spatial transformations. This post will include more examples illustrating the use of UData, VData, XData, and YData.


Get the MATLAB code

Published with MATLAB® 7.2

45 CommentsOldest to Newest

Where are the new posts??

I am trying to register images. I need to translate, rotate, scale, and accomidate for shear. I have tried many options. I can perform rotation and scaling fine. When I use translation, the offset is not working. I place the images ontop of each other. No translation occured. I read the July 2006 post. Please help!

mike

Michael—I don’t know what you mean by “new posts.” The main URL for this blog is http://blogs.mathworks.com/steve. The July 7 2006 post explains how to specify input and output coordinate systems so that you can control how the translation occurs. I can’t give you more help unless are much more specific. Have you tried the code in that post? Does it work as you expect?

Dear Steve:
I have the following question and hope that you may shed some light on it. Thanks in advance.
I am working on image normalization which involves creating a “compact” image. Such a process involves three steps: 1) translate the coordinate to the image centroid, 2) rotate the coordinate so that it aligns with the eigen vectors, and 3) scale the image along the coordinate such that the final size of the image is fixed.
After the above steps, the following two transformation matrices are created: T1 and T2 for the original image (n-by-n, taking “lena” as an example, n=256) and the image which is half the size of the original (n/2-by-n/2). It is obvious that the values of entries in M2 are twice of those in M1 except for the translation vector. As how to create M1 and M2, I can provide the program if it is necessary.

M1 = [ 0.8083    0.7308         0
      -0.7713    0.7658         0
      -11.4281 -193.1479    1.0000];

M2 = [ 1.6226    1.4663         0
      -1.5476    1.5374         0
      -11.5220 -194.5561    1.0000];

And then, I performed the following image transformation:

tform1 = maketform('affine', M1);
[norm1 xdata1 ydata1] = imtransform(im1, tform1, 'bilinear');
figure, imshow(xdata1, ydata1, uint8(norm1));
pixval on, axis on, axis([xdata1 ydata1]);

tform2 = maketform('affine', M2);
[norm2 xdata2 ydata2] = imtransform(im2, tform2, 'bilinear');
figure, imshow(xdata2, ydata2, uint8(norm2));
pixval on, axis on, axis([xdata2 ydata2]);

The result is: norm1 and norm2 are of different size, however, [xdata1 ydata1] and [xdata2 ydata2] are approximately the same (with less than one pixel of difference). Why is that?

Yuan-Liang—If you do not specify the desired output grid directly, then imtransform automatically computes it so that it contains the entire transformed image. This computation of the desired output bounding box is a floating-point computation, so there can be round-off effects. This can result in the output grid having an additional pixel compared to what you expect.

Thanks alot for the blogs, they have helped lot in the past. I have a question regarding imtransform. I have aligned two images using homography and imtransfom. Obviously after applying imtransform, the part where no image data exists shows up as black(default). The problem is that I am cut and pasting patches from one image onto the other, and I don’t want patches which partly cover the “no-image” black region, to be selected. Is there any way to determine the exact “image” region after imtransform. One not-so-elegant way I thought of, was to calculate the position of the four corners of the original image in the new transformed image and draw straight lines between them, to define the image boundary. Can you give me any better suggestions please?

I am trying to register 3D images and i would like to truncate the transformed images to the original size. I’ve seen the example that there exists in the case of 2D images, where this is accomplished by using XData and YData. In the case of 3D images how can wwe achieve the same result?Moreover, do you think that it would be better to change the input-space origin to the center of the image?Thanks very much.

Aris

Aris—The multidimensional spatial transformation function in the Image Processing Toolbox is tformarray. This is a very general-purpose function with no “convenience” syntaxes, so it takes some study to learn to use. This function operates purely on array index coordinates. That means you will need to incorporate any unit scaling (like XData and YData) and input-space origin translation into the transformation itself. You can do you by composing an affine transform containing the necessary scale and translation factors. I don’t have an opinion about whether it is “better” to change the input-space origin; I would do it if it makes the math and/or code easier to understand.

Hello steve,
I want to recover the original image from transformed/rotated image without usig ‘cpselect’. Is it possible? if so please explain me.
Thank you

santhosh R.R.

Santhosh—Can you be more specific? What information do you have about the image from which you think you can determine the rotation angle?

Hi
I have just performed a simple projective transform on an image. I was expecting the output result to be a single transformed image in the new coordinate system. However to see the transformed image I have to imshow using xdata and ydata. I was wondering if there was a way to produce a single resultant image in the NEW coordinate system.
Thanks
Joe

Hi Steve,

Great blog! I am trying to find a function to zoom an image and I dont know if something like that exists. It seems to me like should be already implemented.

What I want to do is to change the scale of the image (make it bigger, the opposite to subsampling) but using the same of the image. I guess this is called zooming but maybe it is not the case and that’s why I can not find such thing?!

Can you help me with this?

Thanks a lot!

Joe—I do not understand your question. The output of imtransform is a single image in the new coordinate system. Can you clarify?

Hi Steve, thanks for your reply. I dont want to resize the image, the dimensions (rows and cols) of the image should stay the same but the scale of the pixels should change. Something like if you average the values of the pixels in different areas of the images.

Hopefully that was more clear.

Edgar—Use the XData and YData properties of the Handle Graphics image object to change the spatial scale of the pixel values.

thanks steve, I tried that and it worked:

im = imread(’111.jpg’);
[x y] = size(im);
image(im,’XData’,[1 y/2],’YData’,[1 x/2]);
axis image;
image(im,’XData’,[1 y*2],’YData’,[1 x*2]);

but that doesn’t change the actual values in the CData matrix. Is there a function to do something similar but that changes the values?

Edgar—I’m afraid I don’t understand what you are after. You don’t want to resize the image, but you do want to the change the pixel values? That doesn’t make sense to me. Can you find a different to describe the operation you have in mind more precisely?

I hope it’s ok to join in briefly….
Edgar, if you want to keep the matrix dimensions the same but to contain a limited part of the original image (now bigger), I think it would depend upon how accurate you need to be, and also whether you know the scale of the enlargement or the region of the image you want to enlarge.

For example, if you know the scale you want, you could use imresize and then crop out the bits you don’t need, e.g.

im2 = imresize(im, 2.5);
s = size(im);
rect = [100 100 s(2) s(1)];
im = imcrop(im2, rect);

Or if you know rows and columns you want, you can more easily create a smaller matrix containing only those rows and columns and then enlarge it to the desired size using imresize, e.g.

im2 = im(100:200, 100:200);
im = imresize(im2, size(im));

I hope that’s right. Though perhaps you’re right and there is a better way?
Anyway, I’ll back out again now, in case I’ve also misunderstood…

Hi Pete,

thanks for your help. Yes, that is closer to the thing I wanted to do. :)

I guess I should have mentioned this before, I am running an experiment over a database of images with fixed sizes and I wanted to run the same experiment with subsampled (zoomed) images from the database so I needed them with the same sizes. So that is why I mentioned I wanted to keep the same size of the images but the values of the pixels should change (not only its visualization).

Sorry Steve if was not clear enough, thanks for your help and replies.

Cheers!

dear steve, i am kinda new in image processing and currently i am doing car plate recognition for my final year project.as a start i need to crop the image to ease my task in the future. the problem is i dont really understand about the image cropping and how to get the x and y coordinate of the image. please, discuss about this matter in your blog to give a good understanding how to start processing the image and basic understanding about the image. please steve,..it will help me alot..
thank you

dheena

Dheena—If you use two output arguments with the imcrop function, the second output will give you the crop rectangle.

Hi Steve, I am using Matlab as a programming tool in image processing. My question is, is there any posibility to get the transformation parameters (traslations, rotations,etc) when using the imtransform function?, for example when using an affine transformation?. I would really appreciate your answer.

Luciano—I’m not sure I understand your question. You have to supply your transform parameters in some form in order to use imtransform, so why do you need imtransform to give them back to you?

Dear Steve, I am trying to perform image registration using a feature extraction algorithm in order to get the characteristics vectors for the cp2tform function, which will give me back the tform structure. I would like to know if there is any chance to know what were the traslation in pixels and rotation between the images i am trying to align. When i use cp2tform and imtransform together the transformation seems to work well, the images are aligned (by visual inspection), but i really don´t know how many pixels or angles the base image was translated o rotated (I don´t know the transformation matrix). I’m sorry if i was not clear enough. Thanks!

Luciano—You can get the transformation matrix from the .tdata field of the tform struct returned by cp2tform.

Hi, Steve,
I asked a similar question before (Jun. 22, 2007) and thank you for your response. However, the problem is still bothering me. Again, taking the following codes as an example, image im2 is half the size of im1 and transformation matrix mat2 is 2 times mat1 (except for the last row). After transformation, theoretically both transformed images should have approx. the same size, which is not the case shown in the experimental results. My question is:
1. For the spatial sizes, both are similar (reasonable)
2. For pixel sizes, they are very different. Why? It doesn’t look like the round-off effects.
Thanks for your help.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
im1 = imread(‘lena.tif’); % size: 256*256
im2 = imresize(im1, 0.5, ‘bilinear’); % size: 128*128

mat1 = [
-0.5236 -0.6439 0
-0.6505 0.5275 0
151.0877 19.9745 1.0000];
mat2 = mat1;
mat2(1:2,1:2) = mat2(1:2,1:2)*2; % 2 times mat1 except for the last row

tform1 = maketform(‘affine’, mat1);
[imt1 xdata1 ydata1] = imtransform(im1, tform1, ‘bilinear’);
figure, imshow(imt1, []);
xdata1 % Result: [-149.4819 150.5181]
ydata1 % Result: [-144.3364 154.6636]
size(imt1) % Result: 300*301

tform2 = maketform(‘affine’, mat2);
[imt2 xdata2 ydata2] = imtransform(im2, tform2, ‘bilinear’);
figure, imshow(imt2, []);
xdata2 % Result: [-149.4819 149.2159] –> close to xdata1
ydata2 % Result: [-143.8089 153.7267] –> close to ydata1
size(imt2) % Result: 257*258 –> Very different from imt1

Yuan-Lian—I didn’t remember this, but there’s code in imtransform that modifies the width and height of the output pixels to cut down on the output image size, unless you specify the XYScale parameter explicitly. I see that our documentation is incorrect on this point, since it currently says that the scale of the input pixels is used for XYScale. You can get the result you expect by passing in …, ‘XYScale’, 1, … in your input argument list, and I’ll request that the doc be corrected.

Dear Steve,
if we already have a 3×3 homography transformation matrix and we want to transform an image using this matrix,can you tell me which function to use that takes this homography matrix and applies it to a specific image??
thanks in advance

Thanks steve, but we tried this and the result was a Black image and the image became so small
this is our code
Homog =

-0.5909 -0.0619 126.8663
0.0030 -0.5817 13.3776
-0.0003 -0.0000 -0.5001

t_proj = maketform(‘projective’,Homog);
I_projective = imtransform(I,t_proj,’FillValues’,.3);
subplot(334);
imshow(I_projective);
title(‘projective’);

Sara—You shuold take a close look at your transformation. Using tformfwd, I can see that your transformation maps the point (1,1) to (-0.004209131281674, -0.004605571052168), and it maps the point (256,256) to (-0.004192049430379, -0.004589211830939). Given that, it’s not too surprising that your output image is very small!

Hello!
I am trying to find the algorithm inside imtrasform! I need an algorithm which rotates a colour image around its center with any angle, but without using predefined matlab functions(imtransform).Can you help me, please?..thanks

Adrian—Basically, imtransform uses inverse mapping to find the input-space location corresponding to each output-space pixel, and then uses interpolation in input space. My spatial transforms series includes some algorithm information.

Hi, Steve!

I have such quastion: how to recover scale, rotation, shear from projective t-matrix? For example:
0.1038 -0.1363 -0.0007
0.0270 0.6553 0.0001
292.3112 70.3536 1.0000

Thank you
Vitaliy

Vitaliy—I’m not familiar with techniques for doing that. I did come across an article that might be helpful to you: “Decomposing a Matrix into Simple Transformation,” by Spencer W. Thomas, in Graphics Gems II, edited by James Arvo, Morgan Kaufman, 1991.

hi,i want 2 ask somthing about homography.i want to calculate homography matrix H,the equation is x’=Hx.
x’ is 3xN set of homogeneous points,now i am not getting the point that how to calculate this 3xN set of homogeneous points.
please give me some idea.i hope you ill rep.

Hi Steve

I have a doubt related to imtransform. I know the co-odinates of four points in input and output image. I use cp2tform to get projective transformation matrix and use imtransform to generate the perspective distorted image. Now when i use  imtransform with inverse of the transformation matrix on the output image , I do not get the original image. Why should that happen. I am clueless. Please advise.
Thanks 

Steve,
I am for the first time, trying to do spatial transofrmation on 2 MRI scan 3D images saved in NII file format. I have tried several freely available softwares to do this but at the end when I add the two images, I don’t see them being aligned. I am trying to use MATLAB for same, can you help me get started. What functions will help me achieve this successfully. thanks in advance.

Hi Steve,
I have read all your spatial transformation blogs and they have helped me a lot in my image analysis problems. But, I have a doubt when you have to rotate an image around its center. In your blog you said that, we can translate, rotate and then translate back. Say, I have a matrix of size 100 by 100 and I want to rotate this around its center. So, the first translation has to be this:
Translation_1 = [1 0 0; 0 1 0; -50.5 -50.5 1];
Now, I do the rotation with a certain angle:
Rotation = [cos(theta) -sin(theta) 0; sin(theta) cos(theta) 0; 0 0 1];
After this rotation, the size of the image will change. Which means that I cannot translate back with the negative of the translation offsets of Translation_1. Is this right?
Because in your blog you have said that we can translate back with the negative of the translation offsets.
It would be great if you can tell me how this goes.

Thanks a lot.

Hi Steve,
This is in continuation of my previous comment (comment # 42)
I am doing some intensity correlations in several images and I always have the value 1 at the center of the matrix I (size 100 by 100). So I had to rotate about the center so that 50,50 will always be 1. I tried using tformarray and I had the above mentioned problem. I still do not know why it gives me this problem.
But thankfully, I went through all your blogs and I saw that XData and YData has to be manipulated to get the output matrix in the same size.
Now I tried imtransform by specifying XData and YData to be as the same size of the input matrix and the rotation works fine.

It would be great if you can tell me why tformarray does not work for my purpose.
Thanks for all your wonderful blogs.

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