我正在从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时,我只是反转了我的数据。)
答案 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