Python中如何仅检测信号的尖锐峰值 排除宽平顶峰值干扰
方案1:直接调整scipy.signal.find_peaks参数
plateau_size参数(核心):该参数用于限定峰顶平坦区域的采样点数量,刚好适配你排除宽平顶峰的需求。你可以设置为plateau_size=(0,1),即仅允许峰顶最多存在1个采样点的平坦区域,所有平顶超过1个采样点的宽峰会被直接过滤。width参数:该参数限定峰值在半高处的宽度,你可以先统计目标尖锐峰的半高宽范围,比如你的尖锐峰半高宽普遍在3个采样点以内,就设置width=(0,3),进一步过滤宽度超标的宽峰。threshold参数(可选):该参数限定峰值与左右相邻采样点的最小差值,尖锐峰的相邻差值远大于平缓宽峰,可根据你的信号幅值设置合适阈值,过滤掉变化平缓的假峰。
方案2:前置预处理降低检测难度
你目前用滑动窗口差值的思路本身是合理的,可以进一步优化预处理逻辑:
- 先对原始信号做一阶差分计算:
np.diff(原始信号),尖锐电平跳变的位置差分结果会出现极高的幅值,宽平顶区域的差分结果幅值极低甚至为0,对差分后的信号做峰值检测,区分度会远高于原始信号。 - 如果信号噪声较高,可以先做窗口大小不超过3的移动平均平滑,注意不要用过大的平滑窗口,否则会磨平你需要识别的尖锐峰值。
示例代码
import numpy as np from scipy.signal import find_peaks # 此处的processed_signal可以是你计算得到的滑动窗口差值信号,也可以是一阶差分后的预处理信号 peaks, properties = find_peaks( processed_signal, plateau_size=(0, 1), # 过滤宽平顶峰核心参数 width=(0, 3), # 根据实际尖锐峰宽度调整上限 prominence=0.05 # 可选,过滤幅值过低的噪声小峰,数值根据信号幅值调整 )
注:所有参数的数值阈值都需要你结合自身信号的采样率、幅值范围做适配调整,你可以先手动标注几个目标尖锐峰和要排除的宽峰,统计两者的半高宽、平顶长度等数值,再设置对应的过滤阈值即可。
内容的提问来源于stack exchange,提问作者kspr
相关产品推荐
相关产品推荐

