2011/05/24

『Kinectセンサープログラミング』買ってきた

【同時上映: ユーザー検出でバグってみた】

今日は、世界で初めて Kinect プログラミングを解説した技術書の発売日である。

ぼくはこれがすごく気になり、予約開始とともに Amazon に注文をして発売日を今か今かと待ちわびていたほどだった。

しかし突如として Amazon は予約を一方的にキャンセル。さらに「この本はお取り扱いできません」状態が今なお続いている。


仕方なくジュンク堂書店に行ってみたところ、出来たての『Kinect センサープログラミング』が折よく品出し用のワゴンに載っていたので早速ゲットして意気揚々と帰途についた。

『Kinect センサープログラミング』 ¥3,200 (税別)

さてさて。

 Kinect に関しては、このブログでもちょこちょこ言及してきたけれど、いかんせんぼくの調べ方が適当すぎて細かい誤解がいっぱいあった。

その中でも今回は、特に致命的だった事柄について述べたいと思う。



今までは、奥行き情報から 3 次元再構成を行う話をしてきたので、そろそろ心機一転モーションキャプチャ的な事もやりたいなぁと思い、『3.2.7 ユーザーの検出をする(p.117)』を試してみる事にした。

これは、カメラに写った人間を識別し、色分けして表示するというものである。

余談だが、これを画像処理のみで実現しようとすると、一般物体認識手法というなかなかに高度なテクを駆使しなければならない。 Kinect は、赤外線センサーという画期的アプローチによって、この問題を易々とクリアしてしまった。

閑話休題。

本に載っていたサンプルコードを忠実に入力し、ビルド。

処理系がなんか警告を発しているが、そこはまぁ本質ではないので気にしない。

問題は、プログラム起動直後に例外が catch されて即死するという事である。
KinectTest.exe0x76a6fbae で初回の例外が発生しました: Microsoft C++ の例外: std::runtime_error (メモリの場所 0x0029f8a0)。
スレッド 'Win32 スレッド' (0x1ad8) はコード 0 (0x0) で終了しました。
スレッド 'Win32 スレッド' (0x1abc) はコード 0 (0x0) で終了しました。
プログラム '[2224] KinectTest.exe: ネイティブ' はコード 0 (0x0) で終了しました。
こんなエラーメッセージだけを見たところで分かるわけなどないので、適当なところにブレークポイントを設定し、てきとうにデバッガで調べる事に。

その結果、どうやらバグの原因は
  1. // ユーザーの作成  
  2. xn::UserGenerator user;  
  3. rc = context.FindExistingNode(XN_NODE_TYPE_USER, user);  
  4. if(rc != XN_STATUS_OK) {  
  5.     throw std::runtime_error(xnGetStatusString(rc));  
  6. }  
らしい事が判った。

上記コード中に出てくる変数 context は、SamplesConfig.xml という XML ファイルによって初期化されている。

心当たりがあるとすれば、OpenNI を導入する際に参考にした 『OpenNI: WindowsでKinectを使う(※2011年5月24日現在閲覧不可)』 というページに、

4. 設定ファイルの書き変え

・OpenNIの設定ファイル 
[avin2-SensorKinect-*******]/OpenNI/Dataの中身をコピーし、
C:/Program Files/OpenNI/Dataにペーストしてください。
という記述があり、それをそのまま信じてしまった覚えがある。

これ以外に考えられない。



というわけで、SamplesConfig.xml をテキストエディタで開いてみたら、こんなカオスな感じになってしまっていて愕然とした。

  1. <OpenNI>  
  2.     <Licenses>  
  3.         <!-- Add licenses here   
  4.         <License vendor="vendor" key="key"/>  
  5.         -->  
  6.     </Licenses>  
  7.     <Log writeToConsole="true" writeToFile="false">  
  8.         <!-- 0 - Verbose, 1 - Info, 2 - Warning, 3 - Error (default) -->  
  9.         <LogLevel value="3"/>  
  10.         <Masks>  
  11.             <Mask name="ALL" on="false"/>  
  12.         </Masks>  
  13.         <Dumps>  
  14.         </Dumps>  
  15.     </Log>  
  16.     <ProductionNodes>     
  17.         <!-- Normal Image -->  
  18.         <Node type="Image" name="Image1">  
  19.             <Configuration>  
  20.                 <MapOutputMode xRes="640" yRes="480" FPS="30"/>  
  21.                 <Mirror on="true"/>  
  22.             </Configuration>  
  23.         </Node>   
  24.       
  25.         <!-- HighRes Image -->  
  26.         <!--  
  27.         <Node type="Image" name="Image1">  
  28.             <Configuration>  
  29.                 <MapOutputMode xRes="1280" yRes="1024" FPS="15"/>  
  30.                 <Mirror on="true"/>  
  31.             </Configuration>  
  32.         </Node>  
  33.         -->  
  34.           
  35.         <!-- Normal IR -->  
  36.         <!--  
  37.         <Node type="IR" name="IR1">  
  38.             <Configuration>  
  39.                 <MapOutputMode xRes="640" yRes="480" FPS="30"/>  
  40.                 <Mirror on="true"/>  
  41.             </Configuration>  
  42.         </Node>  
  43.         -->  
  44.           
  45.         <!-- HighRes IR -->  
  46.         <!--  
  47.         <Node type="IR" name="IR1">  
  48.             <Configuration>  
  49.                 <MapOutputMode xRes="1280" yRes="1024" FPS="15"/>  
  50.                 <Mirror on="true"/>  
  51.             </Configuration>  
  52.         </Node>       
  53.         -->  
  54.           
  55.         <Node type="Depth" name="Depth1">  
  56.             <Configuration>  
  57.                 <MapOutputMode xRes="640" yRes="480" FPS="30"/>  
  58.                 <Mirror on="true"/>  
  59.             </Configuration>  
  60.         </Node>  
  61.         <!--  
  62.         <Node type="Audio" name="Audio1">  
  63.         </Node>  
  64.         -->  
  65.     </ProductionNodes>  
  66. </OpenNI>  

