スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Kinect+OpenNIでMMDを動かしてみた

Kinect+OpenNIを使って、MMDでモーションキャプチャの様なことをさせよう!、という企画です。

MMDのIK機能を利用して、簡単な実装を行ったものを動画にしました↓


以下、動画と同じことをするために必要なことを解説し、その後現在の問題点等を挙げます。



<解説>

1.OpenNIとドライバのインストール

まずは、kinectを使うためのドライバと、ボーン認識機能を提供しているOpenNIをインストールします。
もちろん、その前にkinectは用意して下さいね。

totakke website様の記事「OpenNI: WindowsでKinectを使う」で詳しく説明されているので、上記サイトを参照して下さい。
ただし、このサイトで説明されているインストール順番は若干怪しく、OpenNIを先にインストールしてからやった方が良いと思います。




2.腕IK入りのMMDモデルを作る

次に、PMDエディタとIK Makerを使って、使用するモデルの腕や足にIKを追加します。
これによって、位置情報のみからモデルをある程度操作することが可能になります。

paperguitar.com「腕IK作成-ギターストラップインストール手順」
に動画付の分かりやすい解説があるので、そちらを参照してIKを追加して下さい。

なお、動作に必要なDirectXランタイムは、普通のDirectXとは別物らしいので、動かない場合はランタイムの方のインストールを確認して下さい。


追加すべきIKは、「右腕IK、右腕IK先、左腕IK、左腕IK先」です。
(足のIKが無いモデルでは、足系のIKも全て追加して下さい。)


なお、このやり方では使用できないモデルがあります。
例えば、初音ミク標準モデルver2では、同じ方法で腕IKを追加したにも関わらず、正常な動作はしませんでした。

動作を確認したのは、初音ミク標準モデルと咲音メイコ標準モデルです。
とりあえずは、初音ミク標準モデルで試されるのが、無難だと思います。




3.VMDConverterのダウンロード

MMDのモーションファイルとcsv形式のファイルの相互変換を行ってくれる、VMDConverter
をダウンロードしてきます。

csv形式のファイルはこんな感じです。

Vocaloid Motion Data 0002 0
初音ミクIK
1149
センター 0 0 0 0 0 0 0 0x14141414141414146B6B6B6B6B6B6B6B141414141414146B6B6B6B6B6B6B6B011414141414146B6B6B6B6B6B6B6B010014141414146B6B6B6B6B6B6B6B000000
右足IK 0 0 0 0 0 0 0 0x14141414141414146B6B6B6B6B6B6B6B141414141414146B6B6B6B6B6B6B6B011414141414146B6B6B6B6B6B6B6B010014141414146B6B6B6B6B6B6B6B000001
左足IK 0 0 0 0 0 0 0 0x14141414141414146B6B6B6B6B6B6B6B141414141414146B6B6B6B6B6B6B6B011414141414146B6B6B6B6B6B6B6B010014141414146B6B6B6B6B6B6B6B000002
右腕IK 0 0 0 0 0 0 0 0x14141414141414146B6B6B6B6B6B6B6B141414141414146B6B6B6B6B6B6B6B011414141414146B6B6B6B6B6B6B6B010014141414146B6B6B6B6B6B6B6B000003
左腕IK 0 0 0 0 0 0 0 0x14141414141414146B6B6B6B6B6B6B6B141414141414146B6B6B6B6B6B6B6B011414141414146B6B6B6B6B6B6B6B010014141414146B6B6B6B6B6B6B6B000004
センター 1 0.0110628 -0.0175928 -0.00531413 0 0 0 0x14141414141414146B6B6B6B6B6B6B6B141414141414146B6B6B6B6B6B6B6B011414141414146B6B6B6B6B6B6B6B010014141414146B6B6B6B6B6B6B6B000005
右足IK 1 -0.000152049 0.00649809 -0.0020988 0 0 0 0x14141414141414146B6B6B6B6B6B6B6B141414141414146B6B6B6B6B6B6B6B011414141414146B6B6B6B6B6B6B6B010014141414146B6B6B6B6B6B6B6B000006
左足IK 1 0.000911668 0.0285853 -0.00121663 0 0 0 0x14141414141414146B6B6B6B6B6B6B6B141414141414146B6B6B6B6B6B6B6B011414141414146B6B6B6B6B6B6B6B010014141414146B6B6B6B6B6B6B6B000007
右腕IK 1 0.0787494 0.149375 -0.0125334 0 0 0 0x14141414141414146B6B6B6B6B6B6B6B141414141414146B6B6B6B6B6B6B6B011414141414146B6B6B6B6B6B6B6B010014141414146B6B6B6B6B6B6B6B000008
左腕IK 1 0.0209193 -0.00686816 -0.00621338 0 0 0 0x14141414141414146B6B6B6B6B6B6B6B141414141414146B6B6B6B6B6B6B6B011414141414146B6B6B6B6B6B6B6B010014141414146B6B6B6B6B6B6B6B000009



0
0
0


各要素の意味は、ソフト付属の図を参照してください。
この形式に合わせて、ボーンのデータを取り出すプログラムを用意することになります。




