2016-07-11 6 views
1

Так что я начал на поиски, чтобы подсчитать количество шагов, предпринятых пользователем с помощью данных, я получаю от акселерометра т.е. х, у и Z координаты ,Нахождение локальных максимумов точек данного набора данных

Я пытаюсь реализовать алгоритм this, но в настоящее время я застрял в локальной части максимума. Matlab имеет встроенный метод findpeaks(), который определяет все локальные максимумы заданного набора данных.

Ниже приведена моя попытка реализовать алгоритм, но я по-прежнему получаю от него чрезвычайно большие результаты. Сначала, используя набор данных, который состоял из действительных шагов 20, алгоритм рассчитал, что количество выполненных шагов было 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: формат Datasheet является X, Y, Z, RMS (среднеквадратичное)

+0

Потому что я пытаюсь реализации этой MatLab встроенного в 'findpeaks()' метод в прошивкой – eshirima

+1

В вашем методе 'findPeaks', почему вы это делаете:' peaks.append (max (величины [i], величины [i-1], величины [i + 1])) '? Не следует ли добавлять только значение, если max является «величинами [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

 Смежные вопросы

  • Нет связанных вопросов^_^