2010年12月12日日曜日

Wiiリモコンのジェスチャー認識

3軸加速度は大体分かったところで、次はジェスチャ認識を試してみましょう。
おそらくゲームのキモの部分になるけれど、じっくり調整は後にして当面は出来合いの流用してすましたいところ。

wiiremote gesture recognition で検索するといくつも出てきますね。

フリーソフトウェアとして整っているものは wiigee しか無いようです。
しかしこれは Java で書かれていて、C# XNA とは相性がよろしくない。

C で書かれた WiimoteGR というのもありました。ライセンスは不明。

論文は豊富にありますが、ソフトウェアが公開されているものは少なそう。
基本的には研究室内で使われているコードなんでしょうね。
いずれ書き直すとして、WiimoteGR 使いましょう。

論文は A latest compilation of links to the wiimote のリンク集が良さそうです。
ざっとサーベイしたところ、ニューラルネットはダメで、隠れマルコフモデル(HMM)が主流で、Slow Feature Analysis(SFA) が有望という感じ?


WiimoteGR

パターン認識のアルゴリズムはまだいいけれど、全体の設計は理解しておきます。

main() から処理が始まり、トレーニングをしてテストという流れになっています。
トレーニング時は パターン名を指定して、3軸加速度を何セットか記録。SQLLite で保存。

テスト時は SQLLite から学習データを読み込み、
リモコンのデータを記憶しながら、過去いくつかの入力信号をまとめてパターン認識にかける。

認識器は HMM クラス、隠れマルコフモデルでしょう。
const HMM& HMMLib::Recognize(const vector<HMM>& HMMVec, TimeSlot& seq) { vector<HMM>::const_iterator recognizedHMM = HMMVec.begin(); for(vector<HMM>::const_iterator curHMM = HMMVec.begin()+1; curHMM < HMMVec.end(); curHMM++){ if( SeqLogProb(*curHMM,seq,false) > SeqLogProb(*recognizedHMM,seq,false) ) recognizedHMM = curHMM; } return *recognizedHMM; }
HMMLib は個々のパターンを表す HMM オブジェクトを何組か持っていて、
Recognize() 関数は SeqLogProb() の値が一番大きい HMM を選んで返すようだ。

おそらくこれは、ユーザーがジェスチャで何らかのコマンドを入力するというシーンを想定しているのであろう。
未知の入力対して、一番近いジェスチャパターンを返す。
対して振りゲーの場合、正解となるジェスチャが分かっている。
そのジェスチャとのみ評価を行い、評価値が一定以上ならば正解とする使い方になる。

ところで、テスト部では
while(wiimote.Button.A()){ wiimote.RefreshState(); // Acceleration: tempAcc.x=wiimote.Acceleration.X; tempAcc.y=wiimote.Acceleration.Y; tempAcc.z=wiimote.Acceleration.Z; tempSeq.AddObservableSymbol(defaultQuantizer.Quantize(tempAcc)); cout << trainer.Recognize(loadedHMMVec,tempSeq).gestureName << " "; gestureReceived = true; Sleep(10);//period (ms) } void AddObservableSymbol(size_t obsSymbol){ o.push_back(obsSymbol); }
3軸加速度そのものではなく、量子化(Quantize)した size_t 型の値を使っているようだ。

Quantize() 関数は
size_t DefaultQuantizer::Quantize(const Acceleration& acc) const{ double rho = sqrt(acc.x*acc.x+acc.y*acc.y+acc.z*acc.z); return (rho>rho_threshold? 1<<3 : 0) + (acc.x>acc.y? 1<<2 : 0) + (acc.y>acc.z? 1<<1 : 0) + (acc.z>acc.x? 1 : 0); }
となっていて、4bitのビットベクトルである。ビットの意味は
  • 加速度の大きさが、スレッショルドを超えているかどうか
  • 加速度の X方向成分が Y方向成分よりも大きいかどうか
  • 加速度の Y方向成分が Z方向成分よりも大きいかどうか
  • 加速度の Z方向成分が X方向成分よりも大きいかどうか
後段の 3つは加速度の向きを単純化したもので、最初の1つは大きさを単純化したものである。
3軸加速度そのものは使わずに、パターン認識に必要十分な特徴量へと変換したというわけであろう。
この量子化関数はパターン認識の精度に関わる重要なファクターになりそうだ。

例えば、このコードでは三軸加速度のみを用いているが、M+ のジャイロセンサーを活用できるであろう。
単純に、加速度と同様の手法で角速度を8通りに量子化すればよいのであろうか。
各速度を積分して姿勢を判別し、加速度に向きの補正をかければ良いのであろうか。
しっかり考えないと分からないな。

0 件のコメント:

コメントを投稿