简体   繁体   English

除了噪声数据的局部最大值和最小值之外,还找到局部“平坦”

[英]Find local “flat” in addition to local maxima and minima of noised data

There is a time-stress spectrum with 10,000s counts of records.有一个包含 10,000 条记录计数的时间应力谱。

The timestamp-stress was recorded at random frequency from 10e-5 to 1HZ.以 10e-5 到 1HZ 的随机频率记录时间戳压力。

At the beginning I am trying to find:一开始我试图找到:

  • Local peak and valley, with fluctuation higher than certain threshold (say 0.6 unit).局部峰谷,波动高于一定阈值(比如0.6个单位)。
  • Just an extreme simple way to filt out some noise and record noticeable changes in pressure.只是一种极其简单的方法,可以滤除一些噪音并记录压力的显着变化。

I searched the web and common approach is de-noise and find local maxima and minima.我搜索了 web,常用的方法是去噪并找到局部最大值和最小值。

On the other hand, the legacy code I have implemented in the following way (in Javascript).另一方面,我以以下方式(在 Javascript 中)实现的遗留代码。

  function filtSpectrum(res, minor){  
    var filted = []; //array of filted minor cycles
    var lookformax = 1; // 1 for look for max, 0 for look for min
    var currentstress;
    var mx_index = 0;
    var mn_index = 0;
  
    for (var i=0; i < arrayLength; i++){
      currentstress = res[i].psi;
      if(currentstress > res[mx_index].psi){
        mx_index = i;
      }
      if (currentstress < res[mn_index].psi){
        mn_index = i;
      }
      if(lookformax === 1){
        if(currentstress < res[mx_index].psi - minor){
          filted.push(res[mx_index]);
          mn_index = i;
          lookformax =0;
        }
      }else if (currentstress > res[mn_index].psi + minor){
        filted.push(res[mn_index]);
        mx_index = i;
        lookformax = 1;
      }
    }
    return filted;
  }

It has no issue to output the results like the following picture output 没有问题,结果如下图直线被过滤,曲线是原始信号

Now the spectrum is represented by peak - valley type of points.现在频谱由峰 - 谷类型的点表示。

But there are some area in the middle if the picture that are flat .但是如果图片中间有一些区域是平坦的。 The oversimplification ignored the flat area and misrepresent the slope / (or frequency) of the peak and valleys.过度简化忽略了平坦区域并歪曲了峰谷的斜率/(或频率)。

Is there some simple algorithm to convert the original signal into peak-flat-valley kind of representation?是否有一些简单的算法可以将原始信号转换为峰平谷类型的表示?

I am rather new to DSP.我对DSP相当陌生。 Thanks in advance for any suggestions and feedbacks.提前感谢您的任何建议和反馈。

Just like the red dashed flat line in the following image.就像下图中的红色虚线一样。 在此处输入图像描述

One idea would be to:一个想法是:

  • Always select the very first and last points of your series总是 select 你的系列的第一个和最后一个点
  • Look for the point that deviates the most from the line through those two end points, and select that point as well.寻找与这两个端点的直线偏差最大的点,以及该点的 select。
  • Split the series into two at that newly selected point, such that this point is the last one in the first subseries, and the first in the second subseries.在新选择的点将系列分成两部分,这样该点是第一个子系列中的最后一个,第二个子系列中的第一个。 Then use recursion to apply the above algorithm for these two subseries.然后使用递归将上述算法应用于这两个子系列。
  • Stop the recursion when the largest deviation found is smaller than the threshold.当找到的最大偏差小于阈值时停止递归。 In that case only keep the end points.在这种情况下,只保留端点。

Here is an implementation, with a demo on a data set that is similar to what you pictured in your question, but it is structured as a simple array of [x, y] pairs, as I couldn't completely see from your question how your data is structured (but y seems to correspond to psi ):这是一个实现,其中包含与您在问题中所描绘的类似的数据集的演示,但它的结构是[x, y]对的简单数组,因为我无法从您的问题中完全看出如何您的数据是结构化的(但y似乎对应于psi ):

 function simplify(polyline, maxdy) { function recur(first, last) { let [x0, y0] = polyline[first]; let [x1, y1] = polyline[last]; let m = (y1 - y0) / (x1 - x0); let localMaxdy = 0; let choice = 0; for (let i = first + 1; i < last; i++) { let [x, y] = polyline[i]; let dy = Math.abs(y0 + m*(x - x0) - y); if (dy > localMaxdy) { choice = i; localMaxdy = dy; } } return localMaxdy < maxdy? [[x0, y0]] // Only keep first point: recur(first, choice).concat(recur(choice, last)); } return recur(0, polyline.length - 1).concat(polyline.slice(-1)); // always add last point } const ctx = document.querySelector('canvas').getContext('2d'); function drawPolyline(polyline, color) { ctx.lineWidth = 1.5; ctx.strokeStyle = color; ctx.beginPath(); for (const [x, y] of polyline) ctx.lineTo(x, y); ctx.stroke(); } // Demo let data = [[0,0],[81.5,1.5],[97.5,7.5],[98,8.5],[113,10.5],[113.5,12],[123,10.5],[127.5,12],[131.5,13.5],[132.5,15.5],[133,10],[133.5,30],[136,14.5],[138,15.5],[139.5,20],[140.5,21.5],[141,33],[149,35.5],[149.5,37.5],[152,40],[152.5,41],[159.5,45],[167.5,46],[171.5,47.5],[208,48.5],[290.5,52.5],[322,56.5],[330.5,64.5],[335,66],[345,63.5],[347.5,61.5],[352,65],[362.5,66.5],[367.5,64.5],[369.5,66],[386,65],[390,66],[391,67.5],[392,76],[394,80],[396,151.5],[396.5,154],[398,155],[400,159],[401.5,152.5],[402.5,140],[403.5,137.5],[405.5,180],[407.5,168],[409,139.5],[410,129.5],[412,126.5],[413.5,127.5],[415,123],[415.5,117],[416.5,114],[417.5,105.5],[419,102.5],[419.5,96],[420.5,91.5],[422.5,89.5],[423.5,78],[424.5,71.5],[426,69],[429,77],[432,43.5],[433,50.5],[434,52.5],[435.5,51.5],[436,54.5],[439,57],[440.5,60.5],[442.5,58.5],[444.5,58],[446,56],[447,51.5]]; drawPolyline(data, "grey"); let simple = simplify(data, 10); drawPolyline(simple, "red");
 <canvas width="500" height="180"></canvas>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM