Kinect for Windows v2入門 ― C++プログラマー向け連載(2)
Kinect v2プログラミング(C++) - Color編
Kinect SDK v2で、データを取得する基本的な流れを説明。Color画像を取得するサンプルプログラムを紹介する。正式版に合わせて改訂。
前回は、旧型のKinect for Windows(以下、Kinect v1)と新型のKinect for Windows(以下、Kinect v2)の仕様を比較して紹介した。
今回からは、Kinectから各種データを取得する方法を比較しながら紹介する。
Colorカメラ
Kinectには通常のWebカメラなどと同様にColorカメラが搭載されており、Color画像を取得できる。このColorカメラは、Kinect v1では640×480の解像度であったが、Kinect v2では1920×1080と大幅に解像度が向上している。
今回は、Colorカメラから画像を取得する方法を紹介する。
データを取得する流れ
Kinect SDK v1とKinect SDK v2でデータを取得する基本的な流れを図1に示す*1。
- *1 ここで示すのはあくまでも基本的な流れである。Kinect SDK v2には、複数の「Source」や「Reader」を一括して扱うAPIがあり、ここで紹介するデータを取得する流れとは少し異なることもある。
Kinect SDK v1では、Sensor
からStream
を開き、Stream
からFrame
を取得、Frame
からデータ
を取得するという流れであった。
Kinect SDK v2では、Sensor
からSource
を取得、Source
からReader
を開き、Reader
からFrame
を取得、Frame
からデータ
を取得するという流れになった。
Kinect SDK v2の「Source」は、Kinectから取得するColor
やDepth
といったデータの流れごとに1つ存在する。これは、Kinect SDK v1の「Stream」と同じだ。
Kinect SDK v2では、「Reader」というステップが追加された。「Reader」は1つの「Source」に対して複数開くことができる。この仕様により、マルチスレッドのアプリケーションでは取得したデータを別のスレッドにコピーするといった処理が不要になる、複数のアプリケーションでは同じセンサーからデータを取得できるなどの利点がある。
サンプルプログラム
Kinect SDK v2でColor画像を取得して表示するサンプルプログラムを示す。図1で示したデータを取得するステップごとに抜粋して解説する。このサンプルプログラムの全容は、以下のページで公開している。
このサンプルプログラムでは、画像データを扱うためにOpenCVを用いる。OpenCVの詳細は以下の情報を参照するといいだろう。
また、Kinect SDK v1で同様にColor画像を取得して表示するサンプルプログラムは、筆者の近著『Kinect for Windows SDK実践プログラミング』を参照していただきたい。
「Sensor」
Sensor
を取得する。
// Sensor
IKinectSensor* pSensor; //……1
HRESULT hResult = S_OK;
hResult = GetDefaultKinectSensor( &pSensor ); //……2
if( FAILED( hResult ) ){
std::cerr << "Error : GetDefaultKinectSensor" << std::endl;
return -1;
}
hResult = pSensor->Open(); //……3
if( FAILED( hResult ) ){
std::cerr << "Error : IKinectSensor::Open()" << std::endl;
return -1;
}
|
- 1Kinect v2を扱うためのSensorインターフェース。
- 2デフォルトのSensorを取得する。
- 3Sensorを開く。
「Source」
Sensor
からSource
を取得する。
// Source
IColorFrameSource* pColorSource; //……1
hResult = pSensor->get_ColorFrameSource( &pColorSource ); //……2
if( FAILED( hResult ) ){
std::cerr << "Error : IKinectSensor::get_ColorFrameSource()" << std::endl;
return -1;
}
|
- 1ColorフレームのためのSourceインターフェース。
- 2SensorからSourceを取得する。
「Reader」
Source
からReader
を開く。
// Reader
IColorFrameReader* pColorReader; //……1
hResult = pColorSource->OpenReader( &pColorReader ); //……2
if( FAILED( hResult ) ){
std::cerr << "Error : IColorFrameSource::OpenReader()" << std::endl;
return -1;
}
|
- 1ColorフレームのためのReaderインターフェース。
- 2SourceからReaderを開く。
「Frame」~「Data」
Reader
から最新のFrame
を取得する。
int width = 1920; //……1
int height = 1080; //……1
unsigned int bufferSize = width * height * 4 * sizeof( unsigned char ); //……2
cv::Mat bufferMat( height, width, CV_8UC4 ); //……3
cv::Mat colorMat( height / 2, width / 2, CV_8UC4 ); //……3
cv::namedWindow( "Color" );
while( 1 ){
// Frame
IColorFrame* pColorFrame=nullptr; //……4
hResult=pColorReader->AcquireLatestFrame( &pColorFrame ); //……5
if( SUCCEEDED( hResult ) ){
hResult = pColorFrame->CopyConvertedFrameDataToArray( bufferSize, reinterpret_cast<BYTE*>( bufferMat.data ), ColorImageFormat_Bgra ); //……6
if( SUCCEEDED( hResult ) ){
cv::resize( bufferMat, colorMat, cv::Size(), 0.5, 0.5 ); //……7
}
}
SafeRelease( pColorFrame ); //……8
// Show Window
cv::imshow( "Color", colorMat );
if( cv::waitKey( 30 ) == VK_ESCAPE ){
break;
}
}
|
- 1Color画像のサイズ(1920×1080)。
ここでは説明の簡素化のため画像サイズを決め打ちしているが、サンプルプログラムではSourceからフレーム情報を取得している。 - 2Color画像のデータサイズ。
- 3Color画像を扱うためにOpenCVのcv::Mat型を準備する。
「bufferMat」は生の画像データ、「colorMat」はリサイズした画像データを扱う。
「CV_8UC4」は、符号無し8bit整数(8U)が4channel(C4)並んで1画素を表現するデータ形式。 - 4Color画像を取得するためのFrameインターフェース。
- 5Readerから最新のFrameを取得する。
- 6FrameからColor画像を取得する。
デフォルトのフォーマットはYUY2(=輝度と色差で表現するフォーマット)だが、扱いやすいBGRAに変換して取得する。 - 7縦横それぞれ半分のサイズ(960×540)に縮小する。
- 8Frameを解放する。
内部バッファが解放されて次のデータを取得できる状態になる。
Frame
が取得できたらColor画像のデータ
を取り出し表示する。Kinect SDK v1では画像サイズやフォーマットをあらかじめ指定していたが、Kinect SDK v2では画像サイズを指定することはできない。そのため、データを取得してから任意の形に整える。
取得したColor画像はそのまま表示するにはサイズ(1920×1080)が大きいため、ここではOpenCVのリサイズ命令(cv::resize()
)を用いて縦横それぞれ半分のサイズ(960×540)に縮小している。
取り出したColor画像のデータはBGRAのフォーマットを指定した場合、図2のように並んでいる。青(B)、緑(G)、赤(R)、無効値(A)の合計32bitで1画素を構成している。
実行結果
このサンプルプログラムを実行すると図3のようにKinect v2から取得したColor画像が表示される。
まとめ
今回はKinect SDK v2のデータを取得する基本的な流れとColor画像を取得するサンプルプログラムを紹介した。次回はDepthデータを取得するサンプルプログラムを紹介する。
※以下では、本稿の前後を合わせて5回分(第1回~第5回)のみ表示しています。
連載の全タイトルを参照するには、[この記事の連載 INDEX]を参照してください。
1. Kinect v1とKinect v2の徹底比較
Kinect for Windowsの旧版と、次世代型の新版を比較しながら、進化したハードウェア&ソフトウェアをC++開発者向けに紹介する(正式版に対応させた改訂連載スタート)。今回はセンサー仕様や動作要件を徹底的に比較する。
2. 【現在、表示中】≫ Kinect v2プログラミング(C++) - Color編
Kinect SDK v2で、データを取得する基本的な流れを説明。Color画像を取得するサンプルプログラムを紹介する。正式版に合わせて改訂。
4. Kinect v2プログラミング(C++) - BodyIndex編
Kinect SDK v2で、BodyIndex(人物領域)を取得する方法を、サンプルコードを示しながら説明する(正式版に合わせて改訂)。
5. Kinect v2プログラミング(C++) - Body編
Kinect SDK v2に実装されている主要な機能の紹介は、一通り完了。今回は、Body(人物姿勢)を取得する方法を説明する(正式版に合わせて改訂)。