Distance between connected components - matlab

I wanted to know if there is some inbuilt function to get distance between different connected components in MATLAB. I am using bwlabel to get the various connected components.Is there some way to get the distance between these connected components?

I guess you could use regionprops to locate the centroid of each connected component and then apply pdist to find the pairwise distance between each of them.
Simple example:
clear
clc
close all
%// Create logical array
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])
%/ Call regionprops and concatenate centroid coordinates
S = regionprops(bwlabel(BW,4),'Centroid')
Centroids = vertcat(S.Centroid)
%// Measure pairwise distance
D = pdist(Centroids,'euclidean')
Outputs in the Command Window:
BW =
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
S =
3x1 struct array with fields:
Centroid
Centroids =
2.0000 4.5000
5.5000 2.5000
6.8000 5.8000
D =
4.0311 4.9729 3.5468

Related

perimeter of periodic binary matrix (in matlab)

I have a periodic binary matrix which includes a block of ones. I need to find the boundary between zeros and ones in the matrix. Here is an example:
A=[0,1,1,1,0,0,0,1,1;
0,0,0,0,1,1,1,1,0;
0,0,0,0,1,1,1,1,0;
0,0,0,0,1,1,1,1,0;
0,1,1,1,1,1,1,0,0;
0,1,1,1,1,1,1,0,0;
0,1,1,1,0,0,0,0,0;
0,1,1,1,0,0,0,0,0;
0,1,1,1,0,0,0,0,0]
If the matrix was not periodic, I could use
perim=bwperim(A);
to find the perimeter. But this does not work perfectly for periodic matrices. I appreciate it if someone can help me with this problem.
EDIT:
a periodic matrix is a matrix that its boundary elements are connected to the boundary elements on the other side of the matrix.
You can pad the image on each side with the column/row that it's connected to. For example, the left edge will be padded with the rightmost column. Then use bwperim, and trim one row/column from each side of the result.
A = [0 1 1 1 0 0 0 1 1;
0 0 0 0 1 1 1 1 0;
0 0 0 0 1 1 1 1 0;
0 0 0 0 1 1 1 1 0;
0 1 1 1 1 1 1 0 0;
0 1 1 1 1 1 1 0 0;
0 1 1 1 0 0 0 0 0;
0 1 1 1 0 0 0 0 0;
0 1 1 1 0 0 0 0 0];
padded_A = [0 A(end,:) 0;
A(:,end) A A(:,1);
0 A(1,:) 0];
padded_perim = bwperim(padded_A);
perim = padded_perim(2:end-1,2:end-1);
Result:
perim =
0 1 1 1 0 0 0 1 1
0 0 0 0 1 1 1 1 0
0 0 0 0 1 0 0 1 0
0 0 0 0 1 0 0 1 0
0 1 1 1 0 0 1 0 0
0 1 0 0 1 1 1 0 0
0 1 0 1 0 0 0 0 0
0 1 0 1 0 0 0 0 0
0 1 0 1 0 0 0 0 0
You can use conv2 and padarray to find the perimeter:
4-connected:
perim = A & conv2(padarray(A, [1 1], 'circular'), [0 1 0;1 0 1;0 1 0], 'valid') < 4;
8-connected:
perim = A & conv2(padarray(A, [1 1], 'circular'), [1 1 1;1 0 1;1 1 1], 'valid') < 8;
Using the definition of the perimeter:
A pixel is part of the perimeter if it is nonzero and it is connected to at least one zero-valued pixel.
Use A & ... to ensure that the pixel is nonzero. The boundary pixels are replicated using padarray with option 'circular'. The padded array is convolved with the connectivity mask. use conv2 with option 'valid' to trim the replicated boundary pixels. If it is less than 4 or 8 it means that it is connected to at least one zero-valued pixel.

What is the result of dilation of this image?

