2

我试图在 Matlab 中找到一些峰值,但该函数findpeaks.m没有宽度选项。我想被检测到的峰在球中。所有检测到的都在红色方块中。如您所见,它们的宽度很小。有什么帮助吗?

在此处输入图像描述

这是我使用的代码:

[pk,lo] = findpeaks(ecg);

lo2 = zeros(size(lo));

for m = 1:length(lo) - 1
    if (ecg(m) - ecg(m+1)) > 0.025
        lo2(m) = lo(m);
    end
end

p = find(lo2 == 0);

lo2(p) = [];

figure, plot(ecg);
hold on
plot(lo, ecg(lo), 'rs');
4

4 回答 4

1

务实地思考,我想你可以使用这种简单的蛮力方法:

[peaks  , peakLocations]   = findpeaks(+X);
[troughs, troughLocations] = findpeaks(-X);

width = zeros(size(peaks));
for ii = 1:numel(peaks)

    trough_before = troughLocations( ...
        find(troughLocations < peakLocations(ii), 1,'last') );

    trough_after  = troughLocations( ...
        find(troughLocations > peakLocations(ii), 1,'first') );

    width(ii) = trough_after - trough_before;

end

这将找到围绕感兴趣峰的两个波谷之间的距离。

使用'MinPeakHeight'选项findpeaks()来预先修剪您的数据。从外观上看,没有自动方法可以提取您想要的峰值(除非您以某种方式对它们有明确的索引)。这意味着,您必须手动选择它们。

当然,现在还有更多的细节需要处理,但是考虑到你的数据集的形状,我认为这里的基本思想可以很好地解决你的问题。

于 2013-07-02T12:19:25.483 回答
1

从外观上看,您希望根据幅度和宽度来表征每个峰值,以便您可以对这些值应用阈值(或类似值)以仅选择符合您的标准(高和薄)的那些。

您可以做到这一点的一种方法是为每个峰值拟合正态分布,将平均值和幅度与您已经找到的值挂钩,并使用优化函数来找到标准偏差(正态分布的宽度)。

所以,你需要一个函数,它根据你拥有的所有高斯分布的总和来计算你的数据的表示,以及一个误差函数(可能是均方误差),然后你只需要把它扔到一个 matlabs 内置优化/最小化函数。

最佳标准偏差参数集将为您提供每个峰的宽度,或者至少是一个很好的近似值。

另一种方法,基于 Adiel 的评论,可能更合适,因为看起来您正在处理心电图数据,也可以找到局部最小值(波谷)和峰值。由此,您可以通过获取给定峰两侧的波谷之间的 x 轴距离来构建“薄度”的近似度量。

于 2013-07-02T11:33:35.923 回答
1

您需要定义感兴趣的峰意味着什么,以及峰的宽度是什么意思。一旦你做了这些事情,你就领先了一步。

也许您可以使用 find peaks 来定位每个峰。然后找到低谷,其中一个应该位于每对峰之间。低谷只是 -y 的峰值。确保您担心第一个和最后一个高峰/低谷。

接下来,将半高点定义为每个峰和谷之间高度的中间位置。这可以使用曲线上的反向线性插值来完成。

最后,半高处的宽度可能只是这两个半高点之间的距离(在 x 轴上)。

于 2013-07-02T12:48:25.103 回答
1

您需要先定义峰宽,确定您希望峰的宽度,然后相应地选择它们。

例如,您可以将峰的宽度定义为 x 坐标之间的差异,此时 y 坐标等于峰值的一半(请参见此处)。另一种方法(在这里似乎更合适)是在距峰本身固定距离处测量梯度,并相应地选择峰。在 MATLAB 中,您可能会为此使用梯度滤波器:

g = conv(ecg, [-1 0 1], 'same'); %// Gradient filter
idx = g(lo) > thr);              %// Indices of narrow peaks
lo = lo(idx);

thr您需要自己确定的阈值在哪里。较低的阈值意味着对更宽峰值的容忍度更高。

于 2013-07-02T12:07:54.783 回答