How to find local maxima in an image

Question about the concept of object detection. I am stuck after finding the corner of an image and I want to know how to find a point within the calculated angles.

Suppose I have a grayscale image that has data like this

A = [ 1 1 1 1 1 1 1 1;
      1 3 3 3 1 1 4 1;
      1 3 5 3 1 4 4 4;
      1 3 3 3 1 4 4 4; 
      1 1 1 1 1 4 6 4;
      1 1 1 1 1 4 4 4]

      

if i use

B = imregionalmax(A);

      

the result will be like this:

B = [ 0 0 0 0 0 0 0 0;
      0 1 1 1 0 0 1 0;
      0 1 1 1 0 1 1 1;
      0 1 1 1 0 1 1 1;
      0 0 0 0 0 1 1 1;
      0 0 0 0 0 1 1 1]

      

The question is, how do I select the highest peak within the maximum local area (in the example, how I chose 5 out of 3 and 6 out of 4)?

My idea was to use B to detect each region and use it again imregionalmax()

, but I am not good at coding and need advice or other ideas.

+1


source to share


2 answers


There are several other simple ways to implement a 2D peak finder: ordfilt2

or imdilate

.

ordfilt2

The most direct method is to use ordfilt2

that sorts the values ​​in local neighborhoods and picks the nth value. (The MathWorks example demonstrates how to implement a maximum filter.) You can also implement a 3x3 peak finder with ordfilt2

by, (1) using a 3x3 domain that does not include the center pixel, (2) selecting the largest (8th) value, and (3) compared to the central value:

>> mask = ones(3); mask(5) = 0 % 3x3 max
mask =
     1     1     1
     1     0     1
     1     1     1

      

There are 8 values ​​taken into account in this mask, so the 8th value is max. Filter output:

>> B = ordfilt2(A,8,mask)
B =
     3     3     3     3     3     4     4     4
     3     5     5     5     4     4     4     4
     3     5     3     5     4     4     4     4
     3     5     5     5     4     6     6     6
     3     3     3     3     4     6     4     6
     1     1     1     1     4     6     6     6

      



The trick is compared to A

, the center value of each neighborhood:

>> peaks = A > B
peaks =
     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     0     0     0     0     0     0     0
     0     0     0     0     0     0     1     0
     0     0     0     0     0     0     0     0

      

imdilate

Image dilation is usually done on binary images, but grayscale decorating is just a max filter (see the Definitions section of the imdilate

docs) The same trick used with ordfilt2

applies here: define a neighborhood that does not include a central neighborhood pixel, apply filter and compare with unfiltered image:

B = imdilate(A, mask);
peaks = A > B;

      

NOTE . These methods only detect one pixel peak. If any neighbors have the same value, this will not be a peak.

+3


source


The imregionalmax function gives you an 8-connected area containing at most and its 8 neighbors (i.e. the 3x3 areas you are seeing). Then you could use morphological operations with the same 3x3 building block to trim those regions at their centers. For example.

 B = imregionalmax(A);
 C = imerode(B, ones(3));

      

or equivalent

 B = imregionalmax(A);
 D =  bwmorph(B, 'erode');

      



Alternatively, you can write your own maximum search function using block processing :

 fun = @(block) % your code working on 'block' goes here ...
 B = blockproc(A, ones(3), fun)

      

But it will most likely be slower than the built-in functions. (I don't have the toolkit right now, so I can't try this.)

Also take a look here and here .

+1


source







All Articles