【问题标题】:Three dimensional (3D) matrix interpolation in MatlabMatlab中的三维(3D)矩阵插值
【发布时间】:2014-09-06 03:24:09
【问题描述】:

我在 Matlab 中有一个特定大小的 3D 矩阵,但是我需要对其进行插值以获得更大尺寸的矩阵。

size(M)
ans= 
  50   108    86

我需要对该矩阵进行插值并最终获得一个大小为100x213x140 的矩阵。关于如何使用interp3 的任何想法?这可能吗?

我试过了

Vq = interp3(M,1:100,1:213,1:140)
Error using griddedInterpolant/subsref
The input data has inconsistent size.

Error in interp3 (line 178)
    Vq = F(Xq,Yq,Zq);

如果我使用meshgrid:

[X,Y,Z] = meshgrid(1:100, 1:213, 1:140);
Vq =interp3(M,X,Y,Z);

Matlab 似乎喜欢它,但是发生了两件事:

  1. size(Vq) ans= 213 100 140
  2. 我可以在Vq 中看到NaN 的值

背后的原因是因为我需要比较以不同频率采样的两个矩阵。因此,我可以对M 进行插值以获得大小为100x213x140 的矩阵,或者将我的另一个大小为100x213x140 的矩阵M2 的大小“减小”为50x108x86。我认为前者应该更容易更安全......

【问题讨论】:

  • 您是要调整矩阵的大小,使其看起来像原始的M,但要大两倍,还是只是想插入值?
  • @rayryeng 我想调整它的大小,但我还需要这些新坐标的值,因此需要插值
  • 我现在给你写一篇文章。
  • 我必须为您编写代码才能这样做。 MATLAB 中没有内置函数。我会修改我的帖子。
  • 要调整 3D 矩阵的大小,您也可以使用此解决方案:stackoverflow.com/questions/12520152/…

标签: octave interpolation matlab


【解决方案1】:

你几乎说对了。您需要定义坐标的3D 网格。创建单个向量不是正确的方法。你当然可以在这里使用interp3。尝试做:

[X,Y,Z] = meshgrid(1:213, 1:100, 1:140);
Vq = interp3(M, X, Y, Z);

请注意,我交换了行 (100) 和列 (213) 限制,因为第一个参数水平进行,而第二个参数垂直进行。

此外,通过以这种方式使用interp3,我们假设XYZ 的限制在1:2131:1001:140 之内。如果您提供超出这些限制的任何值,您将获得NaN。有几种方法可以避免这种情况:

  1. 在末尾指定 spline 标志以允许样条外推
  2. 如果您想调整矩阵的大小(例如调整图像的大小),那么目前没有可以通过这种方式调整 3D 矩阵大小的内置方法。你必须自己写这个。

如果您想执行第 2 步,您可以执行以下操作。

首先,您需要计算出每个维度的比例因子。基本上这是每个维度的输出大小与原始输入大小的比值。

在此之后,您将创建一个 2D 网格,其限制为输入矩阵的原始大小,但该网格的大小将与输出矩阵的大小相同。比例因子在这里很有用,因为它有效地为我们提供了网格中每个值应该插值的内容。我们将创建从 1 到每个维度的输出大小的新坐标,增量为1/scaleFactor。例如,如果我们想将矩阵的大小加倍,这是一个因子 2。如果我们的 XY 坐标从 1 变为 3 和 1分别为 3,原始网格如下所示:

X =            Y = 

1  2  3        1  1  1
1  2  3        2  2  2
1  2  3        3  3  3

要加倍,这只是:

X =                         Y = 

1  1.5  2  2.5  3           1   1   1   1   1
1  1.5  2  2.5  3          1.5 1.5 1.5 1.5 1.5
1  1.5  2  2.5  3           2   2   2   2   2
1  1.5  2  2.5  3          2.5 2.5 2.5 2.5 2.5 
1  1.5  2  2.5  3           3   3   3   3   3

请注意,这会创建一个 5 x 5 的输出网格。要将其加倍为 6 x 6,您可以做任何您想做的事情,但为了简单起见,只需复制最后一行和最后一列,因此:

