【问题标题】:2D peak finding with non-maximum suppression using numpy使用 numpy 进行非最大抑制的 2D 峰值查找
【发布时间】:2018-01-20 01:16:14
【问题描述】:

我编写了一个函数(如下所示)来查找图像中顶部num_peaks 强度值的位置,同时执行非最大值抑制以仅选择局部最大值:

def find_peaks(img, num_peaks, threshold_fraction=0.5, nhood_size=None):
    """Find locally maximum intensities in an image"""
    # calculate threshold as a fraction of intensity range in the image
    threshold = (threshold_fraction * (img.max() - img.min())) + img.min()

    # determine offsets in each direction that constitute a neighbourhood
    if nhood_size is None:
        nhood_size = np.array(img.shape) * 0.02
    nhood_offset = (np.around(nhood_size / 2)).astype(int)

    # create array with labelled fields to allow intensity-specific sorting
    rows, cols = np.array(np.where(img >= threshold))
    values = []
    for i, j in zip(rows, cols):
        values.append((i, j, img[i, j]))

    dtype = [('row', int), ('col', int), ('intensity', np.float64)]
    indices = np.array(values, dtype=dtype)

    # sort in-place in descending order
    indices[::-1].sort(order='intensity')

    # Perform suppression
    for idx_set in indices:
        intensity = idx_set[2]
        if not intensity:
            continue

        x0 = idx_set[1] - nhood_offset[1]
        xend = idx_set[1] + nhood_offset[1]
        y0 = idx_set[0] - nhood_offset[0]
        yend = idx_set[0] + nhood_offset[0]

        indices_to_suppress = np.where((indices['col'] >= x0) &
                                       (indices['col'] <= xend) &
                                       (indices['row'] >= y0) &
                                       (indices['row'] <= yend))
        if indices_to_suppress:
            indices['intensity'][indices_to_suppress] = 0

        idx_set[2] = intensity

    # perform second sorting & return the remaining n (num_peaks) most
    # intense values
    indices[::-1].sort(order='intensity')
    if len(indices) <= num_peaks:
        return np.array([np.array([i, j])
                        for i, j in zip(indices['row'], indices['col'])])

    # or return all of them
    return np.array([np.array([i, j])
                    for i, j in zip(indices['row'][:num_peaks], indices['col'][:num_peaks])])

这似乎适用于小图像和大threshold_fraction(要抑制的值较少),但事实证明对于我的目的来说效率很低,因为我的阈值较低,例如 0.1 到 0.2。我无法用我的初学者 numpy 技能来提高效率。

我想知道是否可以对这段代码进行任何更改以提高其性能。另外,由于我使用的是 numpy 和 OpenCV,因此很高兴知道是否有一个库函数可以实现类似的功能或以某种方式利用它来编写高效的峰值查找器。

【问题讨论】:

    标签: python numpy opencv image-processing


    【解决方案1】:

    不管怎样,既然您已经在使用numpy,那么额外使用skimage(与pip install scikit-image 一起安装)应该是轻而易举的事。然后,您可以使用 skimage.feature.peak_local_max()skimage.ndimage.maximum_filter() 创建您感兴趣的位置的地图,并且由于对象本身被认为是 numpy 数组,您可以通过从您的结果数组中减去一部分来抑制这些区域原创。

    【讨论】:

      【解决方案2】:

      您的算法依赖于对图像值进行排序,因此在图像像素数 N 中其时间复杂度为 O(N log N),并且需要额外的 O(N) 内存缓冲区来存储排序后的值。

      标准的局部最大值检测器依赖于使用小的结构元素(其大小取决于图像的“嘈杂”或“尖峰”程度)对图像进行膨胀,然后找到原始图像所在的像素和扩张的具有相同的价值。这在时间上是 O(N) 并且需要额外的 O(N) 缓冲区。非局部最大值像素的抑制是自动的,并且可以通过按图像强度对找到的局部最大值(其数量通常为

      因此,对于足够大的图像,后一种算法理论上性能更高,并且实际上可能也性能更高。当然 YMMV 取决于实现和图像大小。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-10
        • 2015-05-17
        • 2021-03-10
        • 2011-10-19
        • 1970-01-01
        • 2011-05-13
        相关资源
        最近更新 更多