We've talked about using Image Processing Toolbox functions to define an affine transformation and apply it to points. Let's begin to explore transforming images.
First we have to answer a question that is often overlooked: Where is the input image? In other words, the input u-v space is a plane. Where does the image lie on the plane?
Contents
Image location in the plane
With the default spatial coordinates for images in MATLAB, the center of the upper-left image pixel is at (1, 1). Each pixel is a square with unit area, so the corner of the upper-left image pixel is at (0.5, 0.5). A 4-by-4 image looks like this on the plane:
pixel_centers_x = [1 4 4 1 1]; pixel_centers_y = [1 1 4 4 1]; pixel_edges_x = [0.5 4.5 4.5 0.5 0.5]; pixel_edges_y = [0.5 0.5 4.5 4.5 0.5]; plot(pixel_centers_x, pixel_centers_y); hold on plot(pixel_edges_x, pixel_edges_y, ':') % Plot axes lines c = [.7 .7 .7]; plot([-50 50], [0 0], 'color', c); plot([0 0], [-50 50], 'color', c); axis ij, axis equal axis([-5 5 -5 5]); legend({'Pixel centers', 'Pixel edges'}) title('Default image bounding rectangle location') xlabel('u') ylabel('v') hold off
Rotation
A "pure" affine rotation rotates about the origin. This means it can move an image into a completely different quadrant from where it started.
theta = 3*pi/4;
A1 = [ cos(theta) sin(theta) 0
-sin(theta) cos(theta) 0
0 0 1];
tform1 = maketform('affine', A1);
[pixel_centers_x1, pixel_centers_y1] = tformfwd(tform1, ...
pixel_centers_x, pixel_centers_y);
[pixel_edges_x1, pixel_edges_y1] = tformfwd(tform1, ...
pixel_edges_x, pixel_edges_y);
plot(pixel_centers_x1, pixel_centers_y1);
hold on
plot(pixel_edges_x1, pixel_edges_y1, ':')
% Plot axes lines
c = [.7 .7 .7];
plot([-50 50], [0 0], 'color', c);
plot([0 0], [-50 50], 'color', c);
axis ij, axis equal
axis([-5 5 -5 5]);
legend({'Pixel centers', 'Pixel edges'})
title('Rotated image')
xlabel('x')
ylabel('y')
hold off
Scaling
A "pure" affine scaling also operates with respect to the origin. Since the image corner isn't exactly at the origin (by default), scaling with a scale factor greater than 1 not only increases the size of the pixels, but it also moves the corner of the image away from the origin.
A2 = [ 3 0 0
0 3 0
0 0 1];
tform2 = maketform('affine', A2);
[pixel_centers_x2, pixel_centers_y2] = tformfwd(tform2, ...
pixel_centers_x, pixel_centers_y);
[pixel_edges_x2, pixel_edges_y2] = tformfwd(tform2, ...
pixel_edges_x, pixel_edges_y);
plot(pixel_centers_x2, pixel_centers_y2);
hold on
plot(pixel_edges_x2, pixel_edges_y2, ':')
% Plot axes lines
c = [.7 .7 .7];
plot([-50 50], [0 0], 'color', c);
plot([0 0], [-50 50], 'color', c);
axis ij, axis equal
axis([-5 5 -5 5]);
legend({'Pixel centers', 'Pixel edges'})
title('Scaled image')
xlabel('x')
ylabel('y')
hold off
The center of the upper-left pixel is now at (3, 3), and the corner of the upper-left pixel is now at (1.5, 1.5).
When I discuss imtransform, I'll explain how it automatically takes care of these details so that most users don't have to worry about it. But if you want to understand how things work, or if imtransform's automatic procedure doesn't do exactly what you need, then you need to understand this information.
Get
the MATLAB code
Published with MATLAB® 7.1



