MATLAB Answers

Please help, logical indexing of 3D matrices

42 views (last 30 days)
Miguel Lopes
Miguel Lopes on 6 Mar 2015
Answered: Tongyao Pu on 6 Nov 2019
Hello
I'm stuck on this stupid thing and i know is obvious.
I have this matrice A: 480x848x3
And this logical matrice B: 480x848
And I want a matrice C=zeros(480, 848) like this: C(B)=A(B,1)
It should work but there's something wrong. I thought it might be like this:
C(B)=A([B 1])
or like this:
C(B)=A([B, 1])
or like this:
C(B)=A([B; 1])
But nothing works.
I know it works if i make:
D=A(:,:,1)
C(B)=D(B)
But how do i make it work with the indexes in 3D???
Thanks!!!
  10 Comments
James Tursa
James Tursa on 6 Mar 2015
So, it sounds like the memory problem isn't this calculation for a single photo, but the fact that you have very many of these photos in memory at the same time?

Sign in to comment.

Answers (5)

Star Strider
Star Strider on 6 Mar 2015
Edited: Star Strider on 6 Mar 2015
Your ‘A’ matrix looks like it could be an image. To collapse the third dimension, use the rgb2gray function in the Image Processing Toolbox.
For example:
A = uint8(randi([0 255], 480, 848, 3));
figure(1)
imshow(A)
G = rgb2gray(A);
figure(2)
imshow(G)
Another option is to expand ‘C’ to three dimensions by replicating it three times in the third dimension:
C = zeros(480,848);
Cx = repmat(C, 1, 1, 3);
  2 Comments
Star Strider
Star Strider on 6 Mar 2015
If you need all three channels, then don’t collapse them into grayscale.
If you have different masks for each channel, concatenate them:
C1 = uint8(randi([0 255],480,848)); % Red Mask
C2 = uint8(randi([0 255],480,848)); % Green Mask
C3 = uint8(randi([0 255],480,848)); % Blue Mask
Cc= cat(3, C1, C2, C3); % All Masks
That creates a (480x848x3) matrix in ‘Cc’ that you may be able to use.

Sign in to comment.


Adam
Adam on 6 Mar 2015
Edited: Adam on 6 Mar 2015
(Edited version as in comments below - original edit was incorrect!)
C = zeros( size(B) );
ind2d = find(B);
C( ind2d ) = A( ind2d );
works without needing to create another matrix. Note that it works specifically because it is the 1st index of the 3rd dimension that you want. If you wanted the 2nd then you would need to add the x*y size to the ind2d array and for the 3rd index of the 3rd dimension you would need to add twice the x*y size to the indices.
In case you aren't aware, this works because you can use 1d (linear) indexing into an array of any dimension in addition to the standard subscript access of e.g. (300,200,3)
  4 Comments
Adam
Adam on 6 Mar 2015
Wow, that is odd...we both corrected it to the same solution even to the naming of the intermediate variable!!

Sign in to comment.


David Young
David Young on 6 Mar 2015
Edited: David Young on 6 Mar 2015
One way, slightly fiddly but the simplest I can think of now:
[rowsB, colsB] = find(B);
C = zeros(size(B));
ind3 = 1; % index of the plane of A that is wanted
C(B) = A(sub2ind(size(A), rowsB, colsB, ind3*ones(size(rowsB))));

Sad Grad Student
Sad Grad Student on 6 Mar 2015
Does changing from D = A(:,:,1) to D = A(:,:,1).*B and then assign C(B) = D help? Or does it still give memory problems?

Tongyao Pu
Tongyao Pu on 6 Nov 2019
Hello,
I am a bit confused that you would like C to be 480*848.
I wonder if you would like to index each layer of A with logical matrix B? If that is the case, that is how I do it:
C = A;
B2 = repmat(B, [1,1,3]); % just copy B into a 480*848*3 array
C(B2) = 'something you would like it to be, e.g. NaN'

Community Treasure Hunt

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

Start Hunting!