Matlab中的三维(3D)矩阵插值

时间:2014-07-15 19:26:48

标签: octave interpolation matlab

我在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. 我可以在NaN
  3. 中看到Vq个值

    背后的原因是因为我需要比较以不同频率采样的两个矩阵。因此,我可以插入M以获得大小为100x213x140或"缩小"的矩阵。我的其他矩阵M2的大小100x213x14050x108x86的大小。我认为前者应该更容易,更安全......

1 个答案:

答案 0 :(得分:4)

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

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

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

此外,通过以这种方式使用interp3,我们假设XYZ的限制属于1:213,{{ 1}}和1:100。如果您提供超出这些限制的任何值,您将获得1:140。有几种方法可以避免这种情况:

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

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

    在此之后,您创建一个2D网格,其限制受输入矩阵的原始大小限制,但此网格的大小将是输出矩阵的大小。比例因子在这里很有用,因为这有效地为我们提供了网格中每个值应该插值的内容。我们将创建新的坐标,从1到每个维度的输出大小,以spline为增量。例如,如果我们想要加倍矩阵的大小,则这是2的因子。如果我们有1/scaleFactorX坐标从1开始分别为3和1到3,原始网格看起来像这样:

    Y

    要加倍,这只是:

    X =            Y = 
    
    1  2  3        1  1  1
    1  2  3        2  2  2
    1  2  3        3  3  3
    

    请注意,这会创建一个5 x 5的输出网格。为了使其加倍为6 x 6,您可以执行任何操作,但为了简单起见,只需复制最后一行和最后一列,以便:

    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
    

    这定义了用于调整大小的2D列网格。现在,这是在3D中调整大小的问题。我们可以做的是在切片之间进行插值。我们可以使用MATLAB中的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切片,使用permute使用上述2D网格将每个切片的大小调整为输出行和列。
    • 之后,使用interp2interp1调整第三维的大小。

    不用多说,这是执行此操作的代码:

    permute

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