Non local maxima suppression in python

10,512

Solution 1

This may not be entirely correct, but it works better on a small test case

def nonMaximalSupress1(image,NHoodSize):
    #
    dX, dY = NHoodSize
    M, N = image.shape
    for x in range(0,M-dX+1):
        for y in range(0,N-dY+1):
            window = image[x:x+dX, y:y+dY]
            if np.sum(window)==0:
                localMax=0
            else:
                localMax = np.amax(window)
            maxCoord=np.unravel_index(np.argmax(window), window.shape) + np.array((x,y))
            #suppress everything
            image[x:x+dX, y:y+dY]=0
            #reset only the max
            if localMax > 0:
                print localMax
                print "max coord is ", maxCoord
            image[tuple(maxCoord)] = localMax
    return image

I've used local variables to make things easier to read, and tweaked the loop ranges. But the big change is in how I index image. Especially when indexing with slices, you must use one set of brackets.

image[x:x+dX, y:y+dY] is the correct way to select a window, not image[x:x+dX][y:y+dY].

It can be cleaned up a bit more by modifying the window. Since it is a view, changing it changes image.

def nonMaximalSupress2(image,NHoodSize):
    #
    dX, dY = NHoodSize
    M, N = image.shape
    for x in range(0,M-dX+1):
        for y in range(0,N-dY+1):
            window = image[x:x+dX, y:y+dY]
            if np.sum(window)==0:
                localMax=0
            else:
                localMax = np.amax(window)
            maxCoord = np.argmax(window)
            # zero all but the localMax in the window
            window[:] = 0
            window.flat[maxCoord] = localMax
    return image

Solution 2

How about something like this:

# Use the max filter to make a mask
roi = 3
size = 2 * roi + 1
image_max = ndimage.maximum_filter(image, size=size, mode='constant')
mask = (image == image_max)
image *= mask

# Remove the image borders
image[:roi] = 0
image[-roi:] = 0
image[:, :roi] = 0
image[:, -roi:] = 0

# Optionally find peaks above some threshold
image_t = (image > peak_threshold) * 1

# get coordinates of peaks
f = np.transpose(image_t.nonzero())
Share:
10,512
jfalkson
Author by

jfalkson

Updated on June 04, 2022

Comments

  • jfalkson
    jfalkson almost 2 years

    Goal: To input an image (2d numpy array) and a window size, and output the same array with the local maxima remaining, but 0 elsewhere.

    What I am struggling with: I think I made a stupid mistake in my code, maybe a few typos in my loop but I am not sure (the local maxima are only on the left side of the image, which is not true). As I note below I would also welcome any easy tricks with OpenCV or numpy to make this solution shorter.

    similar questions: Finding Local Maxima in an Image

    and Find local maxima in grayscale image using OpenCV

    Mine is different because: I am looking to surpress all but local maxima. I don't have to use my code below, I haven't been able to find a built in function of opencv or numpy to do what I need to (harris corners in cv will implicitly do this as one of the steps, but I need something to perform the sole operation I need). I read a little bit on dilate and wasn't sure if that would be useful here as well.

    What I have tried so far.

    def nonMaximalSupress(image,NHoodSize):
        #For
        for x in range(0,image.shape[0]-1):
    
            if x+NHoodSize[0]<image.shape[0]:
                #while we can still take a square
                #print "AHH ", image.shape
                startWindow=0
                for y in range(startWindow,image.shape[1]-NHoodSize[1]):
                    #try:
                    if np.sum(image[x:x+NHoodSize[0]][y:y+NHoodSize[1]])==0:
                        localMax=0
                    else:
                        localMax = np.amax(image[x:x+NHoodSize[0]][y:y+NHoodSize[1]])
                    #except ValueError:
                        #localMax=0
                    #print "local max is ", localMax
    
                    maxCoord=np.unravel_index(np.argmax((image[x:x+NHoodSize[0],y:y+NHoodSize[1]])),
                                              image.shape)+np.array((x,y))
    
                    #print "X is %r, Y is %r, max coord is %r \n y+nhood is %r" %(x,y,maxCoord,y+NHoodSize[1])
                    #suppress everything
                    image[x:x+NHoodSize[0]][y:y+NHoodSize[1]]=0
    
                    #reset only the max
                    #print maxCoord
                    if localMax > 0:
                        print localMax
                        print "max coord is ", maxCoord[0], maxCoord[1]
                    image[maxCoord[0]][maxCoord[1]]=localMax
                    #increment y
    
    
    
            x+=NHoodSize[0]
    
        return image