Loading…

スポンサーサイト

Posted by Tsukasa SUGIURA on --.-- スポンサー広告
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

OpenNI Advent Calendar 2011/12/8 - OpenNIの設定ファイルに関するTips -

Posted by Tsukasa SUGIURA on 08.2011 Kinect   0 comments   0 trackback
※ 本記事はOpenNI Advent Calendar(2011/12/8 http://atnd.org/events/22725)への参加記事です.

【OpenNIの設定ファイルに関するTips】
OpenNIでは一般にデバイスの設定をXMLで記述した設定ファイルを用います.
設定ファイルをソースコードの中で以下のように読み込みOpenNIのコンテキストを初期化します.

xn::Context context;
XnStatus status = context.InitFromXmlFile("../SamplesConfig.xml");
if(status != XN_STATUS_OK){
std::cout << xnGetStatusString(status) << std::endl;
}

このとき,設定ファイルを実行ファイルからの相対パスで指定したりします.
しかし,設定ファイルと実行ファイルのディレクトリ関係が崩れるたりすると,パスの違いにより設定ファイルを読み取ることができなくなります.
設定ファイルを確実に読み取るためには,

1. 設定ファイルをプログラム実行時にユーザーに指定させる.
2. 設定ファイルをソースコード中に埋め込む.

などの方法が考えられます.

1の方法は,設定ファイルをプログラム実行時にダイアログで指定させることで,パスの違いによる設定ファイルの読み取りミスを防ぎます.
設定ファイルは外部ファイルとしてプログラムとは独立しているため,設定を書き換えることも可能になります.
しかし,プログラム実行時にユーザーが毎回指定する煩わしさがあります.

2の方法は,設定ファイルの設定XMLを直接ソースコードの中で記述してしまうことにより,パスの違いによる設定ファイルの読み取りミスを防ぎます.
プログラム実行時に指定する必要も無いため,ユーザーへの煩わしさは感じさせません.
しかし,設定XMLがプログラムに埋め込まれるため,設定を書き換えることができません.

通常の方法(xn::Context::InitFromXmlFile())も含め,メリット/デメリットあるので利用シーンに応じて適切な方法を選ぶ必要があります.
ちなみに,OpenCVのOpenNIサポート(WITH_OPENNI)では2の方法が採用されています.
今回は,2の方法を採用した書き方を紹介します.

【設定ファイルをソースコード中に埋め込む】
以下のページからサンプルプログラム(Sample.cpp)をダウンロードできます.


以下今回の記事内容の部分を抜粋します.(見やすいようにエラー処理等を除いています.)

#include <iostream>
#include <fstream>
#include <XnCppWrapper.h>

const std::string configure = 
"<OpenNI>"
"<Licenses>"
"<License vendor=\"PrimeSense\" key=\"0KOIk2JeIBYClPWVnMoRKn5cdY4=\"/>"
"</Licenses>"
"<Log writeToConsole=\"false\" writeToFile=\"false\">"
"<!-- 0 - Verbose, 1 - Info, 2 - Warning, 3 - Error (default) --->"
"<LogLevel value=\"3\"/>"
"<Masks>"
"<Mask name=\"ALL\" on=\"true\"/>"
"</Masks>"
"<Dumps>"
"</Dumps>"
"</Log>"
"<ProductionNodes>"
"<Node type=\"Image\" name=\"Image1\">"
"<Configuration>"
"<MapOutputMode xRes=\"640\" yRes=\"480\" FPS=\"30\"/>"
"<Mirror on=\"false\"/>"
"</Configuration>"
"</Node> "
"<Node type=\"Depth\" name=\"Depth1\">"
"<Configuration>"
"<MapOutputMode xRes=\"640\" yRes=\"480\" FPS=\"30\"/>"
"<Mirror on=\"false\"/>"
"</Configuration>"
"</Node>"
"<Node type=\"User\"/>"
"<Node type=\"Gesture\"/>"
"<Node type=\"Hands\"/>"
"</ProductionNodes>"
"</OpenNI>";

int main(int argc, char *argv[])
{
// コンテキストの初期化
xn::Context context;
context.Init();
std::ofstream outfile("SamplesConfig.xml");
outfile.write(configure.c_str(), configure.length());
outfile.close();
context.RunXmlScriptFromFile("SamplesConfig.xml");
/* context.RunXmlScript(configure.c_str()); // doesn't work this code, because there is a bug in xn::Context::RunXmlScript(). */
std::remove("SamplesConfig.xml");

細かくは解説しませんが,以下のような流れになっています.

ソースコード中に文字列で設定XMLを記述する.
xn::Context::context.Init()で初期化する.
一度,設定XMLの文字列をxmlファイルとして書きだす.
xn::Context::RunXmlScriptFromFile()でxmlファイルを読み込み,設定する.
書きだしたxmlファイルを削除する.

本来は,わざわざxmlファイルを書きだす必要は無く,xn::Context::RunXmlScript()で直接設定を読み取れますが,現在はxn::Context::RunXmlScript()にバグがあるため動作しません.
xn::Context::RunXmlScript()で動作するようになると,だいぶスッキリしたコードになると思います.

※ デストラクタや最適化との兼ね合いもあると思いますが,出力演算子を使って書けばXMLファイル書き出し部分が2行になります.(明示的に書いた方がいいのかは自信無し(´・ω・`))
std::ofstream outfile("SamplesConfig.xml");
outfile << configure;

【おわりに】
本記事は,OpenCVのWITH_OPENNI実装を読んでいたら便利そうな記述を見つけたので一般化して紹介しました.

【参考文献】
1.) OpenCV/highgui/cap_openni.cpp
2.) OpenNI Documentation http://openni.org/Documentation/
3.) KINECTセンサープログラミング
関連記事
スポンサーサイト


  • password
  • 管理者にだけ表示を許可する

trackbackURL:http://kgxpx834.blog58.fc2.com/tb.php/26-e7e1750c

プロフィール

Tsukasa SUGIURA

Author:Tsukasa SUGIURA
Twitter:@UnaNancyOwen
Mail:t.sugiura0204(あっと)gmail.com
Address:Aichi,JAPAN
Other:Computer Vision, Image Processing, and more...

お問い合わせはコメント欄以外にもメールなどでも受け付けます。お気軽にお問い合わせください。

ほしい物リスト

買ってくれたら私が喜びます。 Amazon.co.jp ほしい物リスト

最新記事

Access Counter

QRコード

QRコード

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