发现的2-D numpy的阵列的相对最大值 [英] Finding relative maximums of a 2-D numpy array

查看:178
本文介绍了发现的2-D numpy的阵列的相对最大值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个2-D numpy的数组,可细分为64箱(想到一个棋盘)。
的目标是返回在每个盒的最大的位置和值的函数。是这样的:

I have a 2-D numpy array that can be subdivided into 64 boxes (think of a chessboard). The goal is a function that returns the position and value of the maximum in each box. Something like:

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

其中的 argmaxXnn 的和的 argmaxYnn 的是整个阵列(不是框)的索引和的 Maxnn 的是最大值在每框。换句话说,

where argmaxXnn and argmaxYnn are the indexes of the whole array (not of the box), and Maxnn is the max value in each box. In other words,

Maxnn = array[argmaxYnn,argmaxYnn]

我trye​​d明显的嵌套的解决方案:

I've tryed the obvious "nested-for" 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

它的工作原理,但既不优雅,也不eficient。
所以我trye​​d这更Python版本:

It works, but is neither elegant nor eficient. So I've tryed 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

它工作正常,但让我吃惊,是不是比previous版本更高效!

It works fine but, to my surprise, is not more efficient than the previous version!

现在的问题是:有没有更聪明的方法做任务

The question is: Is there a more clever way to do the task?

需要注意的是效率问题,因为我有许多处理大型阵列。

Note that efficiency matters, as I have many large arrays for processing.

任何线索是值得欢迎的。 :)

Any clue is welcome. :)

推荐答案

试试这个:

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),A [I1,I2]将不会返回正确的值,而[I2,I1]会的。

Note that your first FindRefs reverses indices, so that for a tuple (i1,i2,v), a[i1,i2] won't return the right value, whereas a[i2,i1] will.

因此​​,这里的code做了什么:

So here's what the code does:


  • 它首先计算出每个盒子需要有()给您的数组的大小尺寸。请注意,这并不做任何检查:你需要有一个数组可以的均匀地分为8×8的网格。

  • 然后以Z AST 是凌乱位。它采用二维数组,并把它变成的 4D 的数组。四维阵列的尺寸为(8,8,盒[0]中的[1]),所以它可以让你选择哪一个框,你想要的(前两个轴),然后在框中(未来两年)想要什么样的地位。这让我们通过在最后两轴做操作一次处理所有的箱子。

  • V3 让我们沿着最后轴线的最大值:换句话说,它包含最大在每个框中的每个列。 i3r包含行中的框包含了最大值的索引。

  • V2 携自己的最后一个轴,这是目前在框中处理行的最大 V3 的:它需要列马克塞斯,发现最大的人,让 V2 是包含每个盒子的最大值的二维数组。 如果您想让所有的都是最大值,这是所有你所需要的。

  • I2 是保存最大值框中列的索引。

  • 现在,我们需要得到该行的指数在箱......这是棘手。 i3r 包含在框中每列的最大的行索引,但我们要针对在I2指定的特定的列行。我们通过使用 I2 i3r 选择一个元素做到这一点,这让我们 I3

  • 在这一点上,<​​code> I2 和酷睿i3 是8×8包含最大值的行和列索引数组相对于每个框。我们要的绝对指标。所以我们创建 i2x i3x (其实,这是没有意义的,我们只能创建一个,因为它们是相同的),这是只是什么 I2 酷睿i3 的索引(0,1,2阵列,..中,在一维8等等,等等)。然后,我们通过箱尺寸乘以这些,并添加相对最大的索引,以获得最大的绝对指标。

  • 我们再结合这些让你有相同的输出。请注意,如果你让他们为数组,虽然,而不是使元组,它的速度更快。

  • It first calculates the dimensions that each box needs to have (box) given the size of your array. Note that this doesn't do any checking: you need to have an array that can be divided evenly into an 8 by 8 grid.
  • Then z with ast is the messiest bit. It takes the 2d array, and turns it into a 4d array. The 4d array has dimensions (8,8,box[0],box[1]), so it lets you choose which box you want (the first two axes) and then what position you want in the box (the next two). This lets us deal with all the boxes at once by doing operations on the last two axes.
  • v3 gives us the maximum values along the last axis: in other words, it contains the maximum of each column in each box. i3r contains the index of which row in the box contained that max value.
  • v2 takes the maximum of v3 along its own last axis, which is now dealing with rows in the box: it takes the column maxes, and finds the maximum of them, so that v2 is a 2d array containing the maximum value of each box. If all you wanted were the maximums, this is all you'd need.
  • i2 is the index of the column in the box that holds the maximum value.
  • Now we need to get the index of the row in the box... that's trickier. i3r contains the row index of the max of each column in the box, but we want the row for the specific column that's specified in i2. We do this by choosing an element from i3r using i2, which gives us i3.
  • At this point, i2 and i3 are 8 by 8 arrays containing the row and column indexes of the maximums relative to each box. We want the absolute indexes. So we create i2x and i3x (actually, this is pointless; we could just create one, as they are the same), which are just arrays of what the indexes for i2 and i3 are (0,1,2,...,8 etc in one dimension, and so on). We then multiply these by the box sizes, and add the relative max indexes, to get the absolute max indexes.
  • We then combine these to get the same output that you had. Note that if you keep them as arrays, though, instead of making tuples, it's much faster.

这篇关于发现的2-D numpy的阵列的相对最大值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