优化用于在一维阵列中查找峰值的参数

Optimising parameters for finding peaks in 1D array

我需要优化查找一维数组中数据峰值数量的方法。数据是一个wav文件的振幅时间序列。

我已经实现了代码:

from scipy.io.wavfile import read
from scipy.signal import find_peaks


_, amplitudes = read('audio1.wav')


indexes, _ = find_peaks(amplitudes, height=80)
print(f'Number of peaks: {len(indexes)}')

绘制时,数据如下所示:

General scale

我感兴趣的 'peaks' 是人眼清楚的 - 在这个特定数据集中有 23 个。

但是,由于数组太大,数据在一般尺度下清晰的峰内变化极大(因此有数百个峰标有蓝色十字):

Zoomed in view of one peak

之前已经问过很多次寻峰问题(我经历过很多次!)-但我找不到任何帮助或解释优化参数 只找到我想要的峰。我懂一点Python,但在数学分析方面是瞎子!

按宽度分析似乎没有用,因为根据第二张图片,大范围清晰的峰实际上散布着 'silent' 范围。距离没有帮助,因为我不知道其他 wav 文件中的峰值有多接近。 Prominence 已被建议为最佳方法,但我无法获得所需的结果;阈值同样。我也试过抽取信号,用 Savitzky-Golay 滤波器平滑信号,以及参数和值的不同组合,结果都不准确。

单独的高度很有用,因为我从图表中可以看出峰值总是在 80 以上。

查看 0d 持久同源性 找到一个好的策略,其中您可以优化的参数是 峰值持久性。一个不错的博客 post here 解释了基础知识。

但简而言之,这个想法是想象你的图表被水充满,然后慢慢地排出水。每当一张图浮出水面时,一个新的岛屿就会诞生。当两个岛屿彼此相邻时,它们会合并,导致较年轻的岛屿(具有较低的峰值)死亡。 然后每个数据点都有一个出生时间和一个死亡时间。最重要的峰值是 持久性 最长的峰值,即 death - birth.

如果水位以连续速率下降,则持久性根据峰值高度来定义。另一种可能性是随着时间从步骤 t 到步骤 t+1,从一个点到另一个点瞬间滴水,在这种情况下,持久性在峰值 宽度 中定义在信号样本方面。

对您来说,使用峰高 > 70 的原始定义似乎会发现您感兴趣的所有峰聚集在一起,尽管可能太多了。您可以通过选择每个簇中的第一个峰或每个簇中的最高峰来限制这一点,或者通过执行这两种方法并仅选择具有良好高度持久性和宽度持久性的峰。

这是音频处理中的一项常见任务,有多种方法完全取决于您的数据。

但是,有一些实现可用于查找新颖函数的峰值(例如,节拍跟踪器的输出)。试试这些:

基本上他们实现了相同的方法,但细节上可能存在差异。 此外,您可以检查是否真的需要使用这种高采样频率。尝试对信号进行下采样或使用移动平均滤波器。