你好,我正在尝试在一个3D的numpy数组中找到局部最大值,但是使用numpy、scipy或其他方式似乎都没有简单的方法。
目前我使用了scipy.signal.argrelexrema
进行了实现。但是处理大型数组非常耗时,而且只能在分离的轴上运行。
import numpy as np
from scipy.signal import argrelextrema
def local_maxima_3D(data, order=1):
"""Detects local maxima in a 3D array
Parameters
---------
data : 3d ndarray
order : int
How many points on each side to use for the comparison
Returns
-------
coords : ndarray
coordinates of the local maxima
values : ndarray
values of the local maxima
"""
# Coordinates of local maxima along each axis
peaks0 = np.array(argrelextrema(data, np.greater, axis=0, order=order))
peaks1 = np.array(argrelextrema(data, np.greater, axis=1, order=order))
peaks2 = np.array(argrelextrema(data, np.greater, axis=2, order=order))
# Stack all coordinates
stacked = np.vstack((peaks0.transpose(), peaks1.transpose(),
peaks2.transpose()))
# We keep coordinates that appear three times (once for each axis)
elements, counts = np.unique(stacked, axis=0, return_counts=True)
coords = elements[np.where(counts == 3)[0]]
# Compute values at filtered coordinates
values = data[coords[:, 0], coords[:, 1], coords[:, 2]]
return coords, values
我知道这种解决方案远非最佳,并且仅在order=1时起作用。有没有更好的方法在Python中查找3D数组中的局部极大值? 编辑: 我现在使用以下方法,它实际上比较快,而且当order> 1时也有效:
import numpy as np
from scipy import ndimage as ndi
def local_maxima_3D(data, order=1):
"""Detects local maxima in a 3D array
Parameters
---------
data : 3d ndarray
order : int
How many points on each side to use for the comparison
Returns
-------
coords : ndarray
coordinates of the local maxima
values : ndarray
values of the local maxima
"""
size = 1 + 2 * order
footprint = np.ones((size, size, size))
footprint[order, order, order] = 0
filtered = ndi.maximum_filter(data, footprint=footprint)
mask_local_maxima = data > filtered
coords = np.asarray(np.where(mask_local_maxima)).T
values = data[mask_local_maxima]
return coords, values