To sort a matrix according to all columns except the first, I used the following code. I do not want sortrows to consider the first column because that is meant to keep track of the row numbers.
B = [1 1 0 0 0 0 0 0 0 1
2 0 1 0 0 0 0 1 0 0
3 0 0 1 0 1 0 0 1 0
4 0 1 0 0 0 1 1 0 0
5 0 0 1 0 0 0 0 1 0
6 0 0 0 0 0 1 1 0 0
7 1 0 0 1 0 0 0 0 0
8 0 0 1 0 1 0 0 0 0];
D = -sortrows(-B,[2:size(B,2)])
What if you want to sort the matrix according to all rows except the first, so the first element of each column would be ignored when sorting them in descending order? Is there any similar function to sortrows?
To clarify, the desired output is
1 0 0 0 0 0 0 1 0 1
2 1 1 0 0 0 0 0 0 0
3 0 0 1 1 1 0 0 0 0
4 1 1 0 0 0 1 0 0 0
5 0 0 1 1 0 0 0 0 0
6 1 0 0 0 0 1 0 0 0
7 0 0 0 0 0 0 1 1 0
8 0 0 1 0 1 0 0 0 0
You can do this via
transposing the input and output
keeping column 1 separate
you can use negative sort indices to avoid what you've done making the input and output negative
A = [B(:,1) sortrows( B(:,2:end).', -(2:size(B,1)) ).'];
>> A
A =
1 0 0 0 0 0 0 1 0 1
2 1 1 0 0 0 0 0 0 0
3 0 0 1 1 1 0 0 0 0
4 1 1 0 0 0 1 0 0 0
5 0 0 1 1 0 0 0 0 0
6 1 0 0 0 0 1 0 0 0
7 0 0 0 0 0 0 1 1 0
8 0 0 1 0 1 0 0 0 0
In the the matlab documentation there is this sentence about closing an image with imclose:
The morphological close operation is a dilation followed by an
erosion, using the same structuring element for both operations
I tried it out but the result is not the same. Can sombody tell me how I can close an image only with imdilate and imerode?
I = [0 0 0 0 0 0 0 0;
0 0 1 1 1 0 0 0;
0 0 0 1 1 1 0 0;
0 1 1 1 0 0 1 0;
0 0 1 0 0 1 1 0;
0 1 0 0 1 0 1 0;
0 0 1 0 1 0 1 0;
0 0 0 0 0 0 0 0];
Q = [0 1 0; 0 1 0; 0 1 1];
Q_n = [1 1 0; 0 1 0; 0 1 0];
J = imclose(I,Q)
D = imdilate(I,Q);
S = imerode(D,Q)
Closed result:
0 0 0 0 0 0 0 0
0 0 1 1 1 0 0 0
0 0 1 1 1 1 0 0
0 1 1 1 1 1 1 0
0 1 1 1 1 1 1 0
0 1 0 0 1 1 1 0
0 0 1 0 1 1 1 0
0 0 0 0 0 0 0 0
dilate and then erode:
0 0 1 1 1 0 0 0
0 0 1 1 1 0 0 0
0 0 1 1 1 1 0 0
0 1 1 1 1 1 1 0
0 1 1 1 1 1 1 0
0 1 0 0 1 1 1 1
0 0 1 0 1 1 1 1
0 0 1 0 1 1 1 1
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)
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
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