我有的离散样本:
我想在信号中找到局部最大值。
是否为最大值的简单测试是:
然而,最大值可能位于样本之间,例如在处可能存在最大值。
为了找到样本之间的最大值,我相信我需要插值。
- 如何使用插值找到最大值?
- 我应该使用什么形式的插值?
如您所见,我的信号不是很嘈杂,但是如果该方法还进行了一些过滤以使最大值超过阈值并具有一定的宽度(没有尖峰),那就太好了。
然而,我最大的问题是在样本之间找到峰值。有什么好的方法可以做到这一点吗?
提前感谢您的任何答案!
我有的离散样本:
我想在信号中找到局部最大值。
是否为最大值的简单测试是:
然而,最大值可能位于样本之间,例如在处可能存在最大值。
为了找到样本之间的最大值,我相信我需要插值。
如您所见,我的信号不是很嘈杂,但是如果该方法还进行了一些过滤以使最大值超过阈值并具有一定的宽度(没有尖峰),那就太好了。
然而,我最大的问题是在样本之间找到峰值。有什么好的方法可以做到这一点吗?
提前感谢您的任何答案!
获得子样本分辨率
一个非常便宜(就代码大小而言)的解决方案就是对信号进行上采样。在 matlab 中,这可以用interp(y ,ratio)
. 一个稍微复杂一点的解决方案是简单地检测峰值;对于每个峰值,通过 y[peak - 1], y[peak], y[peak + 1] 拟合抛物线;然后使用该抛物线最大的点作为真正的峰值位置。
关于峰值检测
一堆帮助的技术:
所有这些都可以在 Matlab 中通过几次 nlfilter 非常有效地实现。
尝试有损峰值检测器:
y[n] = max(abs(x[n]),a*y[n-1]);
其中“a”是一个小于 1 的数字,用于控制检测器衰减的速度。它决定了相邻峰之间的距离,而不会平滑成一个峰。然后进行阈值检测。
您还可以使用均值偏移算法使用核函数来细化峰值。
如果您关心的峰值与信号大小相比非常少,这将特别有用和高效,因此您不必对整个信号进行上采样(这可能非常昂贵)。
例如,这里是一个简化的 MATLAB 或 GNU Octave 实现:
function peak = meanshift(y, sigma, peak_guess)
peak = peak_guess;
x = 1:size(y, 2);
for iter = 1:10
%TODO: ignore areas more than 3 sigma away
% since those don't affect the output
weights = exp(-(x - peak).^2 / sigma^2) .* y;
off = sum(weights .* x) / sum(weights);
peak = off;
end
endfunction
尽管我必须强调您必须实现“TODO”中描述的内容才能使其高效。