KinectのRecorder機能を使う

Kinectアプリのデバッグは一般的なアプリと違って、わざわざセンサーの前に立って毎回同じような動作をしなければなりません。
先日参加したハッカソンでも、みんなが急に立ち上がって色々動いたり、センサーに向かって手を振ったりと、かなりウケますw

けど、さすがに毎回立ち上がってと、デバッグをしていたら洒落になりません。
そこで便利機能として、Kinectセンサーから取得できた情報を保存して、再生することができます。
これを使えば、毎回立ち上がったり、手を振ったりする必要がなく、デバッグに集中することができます。

チームで開発する時は、各自にKinectを渡さなくても、環境さえ整えればプログラミングが出来て、経費節減にも繋がる!

main.cppの抜粋

1.    xn::Recorder recorder;
2.    if( DO_RECORED && !USE_RECORED_DATA ){
3.        // レコーダーの作成
4.        LOG_I("%s", "Setup Recorder");
5.        nRetVal = recorder.Create(g_Context);
6.        CHECK_RC(nRetVal, "Create recorder");
7.        
8.        // 保存設定
9.        nRetVal = recorder.SetDestination(XN_RECORD_MEDIUM_FILE, RECORD_FILE_PATH);
10.        CHECK_RC(nRetVal, "Set recorder destination file");
11.        
12.        // 深度、ビデオカメラ入力を保存対象として記録開始
13.        nRetVal = recorder.AddNodeToRecording(g_DepthGenerator, XN_CODEC_NULL);
14.        CHECK_RC(nRetVal, "Add depth node to recording");
15.        nRetVal = recorder.AddNodeToRecording(g_ImageGenerator, XN_CODEC_NULL);
16.        CHECK_RC(nRetVal, "Add image node to recording");
17.        
18.        LOG_I("%s", "Recorder setup done.");
19.    }
20.
21.    while (!xnOSWasKeyboardHit())
22.    {
23.        g_Context.WaitOneUpdateAll(g_UserGenerator);
24.        if( DO_RECORED  && !USE_RECORED_DATA ){
25.            nRetVal = recorder.Record();
26.            CHECK_RC(nRetVal, "Record");
27.        }

簡単に説明すると、
・5行目のrecorder.Createでレコーダーを作成しています。
・9行目で、保存先を指定。
・13、15行目で保存するノードを指定します。
・25行目のrecorder.Record()で、毎回データを保存します。
という流れです。


逆に保存されたデータを読み込んで表示する方法は

1.        g_Context.Init();
2.        g_Context.OpenFileRecording(RECORD_FILE_PATH);
3.        xn::Player player;
4.        
5.        // PlayerNodeの取得
6.        nRetVal = g_Context.FindExistingNode(XN_NODE_TYPE_PLAYER, player);
7.        CHECK_RC(nRetVal, "Find player");
8.        
9.        LOG_D("PlaybackSpeed: %d", player.GetPlaybackSpeed());
10.        
11.        xn:NodeInfoList nodeList;
12.        player.EnumerateNodes(nodeList);
13.        for( xn::NodeInfoList::Iterator it = nodeList.Begin();
14.            it != nodeList.End(); ++it){
15.            
16.            if( (*it).GetDescription().Type == XN_NODE_TYPE_IMAGE ){
17.                nRetVal = g_Context.FindExistingNode(XN_NODE_TYPE_IMAGE, g_ImageGenerator);
18.                CHECK_RC(nRetVal, "Find image node");
19.                LOG_D("%s", "ImageGenerator created.");
20.            }
21.            else if( (*it).GetDescription().Type == XN_NODE_TYPE_DEPTH ){
22.                nRetVal = g_Context.FindExistingNode(XN_NODE_TYPE_DEPTH, g_DepthGenerator);
23.                CHECK_RC(nRetVal, "Find depth node");
24.                LOG_D("%s", "DepthGenerator created.");            
25.            }
26.            else{
27.                LOG_D("%s %s %s", ::xnProductionNodeTypeToString((*it).GetDescription().Type ),
28.                      (*it).GetInstanceName(),
29.                      (*it).GetDescription().strName);
30.            }
31.        }

簡単に説明すると
・2行目で保存されているデータを読み込みます
・6行目でPlayerを作成します
・13行目のfor文でPlayerから取り出したノードを調べて、必要なノードからgeneratorを作成します。

これで、保存したファイルからデータを読みながらプログラムを実行することができます。

今回作成したサンプルはgithubに上げてあります。
https://github.com/sparkgene/recorder_test