Unfold 3D Matrix to 2D
5 views (last 30 days)
Show older comments
Hi,
at first glance my question seems easy: I got a 512x512x79 matrix, which is a stack of 79 images. What I now would like to do is convert it to 40448x512 matrix which is a straightforward job for reshape, BUT I don't get it to work I'd like to:
I don't want to put the matrices just side by side or underneath each other, but rahter unfold or unwrap it, i.e. imagine the 3D matrix is the outer shell of a cylinder. Then I would like to get a rectangular field as a result.
Thanks a lot in advance!
3 Comments
Adam Danz
on 27 Mar 2019
Looks like you've got several solutions below.
Stephen Cobeldick's is quickest.
Andrei Bobrov's is most general (for example, if your array becomes 4x4x3).
Accept whichever answer suits your needs.
Answers (5)
Andrei Bobrov
on 27 Mar 2019
Edited: Andrei Bobrov
on 27 Mar 2019
[m,n,k] = size(A);
B = ones(k,n);
[y,x] = find(B);
DT = delaunayTriangulation(x,y);
C = convexHull(DT);
[yy,xx] = ind2sub([k,n],circshift(C(1:end-1),ceil((numel(C) - n -1)/2)));
out = A(sub2ind([m,n,k],ones(numel(xx),1),xx,yy)' + (0:m-1)');
Another variant:
[m,n,k] = size(A);
B = ones(k,n);
[y,x] = find(B);
DT = delaunayTriangulation(x,y);
C = convexHull(DT);
D = reshape(permute(A,[1,3,2]),m,[]);
out = D(:,circshift(C(1:end-1),-floor((numel(C)-1)/2)-1));
3 Comments
Stephen23
on 27 Mar 2019
Edited: Stephen23
on 27 Mar 2019
"This one matches the desired output."
??? My answer also gives exactly the requested output.
As Claas has not given any explanation of how this "unwrapping" should occur for other array sizes, your statement that Andrei Bobrov's solution is "the most general" is pure guessing: the order for larger array sizes has not been specified by Claas!
Walter Roberson
on 26 Mar 2019
Create a meshgrid of X, Y, Z coordinates relative to the center of the matrix. cart2pol() will then convert to r, theta, z .
Now create an interpolation grid of regularly spaced target r, target theta, target z coordinates, and
output = griddata(r, theta, z, OriginalMatrix, target_r, target_theta, target_z);
0 Comments
Stephen23
on 27 Mar 2019
Edited: Stephen23
on 27 Mar 2019
Currently the simplest solution is to just use indexing to get the order you want:
>> M = reshape(A,3,[]);
>> M = M(:,[8,7,4,1,2,3,6,5,9])
M =
32 31 21 1 2 3 23 22 33
35 34 24 4 5 6 26 25 36
38 37 27 7 8 9 29 28 39
There are multiple possible paths (especially the order of the last two columns seems quite arbitrary), and your definition is not enough to to define a general solution (e.g. consider an array with four columns and four pages: the outer "cylinder" might be intuitively defined, but the order of the inside columns is arbitrary, and you have not specified this).
0 Comments
Andrei Bobrov
on 28 Mar 2019
Third variant :
A = reshape(1:9,3,[])' + cat(3,0,20,30);
[m,n,k] = size(A);
size_2_3 = [n,k];
xy0 = [2,3];
out = A(:,FunBoundary(size_2_3,xy0,'right'));
function out = FunBoundary(size_2_3,xy0,direction)
nk = prod(size_2_3);
n = size_2_3(1);
c = [1:n,2*n:n:nk,nk-1:-1:nk-n+1,nk-2*n+1:-n:n+1]';
if strcmp(direction,'left')
c = c(end:-1:1);
end
ii0 = xy0(1) + n*(xy0(2) - 1);
[~,ii] = ismember(ii0,c);
out = circshift(c,1-ii);
end
0 Comments
See Also
Categories
Find more on Logical 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!