Anıl
Anıl

Reputation: 54

Octave value replacement with logical indexing on multidimensional matrices

I have a matrix named IMG, it is a n * m * 3 shaped matrix (an hsv image). What I am trying to achieve is

IF IMG(x, y, 1) < 1/2
THEN IMG(X, Y, 2) = 0.

Logical indexing looks like a solution but with that way we can only access the condition index (IMG(x, y, 1)). With the code below I am changing first indices of the pixels but I want to change second one.

IMG( IMG(:, :, 1) > 1/2 ) = 0;

Thanks for your help.

Upvotes: 3

Views: 269

Answers (3)

Nick J
Nick J

Reputation: 1630

looking for another one-line solution without any intermediate holding variable, the following was proposed for a multi-dimensional array on the Octave Help list:

a( (a(:,:,3)<.5) & shiftdim(1:size(a,3)==2,-1) ) = 0

for example:

>> a = rand(2,3,3)
a =

ans(:,:,1) =

   0.63416   0.28912   0.33463
   0.76642   0.51474   0.28130

ans(:,:,2) =

   0.99748   0.26000   0.45671
   0.73153   0.44499   0.24099

ans(:,:,3) =

   0.94726   0.77252   0.12698
   0.27069   0.46458   0.55833

>> a( (a(:,:,3)<.5) & shiftdim(1:size(a,3)==2,-1) ) = 0
a =

ans(:,:,1) =

   0.63416   0.28912   0.33463
   0.76642   0.51474   0.28130

ans(:,:,2) =

   0.99748   0.26000   0.00000
   0.00000   0.00000   0.24099

ans(:,:,3) =

   0.94726   0.77252   0.12698
   0.27069   0.46458   0.55833

Upvotes: 0

Cris Luengo
Cris Luengo

Reputation: 60695

One simple solution is to extract the whole plane, modify it, then put it back:

s = IMG(:, :, 2);
s(IMG(:, :, 1) > 1/2) = 0;
IMG(:, :, 2) = s;

It is also possible to play around with linear indices, which is more generic, but also more complex:

index = find(IMG(:, :, 1) > 1/2);
offset = size(IMG, 1) * size(IMG, 2);
IMG(index + offset) = 0;

Upvotes: 4

rahnema1
rahnema1

Reputation: 15867

You can multiply the image by a mask:

IMG(:, :, 2) = IMG(:, :, 2) .* (IMG(:, :, 1) <= (1/2)) ;

Or use compound assignment:

IMG(:, :, 2) .*= IMG(:, :, 1) <= (1/2);

Another fast option is reshaping the array:

sz =size(IMG) ;
IMG = reshape(IMG, [], 3);
IMG(IMG(:,1)>1/2, 1), 2) = 0;
IMG = reshape(IMG, sz) ;

Other, possibly less efficient, option is using ifelse :

IMG(:, :, 2) = ifelse(IMG(:, :, 1) > 1/2, 0, IMG(:, :, 2) ) ;

Upvotes: 3

Related Questions