どう見ても User ノードなんて存在しないわけで、そりゃエラーになるわけだ。

そこで、ひとまず SamplesConfig.xml を以下の内容に差し替えた。

  1. <OpenNI>  
  2.     <Licenses>  
  3.         <License vendor="PrimeSense" key="0KOIk2JeIBYClPWVnMoRKn5cdY4=" />  
  4.     </Licenses>  
  5.     <Log writeToConsole="false" writeToFile="false">  
  6.         <!-- 0 - Verbose, 1 - Info, 2 - Warning, 3 - Error (default) -->  
  7.         <LogLevel value="1"/>  
  8.         <Masks>  
  9.             <Mask name="ALL" on="false"/>  
  10.         </Masks>  
  11.         <Dumps>  
  12.         </Dumps>  
  13.     </Log>  
  14.     <ProductionNodes>  
  15.         <Node type="Image" name="Image1">  
  16.             <Configuration>  
  17.                 <MapOutputMode xRes="640" yRes="480" FPS="30"/>  
  18.             </Configuration>  
  19.         </Node>  
  20.         <Node type="Depth" name="Depth1">  
  21.             <Configuration>  
  22.                 <MapOutputMode xRes="640" yRes="480" FPS="30"/>  
  23.             </Configuration>  
  24.         </Node>  
  25.         <Node type="Scene"/>  
  26.         <Node type="User"/>  
  27.         <Node type="Gesture"/>  
  28.         <Node type="Hands"/>  
  29.     </ProductionNodes>  
  30. </OpenNI>  



再チャレンジ!

今度はうまくいった。


パーカーを着たたーせるが検出されて、きもちわるい緑色に着色されている。

おっと、そこに先生(青)もやってきた。


2人とも、かなり精度よく検出されている。

やったね!



【肝心の中身をてきとうにレビューするコーナー】

ざっと目を通してみて、ぼくは OpenNI と NITE の API リファレンスとサンプルコード集みたいだなぁという印象を受けた。

ぼくにとってこの2つは得体の知れないライブラリであり、ぶっちゃけ今までわけがわからないまま使っていた。だから、詳細を日本語で確認できる貴重な情報源として非常に価値の高い一冊だと思う。

こんなに買ってよかったと思えた本に出会えたのは久しぶりである。

ちなみにこの本では、『Kinect から取ってきたデータを OpenCV でレンダリングする』というのが基本方針なのだけど、あくまで解説の焦点は OpenNI と NITE なので、前提知識として OpenCV の初歩的な理解がないと厳しいだろうなぁと感じた。

また、対象読者を中級者向けに設定しているという事もあり、少なくともコールバックとか関数ポインタとかそういった概念を理解していないような人は迂闊に手を出すべきではない。あと C++ の基本的な文法も。

表紙と帯がけっこうポップなので、どちらかというとゲーマー寄りのプログラミング初心者が、『これさえ読めばすぐに光学迷彩を作れるようになる』と勘違いして衝動買いしてしまわないかと余計な心配をしてしまう。

とはいえ。

それまで日本語の情報が慢性的に欠乏していた Kinect プログラミングだけど、この本の登場によって開発の敷居がぐっと下がるだろうと予想している。

Amazon は早く予約を再開すればいいと思うよ。



21時37分追記: キャンセル扱いにされたはずの Amazon から、まさかのご注文発送メールが届いた。

もう既にジュンク堂で同じものを買ってしまったので、Amazon からの荷物は受け取り次第そのまま返品させて頂く事にした。

0 件のコメント:

コメントを投稿

ひとことどうぞφ(・ω・,,)