求scipy.signal.find_peaks()函数的算法实现原理详解
scipy.signal.find_peaks() 峰值查找算法实现细节
核心基础逻辑
find_peaks()的核心是局部最大值判定,所有后续过滤都基于这个基础筛选结果展开:
- 遍历输入数组(默认跳过首尾元素,因缺少单侧邻居),对每个中间点
i,先判定是否满足:x[i] > x[i-1]且x[i] > x[i+1]——这是最基础的峰值条件。 - 遇到平顶峰(连续多个相等的最大值)时,默认取该平台最右侧的点作为峰值;若设置
plateau_size参数,会要求平台长度达到指定值才判定为有效峰值。
可选过滤参数的算法细节
距离过滤(distance)
找到基础峰值后,先按峰值位置排序,再遍历筛选:
- 对每两个相邻峰值,若间距小于指定
distance,保留数值更大的那个,删除较小的;若数值相等,保留位置更靠前的。
高度过滤(height)
将每个峰值的y值与height阈值对比:
- 若
height是单个数值,保留y值≥该数值的峰值; - 若
height是二元组(low, high),则保留y值在[low, high]区间内的峰值。
阈值过滤(threshold)
计算峰值与左右相邻谷值的差值:
- 左差值 = 峰值y值 - 左侧最近谷值的y值;
- 右差值 = 峰值y值 - 右侧最近谷值的y值;
- 只有左、右差值均≥指定
threshold的峰值才会被保留。
突出度过滤(prominence)
这是最复杂的过滤逻辑,核心是计算峰值相对于周围的“突出程度”:
- 对每个峰值,向左右两侧分别遍历,直到找到第一个比当前峰值高的点,这两个点之间的区域就是该峰值的“影响区间”;
- 在影响区间内,找到左右两侧的最低谷值,取两者中的较大值作为基准线;
- 突出度 = 峰值y值 - 基准线y值;
- 仅保留突出度≥指定值的峰值。
宽度过滤(width)
计算峰值的指定高度下的宽度:
- 基于突出度或指定的
rel_height(相对高度,默认0.5即半高),确定宽度的计算基准高度(比如半高就是峰值y值 - 突出度/2); - 在峰值左右两侧,通过线性插值找到第一个低于基准高度的点,计算这两个点之间的间距作为峰值宽度;
- 保留宽度≥指定值的峰值。
边缘峰值处理
默认不判定数组首尾元素为峰值,若需包含边缘点,需结合wlen等参数调整:
- 第一个元素需满足
x[0] > x[1]且通过其他过滤条件; - 最后一个元素需满足
x[-1] > x[-2]且通过其他过滤条件。
内容的提问来源于stack exchange,提问作者j1ling67n
相关产品推荐
相关产品推荐

