2016-07-11 4 views
1

Also habe ich auf der Suche begonnen, die Anzahl der Schritte, die von einem Benutzer unter Verwendung der Daten, die ich von dem Beschleunigungsmesser erhalten genommen zu berechnen, dh x, y und z Koordinaten .Finding lokale Maximalpunkte eines gegebener Datensatz

Ich versuche, this Algorithmus zu implementieren, aber ich bin derzeit bei den lokalen Maxima Teil stecken. Matlab hat eine eingebaute findpeaks() Methode, die alle lokalen Maxima eines gegebenen Datensatzes lokalisiert.

Unten ist mein Versuch, den Algorithmus zu implementieren, aber ich bekomme immer noch extrem enorme Ergebnisse daraus. Zuerst, mit einem Datensatz, der aus 20 tatsächlichen Schritten bestand, berechnete der Algorithmus, dass die Anzahl der Schritte 990+ war. Ich zwickte und debuggte und es gelang mir, diese Nummer auf 660 .. dann 110 schließlich zu einem aktuellen 45 zu bringen. Momentan stecke ich einfach fest und habe das Gefühl, dass meine findpeaks() Methode falsch ist.

Dies ist meine Klasse Implementierung

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) 
} 

} `

Mit diesem datasheet, die tatsächliche Anzahl der Schritte war genommen 20 aber ich bekomme immer wieder um 45. Selbst wenn ich es mit einem Datensatz versucht, die von 30 tatsächlichen Schritten besteht, wurde die berechnete Anzahl Annäherung der 100s.

Jede mögliche Unterstützung/Beratung sehr geschätzt

PS sein wird: Datenblatt Format ist X, Y, Z , RMS (root mean square)

+0

zu verwenden, weil ich versuche, die Matlab eingebaute in 'findpeaks()' Methode in iOS – eshirima

+1

zu implementieren Warum machst du das in deiner "findPeaks" -Methode: 'peaks.append (max (Größen [i], Größen [i - 1], Größen [i + 1]))'? Sollten Sie nicht nur den Wert anhängen, wenn das Maximum "Magnituden [i]" ist? – jjatie

+0

* "Sind sie plump verloren oder dummerweise hinzugefügt?" * Beide. Es ist durchaus möglich, dass zwei nicht verwandte Peaks den gleichen Wert haben. In diesem Fall werden Sie gültige Peaks wegwerfen. Auf der anderen Seite, wenn die Daten winzige Schwingungen haben, zählen Sie zu viele Spitzen. Zum Beispiel haben diese Daten eine Spitze bei 36, aber Sie werden 3 Spitzen zählen: 33,34,33,34,35,34,35,36,35,34,35,34,33,34,33. – user3386109

Antwort

1

Diese Funktion arbeitet mit dem Beispiel, das Sie zur Verfügung gestellt. Es behandelt Plateaus als einen Peak und ermöglicht mehrere Peaks mit demselben Wert. Das einzige Problem ist wie - @ user3386109 weist darauf hin - wenn es viele kleine Oszillationen in den Daten gibt, werden Sie mehr Spitzen als wirklich dort erhalten. Möglicherweise möchten Sie die Varianz des Datasets in dieser Berechnung implementieren, wenn Sie mit solchen Daten arbeiten.

Auch, weil Sie nicht die Variable ändern Sie dort passieren besteht keine Notwendigkeit 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

DANKE SOOOOO VIEL..SERIOUS. Ich hätte den Up-Vote-Button aufgebrochen, wenn ich genug S/O-Wiederholungen hätte. ICH DANKE DIR SEHR. – eshirima