Reputation: 1596
Given a set of linear indexes of a matrix, how can I get only the adjacent indexes from it ?. By adjacent I meant the indexes which are either on the left, right, top, bottom or diagonal position of an index.
For example, given a 4*5 matrix
B = [1 0 0 0 0;
1 1 0 1 1;
0 0 1 0 1;
1 0 1 0 0;]
and the linear indices of B [1, 2, 4, 6, 11, 12, 14, 18, 19] (it corresponds to the indexes of non-zero entreies), how can I select only the one which have at least one neighbour ? In this case, my input is
[1, 2, 4, 6, 11, 12, 14, 18, 19]
I want the output to be
[1, 2, 6, 11, 12, 14, 18, 19]
as except 4, all others have neighbours in the index set.
Upvotes: 1
Views: 232
Reputation: 112729
You can use 2D-convolution to compute the number of non-zero neighbours of each entry, and use that as a logical mask:
result = find(B & conv2(B~=0, [1 1 1; 1 0 1; 1 1 1], 'same'));
Upvotes: 3
Reputation: 14336
The bwconncomp
function from the Image Processing Toolbox returns connected components in binary images. As your matrix is a binary image, i.e. a 2-D matrix containing zeros and ones, we can use this.
Calling the function
>> CC = bwconncomp(B);
returns a struct containing (among other fields) PixelIdxList
, which is a cell array, where each element is an array of pixel indices corresponding to a specific connected component. In your case, this is:
>> CC.PixelIdxList
ans =
1×2 cell array
{8×1 double} {[4]}
So you have two connected components: one consisting of 8 pixels, with indices given by CC.PixelIdxList{1}
, and a second one containing 1 pixel with index 4
.
As you want to remove all pixels that have no neighbors, you can check all elements of CC.PixelIdxList
for their number of elements and remove all with only one elements:
>> numPixels = cellfun(@numel,CC.PixelIdxList);
>> toRemove = (numPixels == 1);
This gives us an array toRemove
containing a 0
for each connected component we want to keep, and a 1
for each connected component we want to remove. Finally, you can concatenate all connected components you want to keep into a single array with
>> allIdx = CC.PixelIdxList(~tooSmall);
>> allIdx = allIdx{:};
which leaves us with the desired result
>> allIdx
allIdx =
1
2
6
11
12
14
18
19
Upvotes: 0