4.サンプルコードの改造

OpenNIには、NiUserTrackerというボーン認識のサンプルプログラムが用意されています。
このサンプルを改造し、VMDConverter形式のデータを出力する様にします。

サンプル内、g_UserGenerator.GetSkeletonCap().GetSkeletonJointPosition()関数で各関節の位置を取得できます。

1つ目の引数は、対象となるユーザ情報を与えます。

ユーザ情報は、以下の様に取得できるようです。
XnUserID aUsers[15];
XnUInt16 nUsers = 15;
g_UserGenerator.GetUsers(aUsers, nUsers);


2つ目の引数は、間接の位置を指定する定数を与えます。

XN_SKEL_TORSO:胴体
XN_SKEL_RIGHT_HIP:右股関節
XN_SKEL_RIGHT_FOOT:右足首


DrawDepthMap()関数の中を見れば、どの定数がどこに対応しているか分かると思います。


3つ目の引数には、取得した位置を保存する変数を与えます。


VMDConverter形式のデータを出力する部分は例えば以下の様に書きます。


void jointOutputForMMD(XnSkeletonJointPosition joint, XnSkeletonJointPosition firstJoint, std::string mmdJointName)
{
if(joint.fConfidence < 0.5) // データの正確性?
return;

double dx = joint.position.X - firstJoint.position.X;
double dy = joint.position.Y - firstJoint.position.Y;
double dz = joint.position.Z - firstJoint.position.Z;

g_ofs << mmdJointName.c_str() << "," << g_keyCnt << "," << -dx/170 << "," << dy/130 << "," << dz/300
<< ",0,0,0,0x14141414141414146B6B6B6B6B6B6B6B141414141414146B6B6B6B6B6B6B6B011414141414146B6B6B6B6B6B6B6B010014141414146B6B6B6B6B6B6B6B"
<< std::setw(6) << std::setfill('0') << g_cnt++ << std::endl;
}


なお、上の関数でもあるようにMMDには、初期位置からの変化を与える必要があるので、
ボーン認識した後に自分でMMDの初期位置と同じポーズを取ってキャリブレーションする必要があります。

今回は適当に、ボーン認識を開始してから2秒後の間接位置を保存し、それとの差を出力するようにしました。
こんな感じで実装しました↓

g_UserGenerator.GetSkeletonCap().GetSkeletonJointPosition(aUsers[i], XN_SKEL_TORSO, joint);
if(isFirst){ g_firstPoseJoint[0] = joint;}
jointOutputForMMD(joint, g_firstPoseJoint[0], "センター");



※注意
MMDでは、手はセンターに追従したボーンになっているので、センターの移動分を考慮してやる必要があります。
手の移動量 - センターの移動量で問題ないと思いますが、まだ試していません。
(動画編集して気がつきましたorz)



5.出力データ→モーションファイル→MMD

プログラムを実行し、データを取得します。
出力したデータをVMDConverterでモーションファイルに変換し、先程用意した腕IK入りのモデルを読み込んだMMDに流し込みます。
後は、再生するなり、調整するなり自由に弄って下さい。




<現在の問題点>

・足先・手先のIKを使っているので、肘・膝の位置が意図したものにならないことがある。
・体の向き等の情報が一切使えない。
・OpenNI座標→MMD座標という変換のパラメータが適当。
・ボーンの長さを考慮していない。


<問題を解決するためには>

・OpenNIで取得可能な情報を増やす。(角度の扱いを理解していない)
・MMDに角度をどうやって与えればよいか知る。(私は理解していない)
・IKを各関節に配置したモデルを作る。(それで動くのかは不明。後、IKMakerで標準的に用意されているIK以外追加の仕方を理解していない)

前途多難ですな。
関連記事

theme : 初音ミク
genre : 音楽

comment

Secret

trackback


この記事にトラックバックする(FC2ブログユーザー)

Kinectでモーションキャプチャ

Kinectでモーションキャプチャ
プロフィール

シロマ=ナノ

Author:シロマ=ナノ
参加予定イベント:
 ・C91 3日目西め28a

DIVA-AC:
 LV.199 白のシンフォニア

Flashカレンダー
Twitter
カテゴリ
最新記事
PCLクレジット
当ブログは、ピアプロ・キャラクター・ライセンス(http://piapro.jp/license/pcl)に基づいて、クリプトン・フューチャー・メディア株式会社のキャラクター 「初音ミク」「鏡音リン」「鏡音レン」「巡音ルカ」「Meiko」「Kaito」及びそれらに依拠して制作されたキャラクター「亞北ネル」「弱音ハク」を描いた作品を公開しています。
アクセスカウンター
検索フォーム
主な作品
WindowHelper(フリーソフト)
WindowHelperポップ

描いた絵・イラスト
リンク
バナー
当サイトはリンクフリーです。
バナーを使用したい場合は以下の画像をお使い下さい。
(リンク先に200x40サイズを置いてあります)

・通常版
banner

・ミク版
banner
RSSリンクの表示
ブロとも申請フォーム

この人とブロともになる

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。