MATLAB的信号处理工具箱中函数findpeaks的意外行为

时间:2010-12-07 12:36:11

标签: matlab signal-processing

编辑:其实这不是意料之外的行为,但我仍然需要一个解决方案。 findpeaks compares each element of data to its neighboring values.

我的数据包含我使用信号处理工具箱中的函数findpeaks检测到的峰值。有时,当我有两次相同的值时,函数似乎没有正确检测到峰值。这在我的数据中非常简单,但这里有一个示例来说明我的问题:

>> values

values =

   -0.0324
   -0.0371
   -0.0393
   -0.0387
   -0.0331
   -0.0280
   -0.0216
   -0.0134
   -0.0011
    0.0098
    0.0217
    0.0352
    0.0467
    0.0548
    0.0639
    0.0740
    0.0813
    0.0858                  <-- here should be another peak
    0.0858                  <--
    0.0812
    0.0719
    0.0600
    0.0473
    0.0353
    0.0239
    0.0151
    0.0083
    0.0034
   -0.0001
   -0.0025
   -0.0043
   -0.0057
   -0.0048
   -0.0038
   -0.0026
    0.0007
    0.0043
    0.0062
    0.0083
    0.0106
    0.0111
    0.0116
    0.0102
    0.0089
    0.0057
    0.0025
   -0.0025
   -0.0056

现在,findpeaks函数只找到一个峰值:

>> [pks loc] = findpeaks(values)

pks =

    0.0116


loc =

    42

如果我绘制数据,很明显,findpeaks错过了18/19位置的其中一个峰值,因为它们都具有值0.08579

alt text

找到失踪峰的最佳方法是什么?

5 个答案:

答案 0 :(得分:1)

如果您有图像处理工具箱,可以使用IMREGIONALMAX找到峰值,之后您可以使用regionprops找到区域的中心(如果这是您需要的),即

bw = imregionalmax(signal);
peakLocations = find(bw); %# returns n peaks for an n-tuple of max-values

stats = regionprops(bw,'Centroid');
peakLocations = cat(1,stats.Centroid); %# returns the center of the n-tuple of max-values

答案 1 :(得分:1)

这是一个古老的话题,但也许有些人仍然在寻找一个更简单的解决方案(就像我今天所做的那样):

除了第一个值之外,您还可以从高原上的所有值中减去一些非常小的固定值。这导致高原上的每个第一个值始终在相应的平台上最高,导致它们被包括为峰值。

只需创建类似代码的部分内容:

peaks = yourdata;
verysmallvalue = .001;
plateauvalue = peaks(1);

for i = 2:size(peaks,1)
    if peaks(i) == plateauvalue
        peaks(i) = peaks(i) - verysmallvalue;
    else
        plateauvalue = peaks(i);
    end
end

[PKS,LOCS] = findpeaks(peaks);
plot(yourdata);
hold on;
plot(LOCS, yourdata(LOCS), 'Color', 'Red', 'Line', 'None', 'Marker', 'o');

希望这有帮助!

答案 2 :(得分:0)

改为使用second derivative test

答案 3 :(得分:0)

我最终编写了自己更简单的findpeaks版本,这似乎符合我的目的。

function [pks,locs] = my_findpeaks(X)      
    M = numel(X);
    pks = [];
    locs = [];
    if (M < 4)
        datamsgid = generatemsgid('emptyDataSet');
        error(datamsgid,'Data set must contain at least 4 samples.');
    else
        for idx=1:M-3
            if X(idx)< X(idx+1) && X(idx+1)>=X(idx+2) && X(idx+2)> X(idx+3)
                pks = [pks X(idx)];
                locs = [locs idx];
            end

        end

    end
end

编辑:为了澄清,问题出现了,当我的峰值正好在两个采样点之间时,这两个采样点的值恰好相同。在超过10,000个案例中,它只发生了几次。

答案 4 :(得分:0)

您描述的行为是R2010b之前的MATLAB版本中的一个已知错误。最小的例子是

findpeaks([0 1 1 0])

返回[],而

findpeaks([0 1 0])

返回峰的(位置)。

该错误已在R2010b和更高版本中修复,请参见官方Bug Report。使用该修复程序,findpeaks返回“具有重复值的峰值”(我称为高原)的上升沿。