I have a set of points [x,y]=meshgrid(1:N,1:M)
defined on a regular 2D, N x M
grid. I have another set of points [u,v]
that are some deformation of the original grid, i.e [u,v]=f(x,y)'
(however I do not have the actual f
that caused the deformation). How can I map a texture to the "deformed" grid defined by u,v
? i.e., given an image with aspect-ratio N/M
how can I map it to the deformed grid?

- 23,991
- 34
- 108
- 149
-
1Can you clarify "map a texture"? – Fabian Tamp Apr 30 '13 at 00:35
-
what is the size of `u` and `v`? do you have explicit expression for the "deformation" relating `u` and `v` to `x` and `y`? What is the texture you are trying to map? Is it a function? A matrix? what size is it? A bounty will not help you get a good answer if your question is too vague to begin with... – Shai Apr 30 '13 at 05:20
-
I added some more explanation, hope it's clear enough... – olamundo Apr 30 '13 at 07:06
-
very interesting question. I think what I understood is that you want to plot a set of deformed points and an image on it? As if you would plot an esphere and try to plot it with the world map on it? you'll need to set each element image portion before the deformation and change each of the portions to plot them in a deformed surface. Is it that what you want? If it is that, change your question and add some images,... so people gets interested (people love colours and images!) because i think it is a highly interesting question. Teal time seems difficult thou... – Ander Biguri Apr 30 '13 at 07:34
4 Answers
I think you are asking to get samples of the original texture at [u,v]
. You can use interp2.
Let's say that the texture samples are in z
and you want new samples z2
. To interpolate the original texture at [u,v]
, use:
z2 = interp2(x,y,z,u,v);
On the other hand, if you want to map the "deformed" texture back to a regularly spaced grid [x2,y2]
, use griddata:
[x2,y2] = meshgrid(1:N2,1:M2);
z2 = griddata(u,v,z,x2,y2);
Update:
Here's some example code showing how to do this with real data. Using normalized coordinates makes it easier.
% get texture data
load penny
z = P;
% define original grid based on image size
[m,n] = size(z);
[a,b] = meshgrid(linspace(0,1,n), linspace(0,1,m));
% define new, differently sized grid
m2 = 256;
n2 = 256;
[x,y] = meshgrid(linspace(0,1,n2), linspace(0,1,m2));
% define deformed grid
u = sqrt(x);
v = y.^2;
% sample the texture on the deformed grid
z2 = interp2(a,b,z,u,v);
% plot original and deformed texture
figure
subplot(2,1,1)
surface(a,b,z,'EdgeColor','none')
axis ij image off
colormap gray
title('original')
subplot(2,1,2)
surface(x,y,z2,'EdgeColor','none')
axis ij image off
colormap gray
title('deformed')
And this is the result:

- 10,648
- 2
- 28
- 49
-
I am sorry, but this is still not what I asked for. In this case, the dimensions of [x,y] are the same as the image's and only [u,v] differs in size. What I would like is the case where the dimensions of [u,v] is the same as those of [x,y] and those are different from the dimensions of the image. Sorry... – olamundo May 02 '13 at 14:44
-
@noam Please see my update. [x,y] and [u,v] are the same size, but different from the image size. – shoelzer May 02 '13 at 15:18
-
-
@noam You're welcome. I just made a minor edit to use `interp2` because we are sampling (mapping) uniformly gridded data (the original texture). It should be faster than `griddata`. – shoelzer May 07 '13 at 18:06
EDIT:
Here is an example of texture mapping using the surface function:
%# image and 2D grid of points of the same size as the image
img = load('clown'); %# indexed color image
[m,n] = size(img.X);
[a,b] = meshgrid(1:n,1:m);
%# initial grid (here 1/5-th the size, but could be anything)
[X,Y] = meshgrid(linspace(1,n,n/5),linspace(1,m,m/5));
%# resize image to fit this grid
[C,map] = imresize(img.X, img.map, size(X), 'bicubic');
%# deformed 2D points (we dont need to know f, just load U/V here)
fx = @(x,y) sqrt(x);
fy = @(x,y) y.^2;
U = fx(X,Y);
V = fy(X,Y);
%# Z-coordinates: I'm using Z=0 for all points, but could be anything
Z = zeros(size(U));
%Z = peaks(max(size(U))); Z = Z(1:size(U,1),1:size(U,2)); view(3)
%# show image as texture-mapped surface
surface(U, V, Z, C, 'CDataMapping','direct', ...
'FaceColor','texturemap', 'EdgeColor','none')
colormap(map)
axis ij tight off
view(2)
An alternative to using imresize
is explicit interpolation (idea borrowed from @shoelzer):
CC = ind2rgb(img.X, img.map); %# convert to full truecolor
C = zeros(size(X));
for i=1:size(CC,3)
C(:,:,i) = griddata(a,b, CC(:,:,i), X,Y, 'linear');
end
of course with this change, there is no need for the colormap/CDataMapping anymore...
(Note: I think interp2
would be much faster here)
Note that in the example above, I'm using an indexed color image with an associated colormap. The code can easily be adapted to work on grayscale or truecolor full RGB images. See this page for an explanation on the different image types.

