【问题标题】:How to plot a surface with a texture map如何使用纹理贴图绘制表面
【发布时间】:2014-06-20 02:13:47
【问题描述】:

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

首先让我们解释一下我所拥有的。

我在网格中有一组点 (~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 表面。每个元素都应具有第一张图像中的纹理。

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

相关帖子(但我有一个网格作为初始点集):Texture map for a 2D grid

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

【问题讨论】:

    标签: matlab image-processing texture-mapping geometry-surface


    【解决方案1】:

    您可以使用surftexturemap 属性,它适用于矩形网格以及非矩形网格。

    创建非矩形数据点

    % 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')
    

    【讨论】:

    • 不使用网格网格怎么办?我知道如何使用网格网格来做到这一点,您可以在我在问题中发布的链接中看到它。抱歉,这不能回答问题
    • @AnderBiguri:请查看我的更新答案,并原谅我一开始没有仔细阅读您的问题。
    • 感谢 H.Muster。我忘了添加表面网格的一些细节,请检查我的编辑。我认为您的答案的变化很小,但我似乎找不到答案。
    • @AnderBiguri:网格坐标不必与纹理坐标匹配。只要不对网格点进行非线性变换,纹理就应该映射到网格点,而与变换无关。
    • 我测试了你的答案。它朝着正确的方向发展,但它不是正确的方向(至少在我的测试中不是!)。似乎整个纹理都绘制在表面上,但这不是我想要的。我只想绘制与每个元素对应的纹理。因此,在我在我的问题中发布的 image2 中,要绘制的纹理应该是与 image1 中的正方形相对应的纹理。这就是为什么我注意到改变的像素对应关系,因为它应该很重要。
    【解决方案2】:

    我不认为你可以用 Matlab 的内置命令和功能做你想做的事。但是使用来自my other answer 的技术和高分辨率版本的网格可以为您做到这一点。

    “高分辨率”是指具有更密集数据点的非均匀网格的插值版本。这用于在更密集的数据点对纹理进行采样,以便可以使用surftexturemap 功能进行绘制。但是,您不能使用普通的 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 个点的插值版本。

    下面是如何将高分辨率网格与 interp2texturemap 一起使用。

    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
    

    【讨论】:

    • 很棒的家伙。我不相信这个想法。我会尝试做这样的事情,它可能会很好用。不过,只是想知道,这样做需要多长时间?似乎也很快!
    • @AnderBiguri 谢谢!得到这个想法后,代码只花了几分钟就写好了。这个小数据集既好又快。你的“巨大”数据集怎么样了?
    • 我仍然无法绘制它,因为它有点复杂,但这个想法是正确的,它应该可以工作!
    【解决方案3】:

    我不确定我是否理解您的问题,但我认为您需要做的是在网格的 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
    

    【讨论】:

    • 不,这不是我想要的,抱歉。我想要在这个表面上绘制纹理本身。您刚刚绘制了一种颜色,但在 4 点之间有一个完整的纹理。我想提取第一张图像中每个元素的纹理以在表面的每个元素中绘制它(作为纹理,不作为颜色)。
    • @AnderBiguri 现在我明白了!请看我的新答案。
    猜你喜欢
    • 2021-03-31
    • 1970-01-01
    • 1970-01-01
    • 2019-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-07
    • 2014-05-03
    相关资源
    最近更新 更多