2010年12月22日水曜日

ビデオの再生方法を調べる

さてジェスチャーの見通しが立ったかなと。
このままジェスチャーからやってもいいのだけれど、アルゴリズムが長くて少しだれてきた。

ビデオ再生

少し方向を変えて、ビデオを表示してみよう。
今の時代ともなると、ビデオは簡単に再生できるライブラリがあるんじゃないかなと期待。


microsoft.xna.framework.media

XNAでは、media 以下に VideoPlayer や Video というクラスがある。

ビデオの現在の絵をエフェクトとして取り出すことができるので、これを貼り付ければいい。
protected override void Draw(GameTime gameTime) {
  _effect.Texture = _player.GetTexture();

このクラスでは、動画はコンテントの仕組みでプログラムに組み込まなければならないようだ。
さらに、コーデックが WMV に限定されている。
コンテントについてはローダ部分を書けばファイルから取れるかもしれないけれど、コーデックはどうしようもない。


DirectShow

COMベースのメディアフレームワーク。元々は DirectX の一部だった。
フィルタパターンで美しそうな設計だ。
コーデックは、対応したソースフィルタを開発し、フィルタグラフに載せることで対応できる。

ただし、C# から使えるラッパは LGPL のしか無いようで、LGPL にしないなら自前で書かないとならない。


Media Foundation

DirectShow の後継で、Vista 以降専用。
現状で DirectShow との差異は、HD動画、DRM対応、効率向上といったところなのかな。


うーん…

DirectShow か MediaFramework か。
MediaFramework は新しいこと以外にこれといってメリットもなさそうだ。
このために WinXP を捨てるのはペイしないなぁ。

DirectShow にするとして、開発環境をどうしよう。
ラッパ使ってもいいのだけれど何とも釈然としない。

技術的にできることが政治的にできないのはムカムカするんだよな。

2010年12月21日火曜日

MMD の kinect 対応

キタ!


ここまでは時間の問題であったわけですが、予想以上に早い。

2010-11-04 米国で kinect 発売
PCで動かせるようになるまで数週間かなぁ
2010-11-10 オープンソースドライバ公開
2010-11-19 MS, Kinect のオープン利用を容認
2010-11-20 JST 日本で kinect 発売
誰かが MMD 対応するだろうけど、モーションデータを PMD 形式にするだけでも一ヶ月はかかりそうだな
2010-12-08 OpenNI 公開。スケルトントラッキング!
2010-12-13 樋口MのMMD+Kinect動画。作者キター! リアルタイム!
2010-12-19 MMD+Kinect 公開
※日付は現地時刻。




さっそく遊んでみましたw

モーションデータも配布してますので、MMD屋さん興味あったらどうぞ。


MMD+Kinect 動作までの流れ

忘れないうちにメモ。

1. Kinect USB インターフェースを用意。

以前も書いたけれど、XBOX360+Kinect バンドルパックだと USB 端子が無くて、サポセンに電話して4000円でケーブル買わないとならないので注意してください。

2. OpenNI, NITE のインストール

OpenNINITE をダウンロードしてインストール。

Kinect ドライバのインストール

https://github.com/avin2/SensorKinect の Bin/SensorKinect-Win32-5.0.0.exe をダウンロードして実行します。

※注: 上記のバイナリは、https://github.com/ros-pkg-git/Sensor でソースコード配布されている OpenNI PrimeSense モジュールを第三者がコンパイルしたものです。
OpenNI の方がこなれてくれば、簡単なインストーラが配布されるでしょうから、そちらを利用してください。

環境変数

マイコンピュータのシステムの環境変数で、
  • XN_SENSOR_VENDOR_ID の値を 0x045E
  • XN_SENSOR_PRODUCT_ID の値を 0x02AE
で新規登録。 Windows での環境変数の反映のタイミングを知らないので、ここで一旦再起動。

Kinect の接続とテスト

Kinect を PC に繋ぎます。USBハブなどは経由せずに、直接PCに挿してください。 OpenNI のインストールディレクトリ(C:\Program Files\OpenNI かな)以下の、Samples\Bin\Release\NiViewer.exe を起動。
しばらくすると、フルスクリーンになって、Kinect の見ている映像が表示されれば成功です。
ダメだったら頑張ってくださいw

MMDインストール

VPVPから、MMD 7.24 と DxOpenNI をダウンロード。 MMD は適当な場所に展開。 次に、MMD の Data フォルダに、DxOpenNI に同梱されている
  • DxOpenNI.dll
  • SamplesConfig.xml
をコピー。

MMD起動

  1. Help メニューから Kinect をチェックして、
  2. 両腕を上げるポーズをとる
キャプチャなどは 樋口さんの説明動画 を見てください。

さぁこれで君もミクミクだ。

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通りに量子化すればよいのであろうか。
各速度を積分して姿勢を判別し、加速度に向きの補正をかければ良いのであろうか。
しっかり考えないと分からないな。

2010年12月10日金曜日

ダンガンロンパ

久しぶりにゲームクリアしましたよと。

ダンガンロンパ、PSP のアドベンチャーゲームです。
シナリオは閉鎖空間固定メンバーで次々に殺人が起きていくサスペンス。
ゲーム的には逆転裁判みたいな議論の矛盾を突いていくものです。

まずはシステムから。
本質的には逆転裁判と同じで、アクションの味付けがされています。
逆裁は長く議論続くとだれちゃうところありますが、ダンガンロンパはちょくちょくアクションが変わるので飽きにくい感じですね。
ちょいとルールが多すぎるきらいはありますが、なかなか楽しいゲームシステムになっていると思います。

さて、シナリオ。
評価ポイントは、ミステリの基本である動機とトリック、そして脱出モノとして舞台設定という三本ですかね。
ひどいってほどではないけれど、正直及第点は付けられないなぁ。

トリックは簡単。死体発見のタイミングで謎の半分は予想付きます。
さらに調査パートで大部分が分かり、議論パートまで分からないのはひとつふたつ。
次々に暴いていくという快感には欠けますね。

さらに「モノクマ」というゲームマスター的なキャラがいまして、ちょくちょくコントロールしてくれちゃいます。
「この事件に共犯者はいない」とか「DVDのこの先は見ちゃダメ」とか。
正直白けます。

動機はとってつけたようなもの。
残る世界設定も、ラノベ的非現実さとご都合主義で置いてけぼり感が強い。
グループ脱出モノとでも言うのかな。
たとえば去年出た「9時間9人9の扉」と色々とかぶります。
999もご都合主義的なルールが多いんですが、シナリオやキャラクターでうまく説明していて白けないよう努力している。
ダンガンはちょっと手抜きがすぎる気がしますねぇ。

おそらく売りでもある演出面があります。
これまたエキセントリックなキャラクタ付け、残虐描写、有名声優などなど、エッジを効かせているんでしょうね。
すいません、悪趣味で権威主義にしか思えませんでした。
悪趣味の気分悪さを感じさせるのは意図的なのは分かります。
でもそんな偽悪的な手法はもうありきたりで、そこからは一歩も出ていないですね。

まとめ。
法廷パートだけでもまぁ楽しめます。
これだけなら可は付けられるかな。
しかし演出などがマイナスに働いて、総合すると満足度は低いです。