Python:检测平滑2D阵列中的峰值(或最小值)

时间:2015-01-27 16:45:25

标签: python arrays detection

我正在从IDL迁移到Python,但有一个我需要的例程,我在python中找不到。

我想检测一个相当平滑的2D阵列中的峰值,该阵列的形状等于(60,300)。我只期望找到一个或两个峰值(但绝不会超过4个)。

是否有一个python例程类似于我可以使用的IDL的FindPeaks(链接如下)?

http://hesperia.gsfc.nasa.gov/ssw/smei/ucsd/gen/idl/toolbox/findpeaks.pro

关于2D阵列/图像中的峰值检测的stackoverflow的其他答案似乎被设计为返回多个(例如,> 20个)峰值(下面的链接)。可以修改其中任何一个以平滑变化的数组吗?

请参阅:     Peak detection in a 2D array,     Find peak of 2d histogram,     Peak detection in a noisy 2d array

(事实上,我真正想要的是检测最小值,但在网上似乎有更多关于最大值/峰值的问题。当我在IDL中使用FindPeaks时,我只是反转了我的数据。)

2 个答案:

答案 0 :(得分:0)

numPeaks = 2
my_points = [[9, 30], [11, 61], [29, 48], [30, 97], [44, 33], [64, 76], [83, 45], [84, 22], [90, 28], [93, 81]]
sorted(my_points,reverse=True,key=lambda (x,y):y)[:numPeaks]

可能会这样做(没有看过其他功能)

没有像您链接的那样的功能。

上面的这个方法探索了整个空间并按Y高度对其进行排序,给出了各种最大值(注意这与峰值略有不同)。对于大型数据集来说,它可能不是一个可接受的解决方案...找到实际的峰值(也称为局部最大值)一个简单的算法是随机爬山,这将返回所有峰值(这是一个点这比其相邻点都要高)

然后,您可以按Y分量

对这些峰进行排序

答案 1 :(得分:0)

经过一些试验和错误,以及调整Peak detection in a 2D array的代码后,我提出了以下解决方案。 NB:threshold = np.mean(image)-np.std(image)

请随意发布任何改进,我仍然是python的新手

def detect_minima(image, threshold):

    # define an 8-connected neighborhood
    neighborhood = generate_binary_structure(2,2)

    # apply the local minimum filter; all pixel of minimal value 
    # in their neighborhood are set to 1
    local_min = minimum_filter(image, footprint=neighborhood) == image
    # local_min is a mask that contains the minimas we are 
    # looking for, but also the background.
    # In order to isolate the minimas we must remove the background from the mask.

    # we create the mask of the background
    background = (image > threshold)

    # a little technicality: we must erode the background in order to 
    # successfully subtract it form local_min, otherwise a line will 
    # appear along the background border (artifact of the local minimum filter)
    eroded_background = binary_erosion(background, structure=neighborhood, border_value=1)

    # we obtain the final mask, containing only minimas, 
    # by removing the background from the local_min mask
    detected_minimas = local_min - eroded_background

    # Label minimas and extract each minima
    labels, nlabels = label(detected_minimas , structure=neighborhood)
    dim1 = np.zeros(nlabels, dtype=np.int)
    dim2 = np.zeros(nlabels, dtype=np.int)
    val  = np.zeros(nlabels)
    for l in range(0,nlabels):
        dim1[l], dim2[l] = minimum_position(image, labels=labels, index=l+1)
        val[l] = image[dim1[l],dim2[l]]

    # ensure points are below threshold
    lt_threshold = val < threshold 
    dim1 = dim1[lt_threshold]
    dim2 = dim2[lt_threshold]
    val  = val[lt_threshold]

    # remove points which neighbour any background or missing points.
    image[background] = threshold
    keep_asl = []

    for l in range(0,len(dim1)):

        bounds1a, bounds1b = dim1[l]-1, dim1[l]+2
        bounds2a, bounds2b = dim2[l]-1, dim2[l]+2   

        if (bounds1a < 0):                  bounds1a = 0
        if (bounds1b >= image.shape[0]):    bounds1a = image.shape[0]-1
        if (bounds2a < 0):                  bounds2a = 0
        if (bounds2b >= image.shape[1]):    bounds2a = image.shape[1]-1

        neighbour_vals = image[ bounds1a:bounds1b, bounds2a:bounds2b ]
        neighbour_max = np.max(neighbour_vals)

        if (type(image.data) == np.ma.core.MaskedArray):
            if ( (neighbour_max < threshold) & (image.fill_value not in neighbour_vals) ):
                    keep_asl.append(l)
        else:
            if (neighbour_max < threshold): keep_asl.append(l)      

    dim1 = dim1[keep_asl]
    dim2 = dim2[keep_asl]
    val  = val[keep_asl]

    # sort by value (lowest first)
    sort_ind = np.argsort(val)
    dim1 = dim1[sort_ind]
    dim2 = dim2[sort_ind]
    val  = val[sort_ind]

    return dim1, dim2, val