4

我想绘制一个带有纹理贴图的表面,但条件不是“理想”的。

首先让我们解释一下我有什么。

我有一组点(~7000),它们是网格中的图像坐标。这点不定义完美的正方形。 它不是网格。为了这个问题,让我们假设我们有 9 分。让我们用图像来说明我们所拥有的:

 X=[310,270,330,430,410,400,480,500,520]
 Y=[300,400,500,300,400,500,300,400,500]

在此处输入图像描述 假设我们可以得到网格的“结构”,所以

 size1=3;
 size2=3;
 points=zeros(size1,size2,2)
 X=[310,270,330;
    430,410,400;
    480,500,520]
 Y=[300,400,500;
    300,400,500;
    300,400,500]
 points(:,:,1)=X;
 points(:,:,2)=Y;

现在假设我们有一个第三维度,Z。

编辑:如果信息忘记添加一块。我对图像中的点进行三角测量并获得 3D 对应关系,因此当显示在表面中时,它们没有图像的 X 和 Y 坐标,为了简化给定数据,可以说 X=X/2 Y=Y /3

我们有:

 points=zeros(size1,size2,3)
 Z=[300,330,340;
    300,310,330;
    290,300,300]

 surf(points(:,:,1)/2,points(:,:,2)/3,points(:,:,3))

在此处输入图像描述

我想要的是用图像纹理绘制 3D 表面。每个元素都应具有第一张图像中的纹理块。

这需要适用于庞大的数据表。我并不特别需要它很快。

相关帖子(但我有一个网格网格作为初始点集):2D 网格的纹理贴图

PD:如果需要,我可以发布原始图像+真实数据,之所以发布这个是因为我认为使用小数据更容易。

4

3 回答 3

10

您可以使用 which 的texturemap属性surf适用于矩形网格以及非矩形网格。

创建非矩形数据点

% creating non-rectangular data points
[X, Y] = meshgrid(1:100, 1:100);
X = X+rand(size(X))*5; 
Y = Y+rand(size(X))*5; 

这导致以下数据点:

在此处输入图像描述

生成高度数据:

Z = sin(X/max(X(:))*2*pi).*sin(Y/max(Y(:))*2*pi);

在此处输入图像描述

加载图片:

[imageTest]=imread('peppers.png');

在此处输入图像描述

并将其作为纹理映射到网格:

surf(X,Y,Z, imageTest, ...
     'edgecolor', 'none','FaceColor','texturemap')

在此处输入图像描述

请注意,为了演示,这个非矩形网格非常稀疏,导致纹理相当参差不齐。使用更多的点,结果会变得更好,而与网格点的失真无关。

另请注意,网格点的数量不必与纹理图像中的像素数量相匹配。

~编辑~

如果 X 和 Y 坐标仅适用于部分图像,您可以通过以下方式相应地调整纹理

minX = round(min(X(:)));
maxX = round(max(X(:))); 
minY = round(min(Y(:)));
maxY = round(max(Y(:)));

surf(X,Y,Z, imageTest(minX:maxX, minY:maxY, :), ...
     'edgecolor', 'none','FaceColor','texturemap')
于 2013-05-07T10:31:01.057 回答
4

我不认为你可以用 Matlab 的内置命令和功能做你想做的事。但是使用我的其他答案中的技术和高分辨率版本的网格可以为您做到这一点。

“高分辨率”是指具有更密集数据点的非均匀网格的插值版本。用于在更密集的数据点对纹理进行采样,以便可以使用 的texturemap特征进行绘制surf。但是,您不能使用普通的 2D 插值,因为您需要保留不均匀的网格形状。这就是我想出的:

function g = nonUniformGridInterp2(g, sx, sy)

[a,b] = size(g);
g = interp1(linspace(0,1,a), g, linspace(0,1,sy)); % interp columns
g = interp1(linspace(0,1,b), g', linspace(0,1,sx))'; % interp rows

请注意,您必须调用它两次以独立插入 X 和 Y 点。这是原始网格的示例和每个方向有 10 个点的插值版本。

绘制原始网格和插值网格

以下是如何将高分辨率网格与interp2和一起使用texturemap

function nonUniformTextureMap

% define the non-uniform surface grid
X = [310,270,330; 430,410,400; 480,500,520];
Y = [300,400,500; 300,400,500; 300,400,500];
Z = [300,330,340; 300,310,330; 290,300,300];

% get texture data
load penny % loads data in variable P

% define texture grid based on image size
% note: using 250-550 so that a,b covers the range used by X,Y
[m,n] = size(P);
[a,b] = meshgrid(linspace(250,550,n), linspace(250,550,m));

% get a high-res version of the non-uniform grid
s = 200; % number of samples in each direction
X2 = nonUniformGridInterp2(X, s, s);
Y2 = nonUniformGridInterp2(Y, s, s);

% sample (map) the texture on the non-uniform grid
C = interp2(a, b, P, X2, Y2);

% plot the original and high-res grid
figure
plot(X(:),Y(:),'o',X2(:),Y2(:),'.')
legend('original','high-res')

% plot the surface using sampled points for color
figure
surf(X, Y, Z, C, 'edgecolor', 'none', 'FaceColor','texturemap')
colormap gray

映射纹理的绘图

于 2013-05-09T13:50:00.843 回答
1

我不确定我是否理解您的问题,但我认为您需要做的是在网格的 X、Y 点处对纹理进行采样(映射)。然后您可以简单地绘制表面并将这些样本用作颜色。

这是一个使用您在问题中提供的数据的示例。它看起来并不多,但使用更多的 X、Y、Z 点应该可以得到你想要的结果。

% define the non-uniform surface grid
X = [310,270,330; 430,410,400; 480,500,520];
Y = [300,400,500; 300,400,500; 300,400,500];
Z = [300,330,340; 300,310,330; 290,300,300];

% get texture data
load penny % loads data in variable P

% define texture grid based on image size
% note: using 600 so that a,b covers the range used by X,Y
[m,n] = size(P);
[a,b] = meshgrid(linspace(0,600,n), linspace(0,600,m));

% sample (map) the texture on the non-uniform grid
C = interp2(a, b, P, X, Y);

% plot the surface using sampled points for color
figure
surf(X, Y, Z, C)
colormap gray

映射纹理的绘图

于 2013-05-07T18:48:59.660 回答