【问题标题】:Unexpected behaviour of function findpeaks in MATLAB's Signal Processing ToolboxMATLAB 信号处理工具箱中函数 findpeaks 的意外行为
【发布时间】:2010-12-07 12:36:11
【问题描述】:

编辑:其实这不是意外的行为,但我仍然需要一个解决方案。 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

找到那些缺失峰的最佳方法是什么?

【问题讨论】:

标签: matlab signal-processing


【解决方案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

【讨论】:

  • 问题不是我只检测到一个峰,而是我根本没有检测到高峰。
  • @Lucas:是的,这个公式不是很好,过滤解决方案也不能保证解决问题,所以我把它删除了。无论如何,imregionalmax 做你想做的事,但如果有超过 2 个相等的值,它也可以工作。您仍然可能需要先过滤以去除因噪声而产生的局部最大值。
  • imregionalmax 似乎确实有效。我可能仍然使用我自己的函数。
【解决方案2】:

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

您也可以只从高原上的所有值中减去一些非常小的固定值,但第一个值除外。这会导致高原上的每个第一个值始终是各自高原上的最高值,从而将它们作为峰值包含在内。

只需在您的代码中创建类似这样的部分:

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');

希望这会有所帮助!

【讨论】:

    【解决方案3】:

    【讨论】:

      【解决方案4】:

      我最终编写了自己的更简单版本的 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 多个案例中发生过几次。

      【讨论】:

      • 我看不出X(idx+1)&gt; X(idx+1) 是如何评估为真的。一定是哪里有错别字。
      • @Jonas:是的,对不起,你是对的。我采用了旧版本,因为我添加了一些针对我的问题的东西。它包含错误。
      【解决方案5】:

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

      findpeaks([0 1 1 0])
      

      返回[],而

      findpeaks([0 1 0])
      

      返回峰值的(位置)。

      R2010b 及以后的bug已经修复,见官方Bug Report。通过该修复,findpeaks 返回“具有重复值的峰值”的上升沿(我将其称为 plateaus)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-03
        • 1970-01-01
        • 1970-01-01
        • 2020-05-05
        • 2017-12-02
        • 1970-01-01
        相关资源
        最近更新 更多