2012-02-07 64 views
0

我基本上有一堆數據對象,它們將時間戳以毫秒爲單位映射到浮點值。我期待從本質上找到給定範圍內數據的峯值/最大值。我一直在使用這樣的東西:因式分解算法中的噪音

float previousValue = 0; 
for (int i = 0; i < data.size(); i++) { 
    MyData value = data.get(i); 
    if (value.getData() < previousValue) { 
     // found the peak! 
     break; 
    } else { 
     previousValue = value.getData(); 
    } 
} 

這個算法的唯一問題是,它沒有考慮到噪聲。從本質上講,我可以有值是這樣的:

[0.1025, 0.3000, 0.3025, 0.3500, 0.3475, 0.3525, 0.1025] 

的實際峯值在0.3525,但我上面的算法將它看作0.3500,因爲它是第一位的。由於我的計算性質,我不能只在數組上做max()並找出最大的值,我需要找到在它下降之前最先出現的最大值。

我怎樣才能找到我的高峯的頂部,同時考慮到噪音方面的一些差異?

+0

你如何定義峯值? .3500之後的值和.3525之後的值下降。有什麼不同? – 2012-02-07 18:44:27

+0

分離問題:首先,使用滑動窗口和平均數據 - 這將消除噪音。之後,您可以輕鬆地使用您的或任何其他方法查找峯值。 – alf 2012-02-07 18:45:27

回答

1

有兩個問題:

  1. 濾除噪聲;
  2. 尋找高峯。

好像你已經有2的解決方案,並需要解決1

爲了濾除噪聲,你需要某種low-pass filter。 A moving average就是這樣一個過濾器。例如,exponential moving average很容易實現,應該運行良好。

總結:把你的系列過濾器,然後應用峯值查找算法。

+0

那麼低通濾波器將擺脫跳動值並讓我回到更線性的結果?我怎樣才能寫過濾器?當談到數學時,我很無能。 – 2012-02-08 20:12:45

0

找到在數組中的單峯(或最高值)(任何數值數組:整數,雙)更簡單的方法是遍歷所述陣列和設置爲最高值的變量...

實施例:(所有的實施例使用稱爲「數據」的浮子陣列)

float highest = 0; //use a number equal to or below the lowest possible value 
for (int i = 0; i < data.length; i++){ 
    if (data[i] > highest){ 
     highest = data[i]; 
    } 
} 

找到在嘈雜的數據多峯濾波部分噪音出我使用這種方法:

boolean[] isPeak = new boolean[20]; // I am looking for 20 highest peaks 
float[] filter = new float[9]; // the range to which I want to define a peak is 9 
float[] peaks = new float[20]; // again the 20 peaks I want to find 
float lowpeak = 100; // use a value higher than the highest possible value 
// first we start the filter cycling through the data 
for (int i = 0; i < data.length; i++){ 
    for (int a = filter.length-1; a > 0; a--){ 
     filter[a] = filter[a-1]; 
    } 
    filter[0] = data[1] 
    // now we check to see if the filter detects a peak 
    if (filter[4]>filter[0] && filter[4]>filter[1] && filter[4]>filter[2] && 
      filter[4]>filter[3] && filter[4]>filter[5] && filter[4]>filter[6] && 
      filter[4]>filter[7] && filter[4]>filter[8]){ 
     // now we find the lowest peak 
     for (int x = 0; x < peaks.lengt-1; x++){ 
      if (peaks[x] < lowpeak){ 
       lowpeak = peaks[x]; 
      } 
     } 
     // now we check to see if the peak is above the lowest peak 
     for (int x = 0; x < peaks.length; x++){ 
      if (peaks[x] > lowpeak && peaks[x] != peaks[x+1]){ 
       for (int y = peaks.length-1; y > 0 && !isPeak[y]; y--){ 
       peaks[y] = peaks[y-1]; 
       } 
       peaks[0] = filter[4]; 
      } 
     } 
    } 
} 

可能不是最有效的方法,但它可以完成工作!