方法一:ampdlib和pyampd
一个直接实现原始AMPD算法的库
pip install ampdlib
import ampdlib
# 假设 your_signal 是你的信号数据 (NumPy数组或列表)
peaks = ampdlib.ampd(your_signal)
注意 :该库对内存消耗可能较高,对于长信号,可以考虑使用ampd_fast进行分窗处理
pip install pyampd
from pyampd.ampd import find_peaks
# 基础用法
peaks = find_peaks(your_signal)
# 指定最大尺度以优化性能
peaks = find_peaks(your_signal, scale=100)
pyampd :一个进行了性能优化的实现,支持指定最大尺度(scale)来提升速度,并提供了能适应信号特征变化的自适应版本
方法二:手动实现算法(自己编写)
import numpy as np
import matplotlib.pyplot as plt
def ampd_algorithm(signal):
"""
AMPD(自动多尺度峰值检测)算法的Python实现。
参考: Scholkmann et al. 2012
"""
n = len(signal)
# 1. 线性去趋势
t = np.arange(n)
p = np.polyfit(t, signal, 1)
detrended_signal = signal - np.polyval(p, t)
# 2. 计算局部极大值刻度图 (LMS)
# 最大尺度 L = floor(N/2) - 1
L = n // 2 - 1
# 初始化LMS矩阵,M[k, i] 表示在尺度k下,点i是否为局部极大值
M = np.ones((L, n), dtype=float) * np.random.rand()
for k in range(1, L + 1):
window_size = k + 1
for i in range(k, n - k):
# 检查点i是否在窗口 [i-k, i+k] 内为最大值
if detrended_signal[i] > detrended_signal[i - k] and detrended_signal[i] > detrended_signal[i + k]:
M[k-1, i] = 0
# 3. 确定最佳尺度 lambda
gamma = np.sum(M, axis=1) # 对LMS矩阵逐行求和
lambda_ = np.argmin(gamma) # 行和最小的索引即为最佳尺度
# 4. 峰值检测:裁剪LMS矩阵并计算列标准差
# 只保留尺度 1 到 lambda_ 的行
M_reduced = M[:lambda_ + 1, :]
# 计算裁剪后矩阵的列标准差
sigma = np.std(M_reduced, axis=0)
# 标准差为0的列索引即为检测到的峰值位置
peaks = np.where(sigma == 0)[0]
return peaks, detrended_signal
# --- 使用示例 ---
if __name__ == '__main__':
# 生成一个含噪声的模拟信号
np.random.seed(42)
x = np.arange(1000)
base_signal = np.sin(0.2 * x) + 2 * np.sin(0.4 * x)
noise = 0.8 * np.random.randn(len(x))
y = base_signal + noise
# 执行峰值检测
detected_peaks, detrended_y = ampd_algorithm(y)
# 可视化结果
plt.figure(figsize=(14, 6))
plt.plot(x, y, 'b-', label='原始信号', alpha=0.7)
plt.plot(x, detrended_y, 'g-', label='去趋势信号', alpha=0.5)
plt.scatter(detected_peaks, y[detected_peaks], color='red', s=40, zorder=5, label='检测到的峰值')
plt.title("AMPD 峰值检测结果")
plt.xlabel("数据点索引")
plt.ylabel("信号值")
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
print(f"检测到峰值数量: {len(detected_peaks)}")
# print(f"峰值位置索引: {detected_peaks}")
关键注意事项
信号预处理 :强烈建议在使用AMPD之前,对信号进行带通滤波,以去除与目标峰值无关的高频噪声和低频漂移,这能显著提升检测准确率。
内存与计算 :AMPD算法的复杂度为
O(N²),处理非常长的信号(如数百万个数据点)时可能较慢或占用大量内存。可考虑使用ampdlib的分窗功能或pyampd的限制尺度功能。参数调整 :虽然算法号称"无参",但部分实现允许你指定最大尺度 (
scale)。对于周期明显的信号,限制此参数可大幅提升速度。边缘与重叠峰 :原始算法在信号起点和终点附近可能检测不佳,对非常接近的重叠峰也可能分辨困难。使用
pyampd的find_peaks_original或最新库可改善边缘问题。