ブログ@kaorun55

HoloLensやKinectなどのDepthセンサーを中心に書いています。

OpenNI2(Beta) 入門(1) :Colorカメラの画像を表示する

さっそくいじってみます。

環境は次の通りです

とりあえずコンソールアプリでプロジェクトを作ります。OpenNI2(Beta) をインストールすると、ヘッダーパス(OPENNI2_INCLUDE)およびライブラリパス(OPENNI2_LIB)が環境変数に追加されていますので、これをVCのプロパティに設定します。OpenNI2(Beta)のライブラリはOpenNI2.libです。

で、次のコードを実行するとカラーカメラの画像が表示されます。なお、実行時には、exeの場所に、OpenNI2(Beta)のサンプルフォルダ(ここでは「C:\Program Files (x86)\OpenNI2\Samples\Bin」)にある「OpenNI2」フォルダをコピーし、VCのデバッグ時の作業パスを$(OutDir)に設定します。

#include <OpenNI.h>

#include <opencv2\opencv.hpp>

#include <vector>

void main()

{

try {

openni::OpenNI::initialize();

openni::Device device;

auto ret = device.open( openni::ANY_DEVICE );

if ( ret != openni::STATUS_OK ) {

throw std::runtime_error( "" );

}

openni::VideoStream colorStream;

colorStream.create( device, openni::SensorType::SENSOR_COLOR );

colorStream.start();

std::vector<openni::VideoStream*> streams;

streams.push_back( &colorStream );

cv::Mat colorImage;

while ( 1 ) {

int changedIndex;

openni::OpenNI::waitForAnyStream( &streams[0], streams.size(), &changedIndex );

if ( changedIndex == 0 ) {

openni::VideoFrameRef colorFrame;

colorStream.readFrame( &colorFrame );

if ( colorFrame.isValid() ) {

colorImage = cv::Mat( colorStream.getVideoMode().getResolutionY(),

colorStream.getVideoMode().getResolutionX(),

CV_8UC3, (char*)colorFrame.getData() );

}

cv::cvtColor( colorImage, colorImage, CV_BGR2RGB );

cv::imshow( "Color Camera", colorImage );

int key = cv::waitKey( 10 );

if ( key == 'q' ) {

break;

}

}

}

}

catch ( std::exception& ) {

std::cout << openni::OpenNI::getExtendedError() << std::endl;

}

}

OpenNIとKinect for Windows SDKの中間のような作りになっているようです。

まず openni::OpenNI::initialize() でOpenNIを初期化します。続いて、openni::Deviceクラスを定義し、openni::Device::open() でデバイスを開きます。この時、引数にはデバイスのURIを指定しますが、ここでは最初に見つけたデバイスを開きます。

続いて、openni::VideoStream クラスを定義し、openni::VideoStream::create() でストリームの作成、openni::VideoStream::start() でストリームを開始します。

メインループでは openni::OpenNI::waitForAnyStream() を呼び出してストリームの更新を待ちますが、この関数が openni::VideoStream** (openni::VideoStreamのポインタの配列)を引数にとるため、std::vector<openni::VideoStream*> を定義し、ストリームへのポインタを追加します。openni::OpenNI::waitForAnyStream()は更新されたストリームのインデックスが返すので、該当ストリームの処理を行います。ここではカラーカメラのみとなります。

更新されたカラーカメラのフレームは openni::VideoStream::readFrame()を呼び出して、openni::VideoFrameRef で受け取ることができます。openni::VideoFrameRef::isValid() でフレームの妥当性を確認し、データを取得します。カラーカメラの画像は openni::VideoFrameRef::getData()で、カラーカメラ解像度は openni::VideoStream::getVideoMode().getResolutionY()(またはgetResolutionX())で取得することができます。

OpenNI1に比べて簡潔なコードで記述でき、Kinectも設定なしで利用できるので、とても使いやすくなっています。

ちなみにもちろんXtionでも全く同じコードで動きます。ただし、解像度がデフォルトで320x240になってるみたいですね。