X =                         Y = 

1  1.5  2  2.5  3  3         1   1   1   1   1   1
1  1.5  2  2.5  3  3        1.5 1.5 1.5 1.5 1.5 1.5
1  1.5  2  2.5  3  3         2   2   2   2   2   2
1  1.5  2  2.5  3  3        2.5 2.5 2.5 2.5 2.5 2.5
1  1.5  2  2.5  3  3         3   3   3   3   3   3
1  1.5  2  2.5  3  3         3   3   3   3   3   3

这定义了我们用于调整大小的 2D 列网格。现在是在 3D 中调整大小的问题。我们可以做的是在切片之间进行插值。我们可以在 MATLAB 中使用permute 轻松做到这一点,稍后我将向您展示如何做到这一点。因此,基本算法是这样的:

  • 确定所需输出矩阵的输出大小
  • 确定每个维度的比例因子
  • 按照上述过程为每个维度创建一个包含插值访问值的 2D 网格
  • 对于矩阵中的每个二维切片,使用interp2 将每个切片的大小调整为使用上述二维网格的输出行和列。
  • 之后,使用interp1permute 调整第三个维度的大小。

事不宜迟,下面是执行此操作的代码:

%// Specify output size of your matrix here
outputSize = [100 213 140];

%//Figure out size of original matrix
d = size(M);

%//Scaling coefficients
scaleCoeff = outputSize ./ d;

%//Indices of original slices in 3D
z = 1:d(3);

%//Output slice indices in 3D
zi=1:1/scaleCoeff(3):d(3);

%//Create gridded interpolated co-ordinates for 1 slice
[X,Y] = meshgrid(1:1/scaleCoeff(2):d(2), 1:1/scaleCoeff(1):d(1));

%//We simply duplicate the last rows and last columns of the grid if
%//by doing meshgrid, we don't get exactly the output size we want
%//This is due to round off when perform 1/scaleCoeff(2) or
%//1/scaleCoeff(1).  We would be off by 1.
if size(X,1) ~= outputSize(1)
    X(end+1,:) = X(end,:);
    Y(end+1,:) = Y(end,:);
end
if size(X,2) ~= outputSize(2)
    X(:,end+1) = X(:,end);
    Y(:,end+1) = X(:,end);
end

%//For each slice...
M2D = zeros(outputSize(1), outputSize(2), d(3));
for ind = z
    %//Interpolate each slice via interp2
    M2D(:,:,ind) = interp2(M(:,:,ind), X, Y);
end

%//Now interpolate in 3D
MFinal = permute(interp1(z,permute(M2D,[3 1 2]),zi),[2 3 1]);

%//If the number of output slices don't match after we interpolate in 3D, we
%//just duplicate the last slice again
if size(MFinal,3) ~= outputSize(3)
    MFinal(:,:,end+1) = MFinal(:,:,end);
end

MFinal 将是您最终的插值/调整大小的 3D 矩阵。在 3D 中插值的关键方法是 permute 方法。这将做的是,对于z 的每个值,我们将生成一个二维值切片。因此,如果我们在z = 1 有一个切片,在z = 2 有一个切片,如果我们想找到切片z = 1.5 的二维值网格,这将生成一个二维切片,它使用信息创建这些插值在z = 1z = 2 之间。我们首先调用permute 来执行此操作,然后再调用permute 来撤消我们的排列并取回原始尺寸。

【讨论】:

  • 哦!我现在明白了!
  • 这真是太棒了!使用interp3 时是否应该始终交换行和列限制?
  • @Manolete - 是的。第一个参数总是水平进行,而第二个参数是垂直进行。此外,如果您想推断,请在末尾使用 spline 标志。我会修改我的答案。
  • 我检查了获得的矩阵的值,似乎有两种类型的值,0s 和 NaNs。我可能做错了什么
  • @Manolete - 别担心。我会修正我的答案
猜你喜欢
  • 2015-02-02
  • 2016-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多