I have this following matrix:
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
1 1 0 0 0 0 0
1 0 0 0 0 1 1
1 0 0 0 0 1 1
And I want to dilate it with the following structuring element:
1 0 0
1 1 1
1 1 1
I already did dilation on Matlab but the result does not match with the one I did by hand. So I guess I missing something here. As far as I know if any '1' of the structuring element touches any of the '1' in the matrix, then it means it is a hit and the center of the current window should be set as 1. If I make dilation in such fashion I would get following (without considering edges):
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 1 1 0 0 0 0
1 1 1 0 1 1 0
1 1 1 0 1 1 1
1 0 0 0 0 1 1
But Matlab gives the following result:
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
1 **0** **0** 0 0 0 0
1 1 1 0 1 1 0
1 1 1 0 1 1 1
1 1 0 0 1 1 1
Without considering edges it almost looks like my result but pixels styled with bold are '1' in my result but '0' in Matlab's result. What am I doing wrong? Pixel just below those '0's are '1's in the original image and the structuring element has '1' at that space when the center of the window is on those '0's so it is a hit and the center must be set '1' but Matlab doesn't do this. Can anyone explain me why? Am I missing something essential here?
Suppose matrix A is your image and matrix B is structuring element. You should pad the matrix A with zeroes on all sides. So let's say you have matrix C. Then you should perform Logical AND operation of C and B. The result matrix called D will be a dilated matrix. For further information, please see here.
Here is the code of Matlab which dilate image without 'imdilate' function:
clc;clearvars;close all;
%Image Dilation without using 'imdilate' function
% Matrix A is our image
A=[0 0 0 0 0 0 0;
0 0 0 0 0 0 0;
0 0 0 0 0 0 0 ;
0 0 0 0 0 0 0;
1 1 0 0 0 0 0;
1 0 0 0 0 1 1 ;
1 0 0 0 0 1 1 ];
%Structuring element
B=[1 0 0; 1 1 1; 1 1 1];
%Pad zeros on all the sides
C=padarray(A,[1 1]);
%Intialize a matrix of matrix size A with zeros
D=false(size(A));
for i=1:size(C,1)-2
for j=1:size(C,2)-2
%Perform logical AND operation
D(i,j)=sum(sum(B&C(i:i+2,j:j+2)));
end
end
display(D);
And this is my output, dilated matrix D:

How to perform logical AND operation by refering the coordinates in matrix [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
The matrix A contains 1's in different coordinates:
A =
1 0 0 0 1 0 0 0 0 0
0 1 0 0 0 1 0 0 1 0
0 0 1 0 0 0 1 0 0 1
0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0
Step 1:
Finding the coordinates of the 1's. For example, in the first row it is (1,1) and (1,5).
c1 = find(A==1)
Step 2:
Scanning this coordinates in Main M matrix and performing AND operation. If the answer is 1 then place the 1 in corresponding coordinates of A matrix. For example, (1,1) (1,5) in M matrix is ANDed with (2,1)(2,5)==> 1 1 ANDed 0 0 ==>0 0. Likewise (3,1) (3,5) upto (10,1) (10,5) in M matrix. If any place 1 it came place the 1 in respective coordinate place in A matrix.
M =
1 0 0 0 1 1 1 1 1 1
0 1 0 0 0 1 1 1 1 1
0 0 1 0 1 1 1 1 1 1
0 0 0 1 0 0 0 0 1 1
1 0 1 0 1 0 0 0 0 0
1 1 1 0 0 1 0 0 1 1
1 1 1 0 0 0 1 0 1 1
1 1 1 0 0 0 0 1 0 0
1 1 1 1 0 1 1 0 1 0
1 1 1 1 0 1 1 0 0 1
Here in the given matrix in 4th row A matrix has 1 in (4,4) check the remaining coordinates in M matrix. It is ANDed with (1,4) the (2,4), while (9,4) it is 1. Place that 1 in A matrix (4,9). I have tried with the code but it is not working in generic case.
a = 1:size(M)
R1 = 1;
for j = 1:size(A)
A1 = A(j,:)
c = find(A1==1) % finding 1's place
l = length(c)
a1 = a(a~=j)
for k = a1(1):a1(end)
R1 = 1;
for i = 1:l1
temp1 = R1
R1 = and(M(j,c(i)),M(k,c(i))) % performing AND operations
R2 = and(R1,temp1)
end
if (R2==1) % if the condition is satisfied by 1
A(j,k)=1 % place the 1 in the particular coordinate in A matrix
end
end
end
New_A = A
New_A =
1 0 0 0 1 0 0 0 0 0
0 1 0 0 0 1 0 0 1 0
0 0 1 0 0 0 1 0 0 1
0 0 0 1 0 0 0 0 1 0
1 0 0 0 0 0 0 1 0 0
If I understand your question, then for each row r of A you want to extract all M columns where A(r,:)==1, then place 1 in first column c of A(r,:) that all the columns in row c in the extracted M is 1. Using the updated A continue the process on the same row until you reach the end, and move to the next row.
Here is a code for that (assuming size(A,1)==size(M,2)):
new_A = A; % copy the current state
for r = 1:size(new_A,1)
Mc = M(:,new_A(r,:)==1).'; % extract the relevat columns in new_A
c = 1; % column counter
while c<=size(A,2)
next_item = find(all(Mc(:,c:end),1),1)+c-1; % find the next item to change
new_A(r,next_item) = 1; % if all rows in Mc are 1, then place 1
Mc = M(:,new_A(r,:)==1).'; % extract the relevat columns in new_A
c = c+1; % go to the next column
end
end
which result in new_A using your A and M above:
new_A =
1 0 0 0 1 0 0 0 0 0
0 1 0 0 0 1 0 0 1 0
0 0 1 0 0 0 1 0 0 1
0 0 0 1 0 0 0 0 1 0
1 0 0 0 0 0 0 1 0 0
Is this what you looked for?

solving binary linear equation in matlab

Consider a binary linear equation of form x*A = b. I want to solve for x, the efficiency way is by avoiding using x = b*inv(A) and instead using x= b/A.But with this command results are not in binary form. I tried the command x = mod(b/A ,2)but still result was not in binary. How to fix this?
example
`
x = 1 0 1 1 0 0 0 1 1 0`
and matrix A is
`0 1 0 1 0 0 1 1 1 1
0 1 1 1 1 1 1 1 0 1
0 0 1 0 1 1 0 1 1 1
1 0 0 1 1 1 1 1 1 1
1 1 0 0 1 1 0 0 0 0
0 1 1 1 0 1 1 0 1 0
0 0 1 1 0 0 0 1 0 0
1 1 1 1 0 1 0 1 1 1
1 0 1 0 1 1 1 0 1 1
1 1 1 0 0 0 1 1 0 0`
which is full rank.
then
>> b = mod (x*A,2)
b =
1 0 1 1 1 0 1 0 1 1
To find x, am getting
>> k = b / A
k =
Columns 1 through 6
1.3750 -0.5000 -0.7500 -0.7500 0.8750 -0.5000
Columns 7 through 10
1.8750 -0.5000 2.1250 -0.7500
or if am using modulus 2, the result is
>> k = mod (b / A,2)
k =
Columns 1 through 6
1.3750 1.5000 1.2500 1.2500 0.8750 1.5000
Columns 7 through 10
1.8750 1.5000 0.1250 1.2500
So ,how can I get x in the same binary form? and by the way matrices are all in class double not galois field
This example at Mathworks shows how to perform boolean matrix inversion with MATLAB and I believe answers your question.
I have not quite gotten it working perfectly, but I believe you need to use a combination of mod() and logical() for example:
A=logical(A);
b=(mod(x*A,2));
inverseA= ~A;
k=mod(b*inverseA,2)
this gives
k=[1 1 0 0 1 1 0 1 0 0]
which is not x, but i think if you play around with the logical function and logical operations in conjunction with mod() you should be able to get it to work
To solvexin binary form, matrix A should be in galois field.
consider the following example;
>> x = randi ([0 1],1,10)
x =
1 1 0 1 1 1 0 1 1 1
>> A = gf (randi([0 1],10,10))
A = GF(2) array.
Array elements =
Columns 1 through 6
1 1 1 0 0 1
1 0 1 0 1 0
1 0 1 1 0 1
0 0 0 0 0 1
1 1 1 0 1 1
0 1 0 1 0 1
0 0 0 1 1 1
0 1 0 0 1 0
0 0 1 0 1 0
0 0 1 0 0 1
Columns 7 through 10
1 1 0 0
1 0 1 1
1 1 0 0
0 0 1 0
1 1 1 1
0 1 1 1
1 0 1 0
1 1 1 0
1 0 0 0
1 1 1 0
then,
>> b = x*A
b = GF(2) array.
Array elements =
Columns 1 through 6
1 0 1 1 0 1
Columns 7 through 10
0 1 0 1
>> x_solved = b*inv (A)
x_solved = GF(2) array.
Array elements =
Columns 1 through 6
1 1 0 1 1 1
Columns 7 through 10
0 1 1 1
As you can see x_solved is the same as the original x. Therefore you should convert matrix A to galois field by just running a codeA = gf(A).

generating combinations in Matlab

I have a column vector x made up of 4 elements, how can i generate all the possible combinations of the values that x can take such that x*x' is less than or equal to a certain value?
note that the values of x are positive and integers.
To be more clear:
the input is the number of elements of the column vector x and the threshold, the output are the different possible combinations of the values of x respecting the fact that x*x' <=threshold
Example: threshold is 4 and x is a 4*1 column vector.....the output is x=[0 0 0 0].[0 0 0 1],[1 1 1 1]......
See if this works for you -
threshold = 4;
A = 0:threshold
A1 = allcomb(A,A,A,A)
%// Or use: A1 = combvec(A,A,A,A).' from Neural Network Toolbox
combs = A1(sum(A1.^2,2)<=threshold,:)
Please note that the code listed above uses allcomb from MATLAB File-exchange.
Output -
combs =
0 0 0 0
0 0 0 1
0 0 0 2
0 0 1 0
0 0 1 1
0 0 2 0
0 1 0 0
0 1 0 1
0 1 1 0
0 1 1 1
0 2 0 0
1 0 0 0
1 0 0 1
1 0 1 0
1 0 1 1
1 1 0 0
1 1 0 1
1 1 1 0
1 1 1 1
2 0 0 0