Steve,
Can you do this example with an actual image? I have been trying to manipulate an image to find its velocity and spin rate. I have found the forward velocity but spin rate is illusive. I want to rotate the image and do some comparisons, but I want to rotate about a point I choose. I tried imrotate, but there is no origin option. I tried your above method, but my image has pixel depth and my images are logicals, so they can’t be manipulated like vectors. Any suggestions are greatly appreciated.
Thanks,
Tadd
Tadd - see the doc for the IPT function imtransform. I’ll be talking more about imtransform in future posts.
Hi Steve,
Is it possible to place a 128×128 image at the center of a 512×512 space? My image has pixel depth. I wish to place the smaller image on the 512×512 space, with the rest of the space set to 0 on the gray scale (black). Do I use imagesc?
Many thanks,
Kelly
Kelly - Try this: B = zeros(512,512,class(A)); B(192:319, 192:319) = A;
Hi Steve,
I’m writing a gui that loads and manipulates images. I have an axes which is part of the figure. I’m loading images using the imread command, and I allow zooming with ‘zoom on/off’. My problem is that if the image I load is smaller then the axes, and I try to zoom in, the image is translated out, and I’m left with a blank (or nearly so) axes. Is there a way to ‘protect’ my image, and make sure it is always centered?
Thanks,
Alon.
Alon - I cannot reproduce the problem you describe. I suggest that you contact MathWorks technical support.
Hi Steve
I’m writing a gui for a program that allows users to choose images by clicking on them. The problem I’m having is that the callback for the axes on which the image is displayed doesn’t recognise a mouse click. How do I correct this?
Many thanks.
Steve.
Steve - Try setting the ButtonDownFcn of the image object instead of the axes object.
Hi Steve
Thank you. I did try ButtonDownFcn, as follows:
image(img, ‘ButtonDownFcn’, ‘myfcn’);
Works fine, but I have sixteen images. This doesn’t work:
image(img, ‘ButtonDownFcn’, ‘myfcn(”this image”)’);
function myfcn(str)
disp(str)
Neither does passing a variable. Tried various other things, including getting the current object. No luck. Can’t find any documentation on this. (Maybe a good tutorial? I can’t be the only person who has got totally stuck with this.) Anyway, I’m lost.
Thank you. Steve
Steve - Troubleshooting GUI code is a bit beyond this blog. I suggest that you contact support (http://www.mathworks.com/contact_TS.html). You could also post a note to the MATLAB newsgroup (http://www.mathworks.com/matlabcentral/newsreader.shtml) asking for tutorial material.
Hi Steve
I appreciate very much your effort in creating and updating this blog. The problem I have is the following: I’m trying to create a GUI to allow the user to segment images based on pixel intensity. Images are acquired with microscopes and typically they have noise and the objects to segment vary a lot in intensity. I tried smoothing out the background first, then substract it from the whole image. After that I appied a log filter to improve the quality of the image and to enhance the difference of intensities at the edges of the objects. After this, I tried the edge command to define the outline of the objects. The whole algorithm, however, is not perfect or close to it because the background substraction sometimes eliminates weak objects or weak parts of objects creating artifacts later on the edge detection. I then read a lot about other segmenting methods, and it seems that the seed region-growing algorithms could in principle provide a more general way to find objects. The complication is how to set up the constrains of the growing region. I would really appreciate feedback on this and about segmentation in general. Best, Ramiro
Ramiro - It’s difficult to offer specific advice without seeing sample images and code. Without knowing more about the problem, I wouldn’t necessarily jump straight to assuming you need to use region growing. There are different ways to do background estimation, and different noise-smoothing preprocessing techniques. I doubt that the edge command would be directly useful in a segmentation problem such as you describe. Have you tried marker-based watershed segmentation? The Image Processing Toolbox has a shipping demo that is an example of this technique. Also, Digital Image Processing Using MATLAB has more information on segmentation, including some stuff about region growing.
hi Steve,
Sorry for my late response. Tell me how to send images to you so you can see the difficulty I’m experiencing in segmeting them.
I wrote the code I used for the watershed segmentation:
clear all,warning off
[NAMEOFIMAGES, ORIGDATADIR, FILTERINDEX] = uigetfile(’*.tif’,'Tif Format (*.tif)’, ‘Select Clustered Image File’,'MultiSelect’,'off’);
cd(ORIGDATADIR)
i1 = imread(NAMEOFIMAGES);
bkg = imopen(i1,strel(’disk’,50,8));
i2 = imsubtract(i1,bkg);
minsignal=7;
i2 =i2 - minsignal;
D = bwdist(~i2);
D = -D;
D(~i2) = -Inf;
L = watershed(D);
[B,L] = bwboundaries(logical(L),’noholes’);
B=B(2:length(B));
figure,imshow(i1)
hold on
for k = 1:length(B)
boundary = B{k};
plot(boundary(:,2), boundary(:,1), ‘r’, ‘LineWidth’, 2)
end
hold off
Ramiro - e-mail works for sending me a sample image. If you send me one, please let me know whether or not I can show it publicly on this blog.
Hi Steve, I appreciate the availability of your blog. I am trying to develop an algorithm that measures the distance automatically between the max pixel value of grid points in my image. I have used pixval and imdistline which both work fine, but I have a tremendous amount of data so I would like to automate the process. Thanks for any help you can give.
Jonathan - can you give me a little more detail? In particular, what characterizes the points between which you want to measure the distance? Send me a sample image if you like.
Steve-I have gaussian fit the the points in the image I emailed to you. I am trying to measure the distance from peak to peak of each point. The points are arranged in a pseudo-lattice structure. Thanks.
Hi,Steve
I like your blog very much. Now I am trying to develop a matlab code to recognize the vortex breakdown positions in many images, but the result is not good. I just wonder, could you give me some indication on this problem? Thank you very mcuh!
Jiang - no, sorry.
I’m getting the following error while using the function linewrap.m
I’m not familiar with cellfun and all, so I wondered if you may have a quick solution to this
Thanks
Avner
??? Too many inputs.
Error in ==> linewrap at 60
c = cellfun(get_contents, tokens, ‘UniformOutput’, false);
Shimron - I wrote imcredit.m and linewrap.m using the R14sp3 release of MATLAB, which shipped in September 2005. linewrap uses a syntax of cellfun that wasn’t in earlier MATLAB releases.
Hi Steve,
Could you please let me know how I can save my files in the analyze format ?Is there any code that saves medical images in the analyze format?
Thanks.
Priya - we don’t have a function for writing to the analyze format, and we currently have no plans to create one.