- 123,847
- 25
- 243
- 454
-
to see the effect of deformation, compare this against the original image: `figure, imshow(img.X,img.map)` – Amro Apr 30 '13 at 13:54
-
here is a related post that uses a similar technique: [How to change an image from (x y )coordinate to polar coordinate matlab](http://stackoverflow.com/a/7586650/97160) – Amro Apr 30 '13 at 14:00
-
Thanks, this is almost exactly what I want. However, you assume size(x)==size(img), while I also want it to work for size(x)==size(img)*k, i.e place the grid on top of the image and map each patch to the deformed grid. – olamundo Apr 30 '13 at 15:07
-
-
@noam: I'm not sure it matters, as you can see I've only used x/y to get the deformed u/v and attach the image on that grid. Perhaps you can use interpolation as shoelzer showed in his answer, and fit the surface over the deformed grid (see `griddata`, `scatteredInterpolant`, or any of the other similar functions) – Amro May 01 '13 at 22:13
-
-
1@Amro I have a question: What kind of data is 'clown' image of? I can't achieve to transform an image load by 'imread' to that kind of structure – Ander Biguri May 02 '13 at 08:13
-
1@amro - I am not sure I follow your claim. You specifically generated x y to be of the same size of the clown image. If you can change the code so that [x y], are say , 1/5 the size of the clown image, and it still works, I'll consider it a full answer. – olamundo May 02 '13 at 11:35
-
@noam For the grid to be a different size than the image you're going to need some kind of interpolation. I updated [my answer](http://stackoverflow.com/a/16302373/1339280) with example code to show how to do that. – shoelzer May 02 '13 at 13:39
-
@noam: sorry I see your point now. See my edit above.. This could be easily fixed with `imresize` or using interpolation as was mentioned by others. – Amro May 02 '13 at 20:02
-
@AnderBiguri: thanks! I included a remark at the end about image types with a link to the docs. The 'clown' image is an indexed image, with both the image and colormap stored in a structure. I can show how to use other types of images if you are having trouble with that – Amro May 02 '13 at 20:04
It seems that you can use tformfwd
and tforminv
with a small twist to get f
.
tformfwd
transforms points from input space to output space. For example, to apply an affine transform to the point (u,v) = (5,3), you can do this:
uv = [5 3];
xy = tformfwd(tform, uv)
This will out put the (x,y) coordinates given tform
Similarly, tforminv
transforms points from output space to input space. If we apply the inverse transformation to the point xy computed above, we should get back the original point.
uvp = tforminv(tform, xy)
uvp =
5 3
So, you can use this machinery to map points by the forward and inverse geometric transformation.
If you are using R2013a and later, you can use the transformPointsForward
and transformPointsInverse
methods of the geometric transformation classes (e.g. affine2d, projective2d), and also consider imwarp
.

- 25,846
- 10
- 70
- 101
-
Thanks, it is surely a step in the right direction, however it does not answer my question fully. I would still need to dissect the image to patches according to the grid, and then map each patch separately. The thing is, I have the points on the grid and their mapping. I am looking for a complete solution in which I just supply matlab with `x,y,u,v` and it does all the work. It seems easy to implement, but I would like to avoid for-loops as my code needs to be real-time. – olamundo Apr 30 '13 at 07:09
-
thanks for adding more info. so you don't have `f` but you do have `x,y,u,v`? is the transformation (x,y)->(u,v) one to one? or nothing is known? – bla Apr 30 '13 at 07:50
-
I would do that. Get the fundamental matrix for transformation of each element and the apply that transformation to the small piece of image of that element. Still I hardly thing this can be made without for loops (that are not slow in matlab anymore) or in real time. – Ander Biguri Apr 30 '13 at 08:47
-
@natan - If I am not mistaken, your updated answer seems to assume I have the deformation defined as some analytical function, as the `tform` argument. I don't. I just have the `[x,y]` points and the `[u,v]` points. – olamundo Apr 30 '13 at 18:54
-
`tform` is a matrix of values that needs to be nonsingular real . It is always numeric. see more here: http://www.mathworks.com/help/images/ref/maketform.html – bla Apr 30 '13 at 19:11
-
@noam, see Jona's answer here: http://stackoverflow.com/questions/12701841/xkcd-style-graphs-in-matlab on a numeric random applicatin of an imtransform using `tform` (in the answer he denotes it `tf`) – bla May 02 '13 at 00:22
Assuming x
, y
, u
and v
are of the same size (MxN
2D matrices) and the image/texture you wish to map is I
of size MxNx3
(three color channels), then you might find scatter
useful:
figure;
scatter( u(:), v(:), 30, reshape( I, [], 3 ), 's', 'filled' );

- 111,146
- 38
- 238
- 371