如何使用 Savitzky Golay 滤波器在离散采样的一维信号中找到局部最大值(在样本之间)?

信息处理 平滑 插值 峰值检测
2021-12-28 17:00:18

我有一个地震信号 y(i): 在此处输入图像描述

在这里,我发现了一个最大值: i=152.54, y=222.29 手动并将其绘制为红色。

我想自动找到所有最大值。

我读到 Savitzky Golay 滤波器 (SGF) 可用于找到信号及其导数的平滑估计,并且 SGF 的好处之一是它比其他滤波器更好地保留最小值和最大值。这听起来很适合我的使用。

我找到了一个生成 SGF 系数的 Matlab 脚本。 并用它来找到导数的四阶 SGF 系数。我编写了一个小的 Matlab 脚本

  1. 通过将信号与导数的四阶 SGF 系数进行卷积来找到信号的导数
  2. 找到导数改变符号的样本对 (i,i+1)
  3. 通过 i 和 i+1 之间的线性插值找到导数的零交叉

脚本:

function [maxX,maxY] = findLocalMax(y)
% Kernel for 4th order Savitzky-Golay filter for finding derivative:
d4 = [0.0724 -0.1195 -0.1625 -0.1061 0 0.1061 0.1625 0.1195 -0.0724];

dy = conv(y,d4,'same'); % derivative

[m n] = size(dy);
maxX = [];
maxY = [];
for i = 1 : n - 1
  if dy(i) < 0 && dy(i+1) > 0 % max somewhere between i and i+1
    a = dy(i)/(dy(i) - dy(i+1)); % linear interpolation
    mx = i + a;
    maxX = [maxX mx];
    my = y(i)*(1-a) + y(i+1)*a; % linear interpolation
    maxY = [maxY my];
  end
end

在我的脚本中,我必须测试导数是否从负变为正才能获得函数以提供所需的结果,但这让我感到困惑。 最大值的导数不应该从正变为负吗? 有没有更好的方法来区分最大值和最小值?

以下是使用此函数查找信号最大值的结果: 在此处输入图像描述

结果看起来不错,但我注意到没有找到一些最大值:i= 143.13, 190.88, 256.97。

这是因为它们要接近其他最大值吗?

如何控制最近的两个最大值?

提前感谢您的任何答案!

1个回答

虽然我不熟悉这种特定类型的过滤器,但根据您显示的图,我猜您的流程未找到的最大值只是与流程中固有的时间分辨率相抵触。任何一种“平滑”都意味着感兴趣的信号存在一些时间局部模糊,因此如果附近有两个峰值,它们可能会合并为一个。低阶滤波器可能会出现较少的这种行为,可能是以牺牲您获得的平滑量为代价的。