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

2024-06-18 11:45:32 发布

您现在位置:Python中文网/ 问答频道 /正文

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

我想在一个相当平滑的二维阵列中检测峰值,它的形状等于(60300)。我只希望找到一两个峰(但绝不会超过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 arrayFind peak of 2d histogramPeak detection in a noisy 2d array

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


Tags: inhttp链接array例程nasaidlgov
2条回答

经过一番尝试和错误,并改编了Peak detection in a 2D array中的代码,我得出了以下解决方案。注意:阈值=np平均值(图像)-np.标准(图像)

请随时发表任何改进,我对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
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分量对这些峰进行排序

相关问题 更多 >