You almost have it right. You need to define 3D Grid of co-ordinates. Creating single vectors is not the right way to do it. You can certainly use interp3
here. 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.
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
. Should you provide any values outside of these limits, you will get NaN
. There are a couple of ways you can avoid this:
- Specify the
spline
flag at the end to allow for spline extrapolation
- 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. You'll have to write this yourself.
If you want to do Step #2, you can do the following.
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. 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
. 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:
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:
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. Now it's a matter of resize in 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. 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
- For each 2D slice in your matrix, use
interp2
to resize each slice to the output rows and columns using the above 2D grid.
- After, use
interp1
and permute
to resize the third dimension.
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. The key method to interpolate in 3D is the permute
method. What this will do is that for each value of z
, we will generate a 2D slice of values. 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
. We do the first call of permute
to do this, then another permute
call to undo our permutation and get the original dimensions back.