Search for relative maxima of a 2-D numpy array

I have a 2-D numpy array that can be divided into 64 fields (think of a chessboard). A goal is a function that returns the position and maximum value in each field. Sort of:

FindRefs(array) --> [(argmaxX00, argmaxY00, Max00), ...,(argmaxX63, argmaxY63, Max63)]

where argmaxXnn and argmaxYnn are the indices of the entire array (not the field), and Maxnn is the maximum value in each field. In other words,

Maxnn = array[argmaxYnn,argmaxYnn]

I tried the obvious nested solution:

def FindRefs(array):
    Height, Width = array.shape
    plumx = []
    plumy = []
    lum = []
    w = int(Width/8)
    h = int(Height/8)
    for n in range(0,8):    # recorrer boxes
        x0 = n*w
        x1 = (n+1)*w
        for m in range(0,8):
            y0 = m*h
            y1 = (m+1)*h
            subflatind = a[y0:y1,x0:x1].argmax() # flatten index of box
            y, x = np.unravel_index(subflatind, (h, w))
            X = x0 + x
            Y = y0 + y
            lum.append(a[Y,X])
            plumx.append(X)
            plumy.append(Y)

    refs = []
    for pt in range(0,len(plumx)):
        ptx = plumx[pt]
        pty = plumy[pt]
        refs.append((ptx,pty,lum[pt]))
    return refs

It works, but is neither elegant nor efficient. So I tried this more pythonic version:

def FindRefs(a):
    box = [(n*w,m*h) for n in range(0,8) for m in range(0,8)]
    flatinds = [a[b[1]:h+b[1],b[0]:w+b[0]].argmax() for b in box]
    unravels = np.unravel_index(flatinds, (h, w))
    ur = [(unravels[1][n],unravels[0][n]) for n in range(0,len(box))]
    absinds = [map(sum,zip(box[n],ur[n])) for n in range(0,len(box))]
    refs = [(absinds[n][0],absinds[n][1],a[absinds[n][1],absinds[n][0]]) for n in range(0,len(box))] 
    return refs

It works great, but, to my surprise, is no more efficient than the previous version!

Question: is there a smarter way to complete the task?

Note that efficiency matters because I have a lot of large arrays to handle.

Any hint is welcome. :)

+4
1

:

from numpy.lib.stride_tricks import as_strided as ast
import numpy as np
def FindRefs3(a):
    box = tuple(x/8 for x in a.shape)
    z=ast(a, \
          shape=(8,8)+box, \
          strides=(a.strides[0]*box[0],a.strides[1]*box[1])+a.strides)
    v3 = np.max(z,axis=-1)
    i3r = np.argmax(z,axis=-1)
    v2 = np.max(v3,axis=-1)
    i2 = np.argmax(v3,axis=-1)
    i2x = np.indices(i2.shape)
    i3 = i3r[np.ix_(*[np.arange(x) for x in i2.shape])+(i2,)]
    i3x = np.indices(i3.shape)
    ix0 = i2x[0]*box[0]+i2
    ix1 = i3x[1]*box[1]+i3
    return zip(np.ravel(ix0),np.ravel(ix1),np.ravel(v2))

, FindRefs , (i1, i2, v), [i1, i2] , [i2, i1] .

, :

  • , (box) . , : , 8 8.
  • z ast . 2d- 4d. 4d- (8,8, box [0], box [1]), , ( ), ( ), , .
  • v3 : , . i3r , .
  • v2 v3 , : , v2 2d , . , , , , .
  • i2 - , .
  • ... . i3r max , , i2. , i3r i2, i3.
  • i2 i3 8 8 , . . , i2x i3x ( , , ), i2 i3 (0, 1,2,..., 8 .. ..). , .
  • , , . , , , , .
+2

All Articles