Question

Say I have the following matrix:

1   6   7   8   9
3   7   6   8   9
8   7   6   5   0
2   8   7   6   5
2   9   6   8   2

I want to find the k-nearest neighbors for a specific element in the matrix

So for example if I want the nearest neighbors of [3,3] with a spatial neighborhood of 5x5, the function would return the entire matrix, and a 3x3 neighborhood would return [7 6 8 7 6 5 8 7 6].

I can do this with direct indexing with the rows and columns but this becomes impractical as the neighborhood becomes larger. Is there a faster way to do this? I have looked over some filters like nlfilter and colfilter but they seem to process the entire matrix, whereas I only want to process a specific element.

Was it helpful?

Solution 2

Neglecting edge conditions this is a simple case of subscript indexing:

r = 3;
c = 3;
n = 4;

M = magic(10);

sub = M((r-n):(r+n), (c-n):(c+n))

where r is your target points row number, c is it's columns number and n is the neighbourhood size. This will work expect for edge cases but we can handle that like this:

sub = M(max((r-n), 1):min((r+n), end), max((c-n),1):min((c+n),end))

if instead of starting at row r-n, which could be less than 1, rather start at the larger of either r-n or 1. Then to stop going past the end just choose the smaller of either r+n or end.

OTHER TIPS

You can either use this method to extract a submatrix from it or make an offset mask, take 3x3 neighbors as an example:

s=size(yourmatrix);
N=length(s);
[c1{1:N}]=ndgrid(1:3);
c2(1:N)={2};
offsets=sub2ind(s,c1{:}) - sub2ind(s,c2{:})

Now, for any linear index in your matrix L, you can get all its neighbors by doing

neighbors = yourmatrix(L+offsets)

It won't work at the edges of the matrix, but you can take care of that by padding the edges first.


I think you need an example to see what this method is doing. Suppose yourmatrix is

yourmatrix =
   1     6    11    16
   2     7    12    17
   3     8    13    18
   4     9    14    19
   5    10    15    20

When you run my code on this small example, you should obtain

offsets =
-6    -1     4
-5     0     5
-4     1     6

So, now, if I want the neighborhood centered at the "14", I would do

>> yourmatrix(14+offsets)
ans =
     8    13    18
     9    14    19
    10    15    20

Check out here for more info.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top