fast interp on 1 dimension of 3d matrix

46 views (last 30 days)
  1. Assume a Matrix A which is (M X N X P) array.
I want to upsample one dimension of the matrix, for example: upsample the third dimension by factor of 2.
Currently I'm using loops to make it happen:
B = zeros(M, N, 2 * P);
for ii = 1 : M
for jj = 1 : N
B(ii, jj, :) = interp(double(A(ii, jj, :)), 2);
end
end
Is there any way to do so which doesn't include any use of loops?
  3 Comments
Stephen23
Stephen23 on 20 Sep 2023
Edited: Stephen23 on 20 Sep 2023
@Bruno Luong: I moved your comment because this size was specified by the OP in their question.
Bruno Luong
Bruno Luong on 20 Sep 2023
Edited: Bruno Luong on 20 Sep 2023
@Stephen23 My comment is directed to your code with linspace, obviously violate the rule of integer upsampling https://en.wikipedia.org/wiki/Upsampling
Expansion: Create a sequence, , comprising the original samples,.
OP does not specify the size, he just allocate (wrongly) the size. He obviously want to use interp with upsampling integer factor
B(ii, jj, :) = interp(double(A(ii, jj, :)), 2)
And obviously induce @Lizhao Du to use the same flawed code.

Sign in to comment.

Accepted Answer

Stephen23
Stephen23 on 18 Dec 2018
Edited: Stephen23 on 18 Dec 2018
Use interp3 or interpn:
>> A = randi(9,5,7,3)
A(:,:,1) =
3 3 5 3 8 1 2
8 7 3 4 9 9 2
3 5 7 8 6 4 9
2 9 1 7 3 6 6
2 5 8 9 7 9 2
A(:,:,2) =
3 6 9 5 3 5 4
6 8 1 6 9 5 8
8 5 5 9 4 2 9
7 6 5 2 7 6 4
8 4 2 6 1 6 4
A(:,:,3) =
5 2 1 9 9 8 1
9 8 5 5 8 8 2
9 6 2 1 8 9 4
5 1 4 9 7 4 2
1 1 4 8 9 8 8
>> S = size(A);
>> Z = interpn(A,1:S(1),1:S(2),1:0.5:S(3)) % halve the step size
Z(:,:,1) =
3.0 3.0 5.0 3.0 8.0 1.0 2.0
8.0 7.0 3.0 4.0 9.0 9.0 2.0
3.0 5.0 7.0 8.0 6.0 4.0 9.0
2.0 9.0 1.0 7.0 3.0 6.0 6.0
2.0 5.0 8.0 9.0 7.0 9.0 2.0
Z(:,:,2) =
3.0 4.5 7.0 4.0 5.5 3.0 3.0
7.0 7.5 2.0 5.0 9.0 7.0 5.0
5.5 5.0 6.0 8.5 5.0 3.0 9.0
4.5 7.5 3.0 4.5 5.0 6.0 5.0
5.0 4.5 5.0 7.5 4.0 7.5 3.0
Z(:,:,3) =
3.0 6.0 9.0 5.0 3.0 5.0 4.0
6.0 8.0 1.0 6.0 9.0 5.0 8.0
8.0 5.0 5.0 9.0 4.0 2.0 9.0
7.0 6.0 5.0 2.0 7.0 6.0 4.0
8.0 4.0 2.0 6.0 1.0 6.0 4.0
Z(:,:,4) =
4.0 4.0 5.0 7.0 6.0 6.5 2.5
7.5 8.0 3.0 5.5 8.5 6.5 5.0
8.5 5.5 3.5 5.0 6.0 5.5 6.5
6.0 3.5 4.5 5.5 7.0 5.0 3.0
4.5 2.5 3.0 7.0 5.0 7.0 6.0
Z(:,:,5) =
5.0 2.0 1.0 9.0 9.0 8.0 1.0
9.0 8.0 5.0 5.0 8.0 8.0 2.0
9.0 6.0 2.0 1.0 8.0 9.0 4.0
5.0 1.0 4.0 9.0 7.0 4.0 2.0
1.0 1.0 4.0 8.0 9.0 8.0 8.0
Generate the required indices either using the colon operator (as shown, e.g. to halve the step size) or linspace (e.g. to double the number of points):
Z = interpn(A,1:S(1),1:S(2),linspace(1,S(3),2*S(3))) % double the number of points
Z(:,:,1) =
3.0 3.0 5.0 3.0 8.0 1.0 2.0
8.0 7.0 3.0 4.0 9.0 9.0 2.0
3.0 5.0 7.0 8.0 6.0 4.0 9.0
2.0 9.0 1.0 7.0 3.0 6.0 6.0
2.0 5.0 8.0 9.0 7.0 9.0 2.0
Z(:,:,2) =
3.0 4.2 6.6 3.8 6.0 2.6 2.8
7.2 7.4 2.2 4.8 9.0 7.4 4.4
5.0 5.0 6.2 8.4 5.2 3.2 9.0
4.0 7.8 2.6 5.0 4.6 6.0 5.2
4.4 4.6 5.6 7.8 4.6 7.8 2.8
Z(:,:,3) =
3.0 5.4 8.2 4.6 4.0 4.2 3.6
6.4 7.8 1.4 5.6 9.0 5.8 6.8
7.0 5.0 5.4 8.8 4.4 2.4 9.0
6.0 6.6 4.2 3.0 6.2 6.0 4.4
6.8 4.2 3.2 6.6 2.2 6.6 3.6
Z(:,:,4) =
3.4 5.2 7.4 5.8 4.2 5.6 3.4
6.6 8.0 1.8 5.8 8.8 5.6 6.8
8.2 5.2 4.4 7.4 4.8 3.4 8.0
6.6 5.0 4.8 3.4 7.0 5.6 3.6
6.6 3.4 2.4 6.4 2.6 6.4 4.8
Z(:,:,5) =
4.2 3.6 4.2 7.4 6.6 6.8 2.2
7.8 8.0 3.4 5.4 8.4 6.8 4.4
8.6 5.6 3.2 4.2 6.4 6.2 6.0
5.8 3.0 4.4 6.2 7.0 4.8 2.8
3.8 2.2 3.2 7.2 5.8 7.2 6.4
Z(:,:,6) =
5.0 2.0 1.0 9.0 9.0 8.0 1.0
9.0 8.0 5.0 5.0 8.0 8.0 2.0
9.0 6.0 2.0 1.0 8.0 9.0 4.0
5.0 1.0 4.0 9.0 7.0 4.0 2.0
1.0 1.0 4.0 8.0 9.0 8.0 8.0
  21 Comments
