2016-07-11 37 views
1

所以我決定出發來計算我從加速度計獲取的使用數據的用戶拍攝的步數即Xÿž座標。尋找局部最大點設定

我想實現this算法,但我目前卡在當地的最大值部分。 Matlab有一個內置的findpeaks()方法,它定位給定數據集的所有局部最大值。

下面是我嘗試實現算法,但我仍然從它得到非常巨大的結果。 首先,使用由實際步驟組成的數據集,該算法計算所採取步驟的數量爲990+。我調整和調試了它,並且我設法將這個數字降低到了660,然後110最終變成了當前的45。目前我只是卡住,並有一種感覺,我的findpeaks()方法是錯誤的。

這是我的類實現

import Foundation 

class StepCounter 
{ 
    private var xAxes: [Double] = [Double]() 
    private var yAxes: [Double] = [Double]() 
    private var zAxes: [Double] = [Double]() 
    private var rmsValues: [Double] = [Double]() 

    init(graphPoints: GraphPoints) 
{ 
    xAxes = graphPoints.xAxes 
    yAxes = graphPoints.yAxes 
    zAxes = graphPoints.zAxes 
    rmsValues = graphPoints.rmsValues 
} 

func numberOfSteps()-> Int 
{ 
    var pointMagnitudes: [Double] = rmsValues 

    removeGravityEffectsFrom(&pointMagnitudes) 

    let minimumPeakHeight: Double = standardDeviationOf(pointMagnitudes) 

    let peaks = findPeaks(&pointMagnitudes) 

    var totalNumberOfSteps: Int = Int() 

    for thisPeak in peaks 
    { 
     if thisPeak > minimumPeakHeight 
     { 
      totalNumberOfSteps += 1 
     } 
    } 

    return totalNumberOfSteps 
} 

// TODO: dummy method for the time being. replaced with RMS values from controller itself 
private func calculateMagnitude()-> [Double] 
{ 
    var pointMagnitudes: [Double] = [Double]() 

    for i in 0..<xAxes.count 
    { 
     let sumOfAxesSquare: Double = pow(xAxes[i], 2) + pow(yAxes[i], 2) + pow(zAxes[i], 2) 
     pointMagnitudes.append(sqrt(sumOfAxesSquare)) 
    } 

    return pointMagnitudes 
} 

private func removeGravityEffectsFrom(inout magnitudesWithGravityEffect: [Double]) 
{ 
    let mean: Double = calculateMeanOf(rmsValues) 

    for i in 0..<magnitudesWithGravityEffect.count 
    { 
     magnitudesWithGravityEffect[i] -= mean 
    } 
} 

// Reference: https://en.wikipedia.org/wiki/Standard_deviation 
private func standardDeviationOf(magnitudes: [Double])-> Double 
{ 
    var sumOfElements: Double = Double() 
    var mutableMagnitudes: [Double] = magnitudes 

    // calculates the numerator of the equation 
    /* no need to do (mutableMagnitudes[i] = mutableMagnitudes[i] - mean) 
    * because it has already been done when the gravity effect was removed 
    * from the dataset 
    */ 
    for i in 0..<mutableMagnitudes.count 
    { 
     mutableMagnitudes[i] = pow(mutableMagnitudes[i], 2) 
    } 

    // sum the elements 
    for thisElement in mutableMagnitudes 
    { 
     sumOfElements += thisElement 
    } 

    let sampleVariance: Double = sumOfElements/Double(mutableMagnitudes.count) 

    return sqrt(sampleVariance) 
} 

// Reference: http://www.mathworks.com/help/signal/ref/findpeaks.html#examples 
private func findPeaks(inout magnitudes: [Double])-> [Double] 
{ 
    var peaks: [Double] = [Double]() 

    // ignore the first element 
    peaks.append(max(magnitudes[1], magnitudes[2])) 

    for i in 2..<magnitudes.count 
    { 
     if i != magnitudes.count - 1 
     { 
      peaks.append(max(magnitudes[i], magnitudes[i - 1], magnitudes[i + 1])) 
     } 
     else 
     { 
      break 
     } 
    } 

    // TODO:Does this affect the number of steps? Are they clumsly lost or foolishly added? 
    peaks = Array(Set(peaks)) // removing duplicates. 

    return peaks 
} 

private func calculateMeanOf(magnitudes: [Double])-> Double 
{ 
    var sumOfElements: Double = Double() 

    for thisElement in magnitudes 
    { 
     sumOfElements += thisElement 
    } 

    return sumOfElements/Double(magnitudes.count) 
} 

}`

有了這個datasheet,所採取的實際步數爲20,但我不斷收到各地45。甚至當我與包括30實際步驟的數據集試了一下,計算出的數量已接近100s.

任何援助/指導,將不勝感激

PS:數據表格式爲XŸžRMS(均方根)

+0

因爲我想實現Matlab的內置'findpeaks()'方法的iOS – eshirima

+1

在你的'findPeaks'方法中,你爲什麼要這樣做:'peaks.append(max(magnitude [i],magnitude [i-1],magnitude [i + 1]))'?如果最大值是[幅度] [i]',你不應該只是追加值嗎? – jjatie

+0

*「他們是笨拙地丟失還是愚蠢地加入?」*兩者。當然,兩個不相關的峯值可能具有相同的值,在這種情況下,您將丟棄有效的峯值。另一方面,如果數據有微小的振盪,你會計算太多的峯值。例如,這個數據在36點有一個峯值,但你會計算出3個峯值:33,34,33,34,35,34,35,36,35,34,35,34,33,34,33。 – user3386109

回答

1

此功能與您所提供的例子。它將高原作爲一個峯值,並允許具有相同值的多個峯值。唯一的問題是 - @ user3386109指出 - 如果數據中有很多小的振盪,你會得到比實際存在更多的峯值。如果你要處理這樣的數據,你可能想在這個計算中實現數據集的變化。

而且,因爲你不改變你傳遞變量是沒有必要使用inout

private func findPeaks(magnitudes: [Double]) -> [Double] { 

    var peaks = [Double]() 
    // Only store initial point, if it is larger than the second. You can ignore in most data sets 
    if max(magnitudes[0], magnitudes[1]) == magnitudes[0] { peaks.append(magnitudes[0]) } 

    for i in 1..<magnitudes.count - 2 { 
     let maximum = max(magnitudes[i - 1], magnitudes[i], magnitudes[i + 1]) 
     // magnitudes[i] is a peak iff it's greater than it's surrounding points 
     if maximum == magnitudes[i] && magnitudes[i] != magnitudes[i+1] { 
      peaks.append(magnitudes[i]) 
     } 
    } 
    return peaks 
} 
+0

非常感謝你。如果我有足夠的S/O代表,我會打破投票按鈕。非常感謝。 – eshirima