我在常规2D [x,y]=meshgrid(1:N,1:M)
网格上定义了一组点N x M
。我有另一组点[u,v]
,它们是原始网格的一些变形,即[u,v]=f(x,y)'
(但是我没有导致变形的实际f
)。如何将纹理映射到u,v
定义的“变形”网格?即,如果给出具有宽高比N/M
的图像,我该如何将其映射到变形网格?
答案 0 :(得分:6)
我想你要求在[u,v]
获取原始纹理的样本。您可以使用interp2。
假设纹理样本位于z
,您需要新样本z2
。要在[u,v]
处插入原始纹理,请使用:
z2 = interp2(x,y,z,u,v);
另一方面,如果要将“变形”纹理映射回规则间隔的网格[x2,y2]
,请使用griddata:
[x2,y2] = meshgrid(1:N2,1:M2);
z2 = griddata(u,v,z,x2,y2);
<强>更新强>
以下是一些示例代码,展示了如何使用实际数据执行此操作。使用标准化坐标可以更容易。
% 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')
这就是结果:
答案 1 :(得分:4)
以下是texture mapping使用surface函数的示例:
%# 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)
使用imresize
的替代方法是显式插值(从@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
当然有了这个改变,就不再需要colormap / CDataMapping ......
(注意:我认为interp2
在这里要快得多)
请注意,在上面的示例中,我使用带有关联色彩映射的索引彩色图像。该代码可以很容易地适用于灰度或真彩色全RGB图像。有关不同图像类型的说明,请参阅this page。
答案 2 :(得分:1)
您似乎可以使用tformfwd
和tforminv
进行小转动以获得f
。
tformfwd
将点从输入空间转换为输出空间。例如,要将仿射变换应用于点(u,v)=(5,3),您可以这样做:
uv = [5 3];
xy = tformfwd(tform, uv)
这将把(x,y)坐标给出tform
类似地,tforminv
将点从输出空间转换为输入空间。如果我们将逆变换应用于上面计算的点xy,我们应该回到原点。
uvp = tforminv(tform, xy)
uvp =
5 3
因此,您可以使用此机制通过正向和反向几何变换来映射点。
如果您使用的是R2013a及更高版本,则可以使用几何变换类的transformPointsForward
和transformPointsInverse
方法(例如affine2d,projective2d),并考虑imwarp
。
答案 3 :(得分:1)
假设x
,y
,u
和v
具有相同的尺寸(MxN
2D矩阵)和您希望映射的图像/纹理是I
大小MxNx3
(三种颜色通道),那么您可能会发现scatter
有用:
figure;
scatter( u(:), v(:), 30, reshape( I, [], 3 ), 's', 'filled' );