scipy.signal.find_peaks
顾名思义,该功能对此有用。但是,要理解以及它的参数是非常重要的width
,threshold
,distance
和高于一切prominence
,以获得良好的峰值提取。
根据我的测试和文档,突出的概念是“有用的概念”,用于保持良好的峰值,并丢弃嘈杂的峰值。
什么是(地形)突出?它是“从山顶下降到更高地形所需的最低高度”,如下所示:
这个想法是:
突出程度越高,峰越“重要”。
测试:
我故意使用了一个(嘈杂的)频率变化正弦曲线,因为它显示了很多困难。我们可以看到该width
参数在这里不是很有用,因为如果您将最小值设置width
得太高,则它将无法跟踪高频部分中非常接近的峰值。如果设置width
得太低,则信号左侧会出现许多不需要的峰值。同样的问题distance
。threshold
仅与直接邻居比较,在这里没有用。prominence
是提供最佳解决方案的一种。请注意,您可以结合使用许多这些参数!
码:
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import find_peaks
x = np.sin(2*np.pi*(2**np.linspace(2,10,1000))*np.arange(1000)/48000) + np.random.normal(0, 1, 1000) * 0.15
peaks, _ = find_peaks(x, distance=20)
peaks2, _ = find_peaks(x, prominence=1) # BEST!
peaks3, _ = find_peaks(x, width=20)
peaks4, _ = find_peaks(x, threshold=0.4) # Required vertical distance to its direct neighbouring samples, pretty useless
plt.subplot(2, 2, 1)
plt.plot(peaks, x[peaks], "xr"); plt.plot(x); plt.legend(['distance'])
plt.subplot(2, 2, 2)
plt.plot(peaks2, x[peaks2], "ob"); plt.plot(x); plt.legend(['prominence'])
plt.subplot(2, 2, 3)
plt.plot(peaks3, x[peaks3], "vg"); plt.plot(x); plt.legend(['width'])
plt.subplot(2, 2, 4)
plt.plot(peaks4, x[peaks4], "xk"); plt.plot(x); plt.legend(['threshold'])
plt.show()