简体   繁体   English

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

[英]Three dimensional (3D) matrix interpolation in Matlab

I have a 3D matrix in Matlab of certain size, however I would need to interpolate it to obtain matrix of larger size. 我在Matlab中有一个特定大小的3D矩阵,但是我需要对其进行插值以获得更大尺寸的矩阵。

size(M)
ans= 
  50   108    86

I need that matrix to be interpolated and finally obtain a matrix of size 100x213x140 . 我需要对该矩阵进行插值并最终获得大小为100x213x140的矩阵。 Any ideas of how to do it using interp3 ? 关于如何使用interp3任何想法? Is this possible at all? 这有可能吗?

I've tried 我试过了

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);

If I use meshgrid : 如果我使用meshgrid

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

Matlab seems to like it, however two things happen: Matlab似乎很喜欢它,但是发生了两件事:

  1. size(Vq) ans= 213 100 140
  2. I can see NaN values in Vq 我可以在Vq看到NaN

The reason behind is because I need to compare two matrices sampled at different frequency. 背后的原因是因为我需要比较以不同频率采样的两个矩阵。 So, I could either interpolate M to obtain a matrix of size 100x213x140 or "reduce" the size of my other matrix M2 of size 100x213x140 to 50x108x86 . 所以,我既可以插M获得大小的矩阵100x213x140或“减少”我的其他矩阵大小M2的尺寸100x213x14050x108x86 I thought the former should be easier and safer... 我认为前者应该更容易,更安全。

You almost have it right. 您几乎是正确的。 You need to define 3D Grid of co-ordinates. 您需要定义坐标的3D网格 Creating single vectors is not the right way to do it. 创建单个向量不是正确的方法。 You can certainly use interp3 here. 您当然可以在这里使用interp3 Try doing: 尝试做:

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

Note that I have swapped the row (100) and column (213) limits, as the first parameter progresses horizontally while the second parameter progresses vertically. 请注意,我已经交换了行(100)和列(213)的限制,因为第一个参数是水平进行的,而第二个参数是垂直进行的。

Also, by using interp3 in this fashion, we are assuming that the limits of X , Y and Z fall within 1:213 , 1:100 and 1:140 . 同样,通过以这种方式使用interp3 ,我们假设XYZ的限制落在1:213 interp3 1:1001:140 Should you provide any values outside of these limits, you will get NaN . 如果您提供超出这些限制的任何值,则将获得NaN There are a couple of ways you can avoid this: 有两种方法可以避免这种情况:

  1. Specify the spline flag at the end to allow for spline extrapolation 在末尾指定spline标志以允许样条线外推
  2. If you want to resize the matrix (like if you were to resize an image), then there currently is no built-in method that can resize a 3D matrix this way. 如果要调整矩阵的大小 (例如要调整图像的大小),则当前没有内置方法可以以此方式调整3D矩阵的大小。 You'll have to write this yourself. 您必须自己编写。

If you want to do Step #2, you can do the following. 如果要执行步骤2,则可以执行以下操作。

First, you need to figure out the scale factors for each dimension. 首先,您需要找出每个维度的比例因子。 Basically this is the ratio of the output size of each dimension with the original input size. 基本上,这是每个尺寸的输出尺寸与原始输入尺寸的比率。

After this, you create a 2D grid that has its limits bounded by the original size of the input matrix, but the size of this grid will be of the size of the output matrix. 此后,您将创建一个2D网格,其限制由输入矩阵的原始大小限制,但是此网格的大小将与输出矩阵的大小相同。 The scale factor is useful here because this effectively gives us what each value in the grid should be to interpolate. 比例因子在这里很有用,因为这可以有效地给我们网格中每个值都应该进行插值。 We would create new co-ordinates that went from 1 to the output size of each dimension, in increments of 1/scaleFactor . 我们将创建新的坐标,该坐标从1到每个维度的输出大小,以1/scaleFactor为增量。 As an example, if we wanted to double the size of our matrix, this is a factor of 2. If we had X and Y co-ordinates that went from 1 to 3 and 1 to 3 respectively, the original grid would look like this: 例如,如果我们想将矩阵的大小加倍 ,这是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

To double this, this would simply be: 要加倍,这将是:

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

Note that this create an output grid of 5 x 5. To make this doubled as 6 x 6, you can do whatever you want, but for the sake of simplicity, just duplicate the last row and last column, and so: 请注意,这将创建一个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

This defines our grid of 2D columns for resizing. 这定义了我们的2D列网格以调整大小。 Now it's a matter of resize in 3D. 现在是3D尺寸调整的问题。 What we can do is interpolate in between the slices . 我们可以做的是在切片之间进行插值。 We can easily do this using permute in MATLAB, and I'll show you how to do that later. 我们可以使用MATLAB中的permute轻松地做到这一点,稍后我将向您展示如何做到这一点。 As such, the basic algorithm is this: 因此,基本算法是这样的:

  • Determine the output size of the output matrix you want 确定所需输出矩阵的输出大小
  • Determine the scale factors in each dimension 确定每个维度的比例因子
  • Create a 2D grid of interpolated access values for each dimension following the procedure above 按照上述步骤为每个维度创建一个内插访问值的2D网格
  • For each 2D slice in your matrix, use interp2 to resize each slice to the output rows and columns using the above 2D grid. 对于矩阵中的每个2D切片,请使用interp2使用上述2D网格将每个切片调整为输出行和列的大小。
  • After, use interp1 and permute to resize the third dimension. 之后,使用interp1permute以调整第三维的大小。

Without further ado, here is the code to do this: 事不宜迟,下面是执行此操作的代码:

%// 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 would be your final interpolated / resized 3D matrix. MFinal将是您最终插入/调整大小的3D矩阵。 The key method to interpolate in 3D is the permute method. 在3D中进行插值的关键方法是permute方法。 What this will do is that for each value of z , we will generate a 2D slice of values. 这将为z每个值生成一个二维的值切片。 As such, if we had a slice at z = 1 and one at z = 2 , if we wanted to find what the 2D grid of values was at slice z = 1.5 , this will generate a 2D slice that creates these interpolated values using information between z = 1 and z = 2 . 这样,如果我们在z = 1处有一个切片,在z = 2处有一个切片,如果我们想找到切片z = 1.5处的二维值网格,则将生成一个二维切片,该切片使用信息创建这些插值在z = 1z = 2 We do the first call of permute to do this, then another permute call to undo our permutation and get the original dimensions back. 我们做的第一个电话permute要做到这一点,那么另一个permute呼吁取消我们的置换,并获得原始尺寸回来。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM