2011/04/13

Kinectプチハック

【ミッション: Kinectのカメラ映像をIplImageに変換して使おう】

前回のあらすじOpenNI を入れた

Kinect のカメラ、及び深度データを OpenCV で使うための最小限のソースコードをこの辺で見つけたので、さっそく試してみた。

自分の環境に合わせてじゃっかんソースコードを書き換えたが、概ねそのままである(下記のコードは、Visual Studio と OpenCV 2.0 のコンビネーションじゃないとうまく動かない気がする。特にライブラリのバージョンに注意)。
これで、Kinect から労せずしてカメラ映像を取得する事ができるようになった。

……と見せかけて、上記のサンプルコードのままでは(僕にとって)多少問題がある

この段階で、画像データは OpenCV の汎用行列クラスである cv::Mat のオブジェクトとして扱えるようになるのだが、このページの情報によると、 cv::Mat のメンバである step の値が、4 バイト単位に調整されなくなるという不都合が残っているらしい。

以前書いたような Windows API との連携を考えた場合、画像の管理には素性がはっきりしている IplImage 構造体を用いた方が、面倒も少なくて済むだろう。

僕がてきとうに調べた限り、Kinect から取ってきた画像データを直に IplImage に変換するような先人のソースコードを見つける事はできなかった。

それでも、恐らく需要はあるかも知れないと思い、ちょっと作ってみることに。



もしかしたら少々面倒かなぁと思ったのだが、意外とあっけなくできたので掲載しておく。
  1. #include<cv.h>  
  2. #include<highgui.h>  
  3. #include<XnCppWrapper.h>  
  4.   
  5. #pragma comment(lib,"C:/Program files/OpenNI/Lib/openNI.lib")  
  6.   
  7. const char* SAMPLE_XML_PATH = "C:/Program Files/OpenNI/Data/SamplesConfig.xml";  
  8.   
  9. int main() {  
  10.     xn::Context context;  
  11.     xn::EnumerationErrors errors;  
  12.   
  13.     context.InitFromXmlFile(SAMPLE_XML_PATH);  
  14.     
  15.     xn::ImageGenerator image; // イメージコンテキスト  
  16.     context.FindExistingNode(XN_NODE_TYPE_IMAGE, image);  
  17.   
  18.     xn::ImageMetaData imageMD;  
  19.   
  20.     int key = 0;  
  21.   
  22.     // 大人の事情で、IplImageで管理することに。  
  23.     cv::Ptr<IplImage> iplimage;  
  24.     iplimage = cvCreateImage(cvSize(640, 480),IPL_DEPTH_8U,3);  
  25.    
  26.     while (key!='q') {  
  27.         // waitとエラー処理  
  28.         context.WaitAnyUpdateAll();  
  29.   
  30.         // 画像メタデータ取得  
  31.         image.GetMetaData(imageMD);  
  32.           
  33.         // IplImageにデータを格納  
  34.         iplimage->imageData = (char *)imageMD.WritableData();  
  35.         cvCvtColor(iplimage, iplimage, CV_RGB2BGR);  
  36.   
  37.         // iplImageはcvShowImageで表示  
  38.         cvShowImage("hoge", iplimage);  
  39.   
  40.         key = cv::waitKey(33);  
  41.     }  
  42.   
  43.     context.Shutdown();  
  44.     return 0;  
  45. }  
なお、cv::Mat オブジェクト宣言時、コンストラクタに IplImage 構造体を渡す事によって、事実上 IplImage から cv::Mat への変換は容易に可能である。 Kinect から取ってきた映像データは一度 IplImage に格納しておくのがよいだろう。

cv::imshow ではなく、cvShowImage 関数で IplImage を表示した結果は次の通りである。
ちゃんと画像を取ってくる事ができたので、あとは OpenCV で煮るなり焼くなりできる。

0 件のコメント:

コメントを投稿

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