Reputation: 103
I have a binary matrix, say:
matrix=double(rand(100,100)>0.7);
I want to find all "diagonal lines" of 1's (from bottom left to top right) of length 2 or more elements in this matrix and set all other 1's to 0, so that I get another matrix with only those diagonal lines.
I want to do the same for vertical lines.
Is there a simple way to do this?
Upvotes: 0
Views: 751
Reputation: 65430
You can use 2D convolution combined with some fancy kernels to detect this. The basic idea is to craft a kernel that looks like the feature you're trying to detect.
First of all, there are two types of diagonals to detect:
We can design a kernel to detect that first type:
kernel = [1 0 0;
0 1 0;
0 0 1];
This is simply the identity matrix (eye(3)
), if we convole this with your input.
conv2(matrix, eye(3), 'same');
If we do this to the identity matrix as a test, we can see the result of the convolution
You can clearly see that the pixels that are part of the diagonal have values > 1. We can then convert this to a binary matrix indicating whether a pixel is along the diagonal. You also want to ensure that the current pixel is also 1.
is_top_left_to_bottom_right = conv2(matrix, eye(3), 'same') > 1 & logical(matrix);
In a similar way, we can flip the kernel to detect diagonals going the other way.
is_top_right_to_bottom_left = conv2(matrix, fliplr(eye(3)), 'same') > 1 & logical(matrix);
Then you can look at either independently or join them with a logical or
is_diagonal = is_top_left_to_bottom_right | is_top_right_to_bottom_left;
For horizontal and vertical lines you can use the following kernels in a similar way as the above (remember that I said at the beginning that you want the kernel to look like the feature you're trying to detect!).
horizontal = [0 0 0
1 1 1
0 0 0];
vertical = [0 1 0
0 1 0
0 1 0];
Upvotes: 1
Reputation: 36710
You can use conv2
to detect the lines:
% your data
M=double(rand(100,100)>0.7);
%length you want to detect
n=2;
kernel=eye(n);
%detect diagonal ones from top left to bottom right
lines=conv2(M,eye(n),'same')==sum(kernel(:));
For diagonals going the other direction, use kernel=fliplr(eye(n));
instead of kernel=eye(n);
For vertical and horizontal lines use kernel=ones(n,1);
or kernel=ones(1,n);
The kernels are matrices containing what you want to detect:
>> kernel=eye(n)
kernel =
1 0
0 1
>> kernel=fliplr(eye(n))
kernel =
0 1
1 0
>> kernel=ones(n,1)
kernel =
1
1
>> kernel=ones(1,n)
kernel =
1 1
Note that for the second diagonal the marked position might be a bit confusing, because convolution works with rectangles. Inputting
[0 0 0;
0 1 0;
1 0 0]
It will return:
[0 0 0;
1 0 0;
0 0 0]
Marking the top left of the rectangles where a diagonal was found. Now having code to identify the diagonals, again convolution can be used to create the intended matrix:
M=(conv2(double(conv2(M,kernel,'valid')==sum(kernel(:))),kernel,'full'))>0
Upvotes: 2