2012-06-29 8 views
9

私はKinect for Windows SDKを使って(C#で)アプリケーションを作成するのに苦労しています。KinectセンサーデータからBPMを計算する

基本的には、指揮者の片手(通常は右手)をトラッキングし、MIDIを介してこの値を他のアプリケーションに送るために指揮(BPM)のスピードを認識する必要があります。私が始めた何

が更新され、最初のエントリを削除している歴史ListDateTime.Now.TicksタイムスタンプとともにJointType.HandRightを追加SkeletonFramesReadyEventです。私は60フレーム(2秒)の履歴を保持します。

Joint.Position.Yの最後の低および高を検索してBPMを計算し、その差を計算してbpm = 60*ticksPerSecond/diffを除算します。しかし、結果は間違っています。これを行う別の方法がありますか?私は何が欠けていますか?私はそれを行う方法を考え出し

public int DetectBPM(JointType type) 
{ 
    // we have not history yet 
    if (!HasHistory()) return 0; 

    // only calculate every second 
    var detectTime = DateTime.Now.Second; 
    if (_lastBPM != 0 && _lastBPMDectect == detectTime) return _lastBPM; 

    // search last high/low boundaries 
    var index = (int) type; 
    var list = History[index]; 
    var i = list.Count - 1; 

    var lastHigh = list[i]; 
    var lastLow = list[i]; 

    // shift to last peak first 
    while (i > 0 && list[i].Joint.Position.Y >= list[i - 1].Joint.Position.Y) i--; 

    // find last low 
    while (i >= 0 && lastLow.Joint.Position.Y >= list[i].Joint.Position.Y) lastLow = list[i--]; 

    // find last high 
    while (i >= 0 && lastHigh.Joint.Position.Y <= list[i].Joint.Position.Y) lastHigh = list[i--]; 

    var ticks = lastLow.Timestamp - lastHigh.Timestamp; 
    var elapsedTime = new TimeSpan(ticks); 

    var bpm = (int) (60000/elapsedTime.TotalMilliseconds); 

    Console.WriteLine("DEBUG: BPM = " + _lastBPM + ", elapsedMS: " + elapsedTime.TotalMilliseconds); 

    _lastBPMDectect = detectTime; 
    _lastBPM = bpm; 

    return _lastBPM; 
} 
+3

どのような結果が得られていますか、どのような結果が期待されていますか? – mlorbetske

+0

DEBUG:BPM = 512、elapsedMS:328 DEBUG:BPM = 182、elapsedMS:-322 DEBUG:BPM = -186、elapsedMS:-337 DEBUG:BPM = -178、elapsedMS:299 DEBUG:BPM = 200 、elapsedMS:683 DEBUG:BPM = 87、elapsedMS:-378 DEBUG:BPM = -158、elapsedMS:92 – fdomig

+1

まず、 'ticks 'の計算の違いの周りに' Math.Abs​​() 'を使用しているはずです'(それは負の値を考慮に入れます)。 'Timestamp'はティックではなく、ミリ秒単位なので、' new TimeSpan(ticks) 'の代わりに' TimeSpan.FromMilliseconds(ticks) 'を使います(おそらく' ticks'の名前を変更します)。 – mlorbetske

答えて

2

は、これは私がこれまで使用していますものです。私はポイントを逃していて、間違っている手のピークと低い位置の間でBPMを計算しました。私は正しい結果を得るために最後の2つの低い点の時間差を計算しなければなりません。

正しい方法は、最後のピークである開始点を見つけることです。そこから最後の低い値に移動すると、これは最初のポイントからの差を計算します。次のピークに移動し、次のローに再び移動します。これは、2つ目のポイントからの差を計算します。とにかく参加するための

var ticks = Math.Abs(firstLow.Ticks - secondLow.Ticks); 
var elapsedTime = new TimeSpan(ticks); 

var bpm = (int) (60000/elapsedTime.TotalMilliseconds); 

ありがとう:

原理は

BPM calucaltion schema

そしてうまくBPMの結果は次のように計算され、以下の図に示します。

+0

あなたのデータが騒々しい場合、最小値の検出は疑わしいものになります。あなたはちょうど1つのチックだけ離れてローカルミニマを得るかもしれません。これは、おそらくあなたのデータをスムーズにする必要があると言っている理由です(可能性のあるKinectは、あなたのためにそれを平滑化していますが、データのグラフを見るのは難しいです。)また、ほとんどの時間はうまくいきます。それから失敗します。 –

+0

データは、特定のKinect設定で既に平滑化されています。 – fdomig

関連する問題