Bruno Luong
Bruno Luong on 18 Dec 2018
Edited: Bruno Luong on 18 Dec 2018
The difference between
Z = interp1(A,linspace(1,S(1),2*S(1)))
and your original INTERP code is that the INTERP1 is not integer-upsampling.
INTERP do integer upsampling and must extrapolate on the right side with (q-1) points where q is up-sampling factor (2 in your example).
It carried out but padding one 0 and filter the padded data, so the extrapolation signal dies out on the right side and can introduce some oscilation.
The difference, though subtle, might be important or not depending on your ultimate goal.
Lizhao Du
Lizhao Du on 18 Sep 2023
Z = interp1(A,linspace(1,S(1),2*S(1)))
It does help!
Thanks to Stephen!

Sign in to comment.

More Answers (3)

madhan ravi
madhan ravi on 18 Dec 2018
interp3(A,2)
  1 Comment
Nitai Fingerhut
Nitai Fingerhut on 18 Dec 2018
Edited: Nitai Fingerhut on 18 Dec 2018
Vq = interp3(V,k) returns the interpolated values on a refined grid formed by repeatedly halving the intervals k times in each dimension. This results in 2^k-1 interpolated points between sample values.
I want to interpolate only along the third dimension and not along all 3 dimensions.

Sign in to comment.


Bruno Luong
Bruno Luong on 18 Dec 2018
Edited: Bruno Luong on 18 Dec 2018
[m,n,p] = size(A);
B = reshape(A,[m*n p]).';
Br = resample(B,2,1); % 2 is upsampling factor
Ar = reshape(Br.',m,n,[]);

Matt J
Matt J on 18 Dec 2018
Using imresizen (Download)
B = imresizen(A,[1,1,2]);
  3 Comments
Matt J
Matt J on 18 Dec 2018
By default, it uses linear interpolation, but you can specify any interpolation method that griddedInterpolant implements, e.g.,
B = imresizen(A,[1,1,2],'pchip');
Matt J
Matt J on 18 Dec 2018
Edited: Matt J on 18 Dec 2018
In addition- I noticed that "imresizen" uses a for loop so it won't improve running time...
Incorrect. The for loop in imresizen only runs in your case from 1 to 3 (the number of dimensions) and does trivially fast pre-computations.

Sign in to comment.

Categories

Find more on Interpolation of 2-D Selections in 3-D Grids in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!