how can i change value of 3d matrix where it has zero in all layer in matlab? - matlab

assume that i got matrix ,called mat.
mat(:,:,1) =
0 1 0 1 0
1 0 1 1 0
1 0 1 0 1
1 1 1 1 0
0 0 1 1 1
mat(:,:,2) =
1 1 0 1 1
0 1 1 0 1
0 1 1 0 1
1 0 1 1 1
0 0 0 0 0
mat(:,:,3) =
1 0 0 1 1
1 1 0 0 0
1 1 1 1 0
0 1 0 0 0
0 0 0 0 1
i want to change value in each layer where it has zero in all 3 layers.
mat_result(:,:,1) =
0 1 -1 1 0
1 0 1 1 0
1 0 1 0 1
1 1 1 1 0
-1 -1 1 1 1
mat_result(:,:,2) =
1 1 -1 1 1
0 1 1 0 1
0 1 1 0 1
1 0 1 1 1
-1 -1 0 0 0
mat_result(:,:,3) =
1 0 -1 1 1
1 1 0 0 0
1 1 1 1 0
0 1 0 0 0
-1 -1 0 0 1
First, i find the position
ind = find(mat(:,:,1)==0 & mat(:,:,2)==0 & mat(:,:,3)==0)
ind =
5
10
11
In the simple way, i do this
matt1 = mat(:,:,1);
matt2 = mat(:,:,2);
matt3 = mat(:,:,3);
matt1(ind) = -1;
matt2(ind) = -1;
matt3(ind) = -1;
mat_result = cat(3,matt1,matt2,matt3);
My question is
Is there a better ways to choose/change submatrix of submatrix?
for example(but it didn't work):
mat(:,:,1)(mat(:,:,1)==0 & mat(:,:,2)==0 & mat(:,:,3)==0) = -1;
Is there a shorter way to change value in each layer where it has zero in all 3 layers?

mat(repmat(~any(mat,3),[1,1,3]))=-1
Instead of using mat(:,:,1)==0 & mat(:,:,2)==0 & mat(:,:,3)==0 you may use the any function.

Use the repmat function to replicate the logical matrix you get by using
mat(:,:,1)==0 & mat(:,:,2)==0 & mat(:,:,3)==0.
Replicate it along the 3rd channel. Final statement is:
mat(repmat(mat(:,:,1)==0 & mat(:,:,2)==0 & mat(:,:,3)==0,[1 1 3]))=-1

Related

What matlab command, or combination of commands (using 25 characters or less), could be used to create the following matrix?

What matlab command, or combination of commands (using 25 characters or less), could be used to create the following matrix?
1 0 0 0 0 1 0 0 0 0
1 1 0 0 0 1 1 0 0 0
1 1 1 0 0 1 1 1 0 0
1 1 1 1 0 1 1 1 1 0
1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 1 0 0 0 0
1 1 0 0 0 1 1 0 0 0
1 1 1 0 0 1 1 1 0 0
1 1 1 1 0 1 1 1 1 0
1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 1 0 0 0 0
1 1 0 0 0 1 1 0 0 0
1 1 1 0 0 1 1 1 0 0
1 1 1 1 0 1 1 1 1 0
1 1 1 1 1 1 1 1 1 1
Hint: Look for a lower triangluar matrix that is repeated many times. First try to produce that lower triangular matrix with as few characters as possible.
You can use the following code:
A = ones(5); % create 5x5 matrix with all elements 1
B = tril(A); % return the lower triangle matrix of A
C = repmat(B, 3, 2); % repeat the matrix B, 3 times in a row and 2 times in a cloumn as you want.
In more details:
A = ones(5);
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
B = tril(A);
1 0 0 0 0
1 1 0 0 0
1 1 1 0 0
1 1 1 1 0
1 1 1 1 1
C = repmat(B, 3, 2);
1 0 0 0 0 1 0 0 0 0
1 1 0 0 0 1 1 0 0 0
1 1 1 0 0 1 1 1 0 0
1 1 1 1 0 1 1 1 1 0
1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 1 0 0 0 0
1 1 0 0 0 1 1 0 0 0
1 1 1 0 0 1 1 1 0 0
1 1 1 1 0 1 1 1 1 0
1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 1 0 0 0 0
1 1 0 0 0 1 1 0 0 0
1 1 1 0 0 1 1 1 0 0
1 1 1 1 0 1 1 1 1 0
1 1 1 1 1 1 1 1 1 1
A solution using rempat and implicit expansion:
repmat(1:5<(2:6)',3,2)

Filter islands based on length in a binary array - MATLAB

I have a binary array and I would like to flip values based on the length which they repeat. as an example
Ar = [0 1 0 0 0 1 1 0 0 0 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1];
Ideally I would like to flip the 1's which repeat only 2 or fewer times resulting in the following.
Ar = [0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1];
From what I have located online, the Diff function is most commenly used to locate and remove sequences. But from what I have located, it appears to target all instances.
Simply use imopen from Image Processing toolbox with a kernel of 3 ones -
imopen(Ar,[1,1,1])
Sample run -
>> Ar = [0 1 0 0 0 1 1 0 0 0 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1];
>> out = imopen(Ar,[1,1,1]);
>> [Ar(:) out(:)]
ans =
0 0
1 0
0 0
0 0
0 0
1 0
1 0
0 0
0 0
0 0
1 1
1 1
1 1
1 1
1 1
0 0
0 0
0 0
0 0
1 1
1 1
1 1
1 1
1 1
1 1
Vectorized solution without using I.P. toolbox -
function out = filter_islands_on_length(Ar, n)
out = Ar;
a = [0 Ar 0];
d = diff(a);
r = find(d);
s0 = r(1:2:end);
s1 = r(2:2:end);
id_arr = zeros(1,numel(Ar));
m = (s1-s0) <= n;
id_arr(s0(m)) = 1;
id_arr(s1(m)) = -1;
out(cumsum(id_arr)~=0) = 0;
Sample runs -
>> Ar
Ar =
0 1 0 0 0 1 1 0 0 0 1 1 1
>> filter_islands_on_length(Ar, 2)
ans =
0 0 0 0 0 0 0 0 0 0 1 1 1
>> filter_islands_on_length(Ar, 1)
ans =
0 0 0 0 0 1 1 0 0 0 1 1 1
Another solution requiring no toolbox but needs Matlab 2016a or later:
n = 3; % islands shorter than n will be removed
Ar = movmax(movsum(Ar,n),[ceil(n/2-1) floor(n/2)])==n;

Matlab how to bitwise-AND of a vector and a matrix?

I want to find out the index of the matrix column in which the vector appears. My idea is to do AND of the vector over matrix and only the column that is the same will be 1 in the new vecotr. But I don't know how to do this. Below is example:
H =
0 0 0 0 1 1 1 1 1 1 1 1 0 0 0
0 1 1 1 0 0 0 1 1 1 1 0 1 0 0
1 0 1 1 0 1 1 0 0 1 1 0 0 1 0
1 1 0 1 1 0 1 0 1 0 1 0 0 0 1
S =
0 1 0 1
From that I want to get 2 as second column or even better vector
0 1 0 0 0 0 ... 0
Since there is error in second column.
How can I do this in Matlab or even better Octave?
Not really sure how you tried to approach the problem. But with repmat or bsxfun it is as simple as this:
all(bsxfun(#eq,H,S'))
How about
result = sum(H==repmat(S(:),[1 size(H,2)]))==4;
I found out the function
ismember(H', S, "rows")
works exactly as I want. Your answers are all good too, thanks.
That's pretty easy with broadcasting. The following will require Octave 3.6.0 or later but you can use bsxfun if you have a previous version:
octave-cli-3.8.1> h = logical ([
0 0 0 0 1 1 1 1 1 1 1 1 0 0 0
0 1 1 1 0 0 0 1 1 1 1 0 1 0 0
1 0 1 1 0 1 1 0 0 1 1 0 0 1 0
1 1 0 1 1 0 1 0 1 0 1 0 0 0 1]);
octave-cli-3.8.1> s = logical ([0 1 0 1]');
octave-cli-3.8.1> all (h == s)
ans =
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
From here, it's all a matter of using find to get the column numbers. It will even work if it matches more than 1 column:
octave-cli-3.8.1> find (all (h == s))
ans = 2

Grouping logical data in Matlab

I have a matrix that contains data of 0 & 1. I want to find groups of ones (not a specific size) in that matrix. Is it possible somehow?
Thanks in advance!
If you mean that you want to find all the "connected components in the matrix, say BW, simply use:
BW = logical([1 1 1 0 0 0 0 0
1 1 1 0 1 1 0 0
1 1 1 0 1 1 0 0
1 1 1 0 0 0 1 0
1 1 1 0 0 0 1 0
1 1 1 0 0 0 1 0
1 1 1 0 0 1 1 0
1 1 1 0 0 0 0 0]);
L = bwlabel(BW,4) %Result
This would yeild:
L =
1 1 1 0 0 0 0 0
1 1 1 0 2 2 0 0
1 1 1 0 2 2 0 0
1 1 1 0 0 0 3 0
1 1 1 0 0 0 3 0
1 1 1 0 0 0 3 0
1 1 1 0 0 3 3 0
1 1 1 0 0 0 0 0
Now if you want to find the size of various groups:
for ii=1:max(L(:))
length_vector(ii)=length(find(L==ii));
end
length_vector
This gives you:
length_vector =
24 4 5

converting matrix into cell in matlab [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I have a 2 d matrix like this:
0 0 0 0 0 0
0 0 0 0 0 1
0 0 0 0 1 0
0 0 0 0 1 1
0 0 0 1 0 0
0 0 0 1 0 1
0 0 0 1 1 0
0 0 0 1 1 1
0 0 1 0 0 0
0 0 1 0 0 1
0 0 1 0 1 0
0 0 1 0 1 1
0 0 1 1 0 0
0 0 1 1 0 1
0 0 1 1 1 0
0 0 1 1 1 1
0 1 0 0 0 0
0 1 0 0 0 1
0 1 0 0 1 0
0 1 0 0 1 1
0 1 0 1 0 0
0 1 0 1 0 1
0 1 0 1 1 0
0 1 0 1 1 1
0 1 1 0 0 0
0 1 1 0 0 1
0 1 1 0 1 0
0 1 1 0 1 1
0 1 1 1 0 0
0 1 1 1 0 1
0 1 1 1 1 0
0 1 1 1 1 1
1 0 0 0 0 0
1 0 0 0 0 1
1 0 0 0 1 0
1 0 0 0 1 1
1 0 0 1 0 0
1 0 0 1 0 1
1 0 0 1 1 0
1 0 0 1 1 1
1 0 1 0 0 0
1 0 1 0 0 1
1 0 1 0 1 0
1 0 1 0 1 1
1 0 1 1 0 0
1 0 1 1 0 1
1 0 1 1 1 0
1 0 1 1 1 1
1 1 0 0 0 0
1 1 0 0 0 1
1 1 0 0 1 0
1 1 0 0 1 1
1 1 0 1 0 0
1 1 0 1 0 1
1 1 0 1 1 0
1 1 0 1 1 1
1 1 1 0 0 0
1 1 1 0 0 1
1 1 1 0 1 0
1 1 1 0 1 1
1 1 1 1 0 0
1 1 1 1 0 1
1 1 1 1 1 0
1 1 1 1 1 1
I want to convert this matrix into something like the following:
100000
100001
100010
and so on...
The answer from #Shai might be what you are looking for, but I read your question to ask about how to concatenate the rows of the matrix to form a vector.
It then depends on what type of format you want for your output, but here is one way to get a vector of numbers instead of the matrix.
>> A = eye(3)
A =
1 0 0
0 1 0
0 0 1
Convert the matrix into string:
>> B = num2str(A)
B =
1 0 0
0 1 0
0 0 1
Extract the chars that correspond to digits (and leave out the spaces):
>> C = B(:,1:3:end)
C =
100
010
001
Here you've got your values as strings which might be what you want (even if it is not really a vector). You could also convert this back to numbers, but then you will get an output of the following kind:
>> D = str2num(C)
D =
100
10
1
Try mat2cell
c = mat2cell( x, ones(1, size(x,1)), size(x,2) );
Though, from your example, it seems like you are more interested in dec2bin:
n = 6; % all binary numbers with n bits
c = dec2bin( 0:(2^n - 1), n );