4

[x,y]=meshgrid(1:N,1:M)在常规 2DN x M网格上定义了一组点。我有另一组点[u,v]是原始网格的一些变形,即[u,v]=f(x,y)'(但是我没有f导致变形的实际点)。如何将纹理映射到由定义的“变形”网格u,v?即,给定具有纵横比的图像,N/M我如何将其映射到变形网格?

4

4 回答 4

6

我想你是在要求获取原始纹理的样本[u,v]。您可以使用interp2

假设纹理样本在z并且您想要新样本z2。要在 处插入原始纹理[u,v],请使用:

z2 = interp2(x,y,z,u,v);

另一方面,如果要将“变形”纹理映射回规则间隔的 grid [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')

这是结果:

原始和变形纹理图

于 2013-04-30T14:29:20.577 回答
4

编辑:

下面是一个使用表面函数的纹理映射示例:

%# 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

当然有了这个改变,就不再需要颜色图/CDataMapping了......

(注意:我认为interp2这里会快得多)


请注意,在上面的示例中,我使用的是带有关联颜色图的索引彩色图像。该代码可以很容易地适用于灰度或真彩色全 RGB 图像。有关不同图像类型的说明,请参阅此页面

于 2013-04-30T13:45:57.757 回答
1

看来您可以使用tformfwdtforminv稍加扭动即可获得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 及更高版本,则可以使用几何变换类(例如 affine2d、projective2d)的transformPointsForward和方法,还可以考虑.transformPointsInverseimwarp

于 2013-04-30T03:29:46.340 回答
1

假设xy和具有相同的大小(二维矩阵)u并且您希望映射的图像/纹理具有大小(三个颜色通道),那么您可能会发现有用:vMxNIMxNx3scatter

figure;
scatter( u(:), v(:), 30, reshape( I, [], 3 ), 's', 'filled' );
于 2013-04-30T09:04:53.793 回答