Kinect開發(fā)教程二:OpenNI讀取深度圖像與彩色圖像
大家應(yīng)該發(fā)現(xiàn)Kinect上長了三只眼睛,其中一個是彩色攝像頭,另外兩個深度攝像頭,一個負責(zé)發(fā)射紅外光,一個負責(zé)接收,這樣,我們便能通過Kinect得到一幅彩色圖像和一幅深度圖像?,F(xiàn)在小斤來講下第一個范例,就是是通過OpenNI得到彩色和深度圖像咯,代碼不長,其中一部分參考了Heresky童鞋的文章《透過 OpneNI 合併 Kinect 深度以及彩色影像資料》,此外,又補充了OpenCV的顯示部分,使范例更為直觀。
- #include <stdlib.h>
- #include <iostream>
- #include <string>
- //【1】
- #include <XnCppWrapper.h>
- #include "opencv/cv.h"
- #include "opencv/highgui.h"
- using namespace std;
- using namespace cv;
- void CheckOpenNIError( XnStatus result, string status )
- {
- if( result != XN_STATUS_OK )
- cerr << status << " Error: " << xnGetStatusString( result ) << endl;
- }
- int main( int argc, char** argv )
- {
- XnStatus result = XN_STATUS_OK;
- xn::DepthMetaData depthMD;
- xn::ImageMetaData imageMD;
- //OpenCV
- IplImage* imgDepth16u=cvCreateImage(cvSize(640,480),IPL_DEPTH_16U,1);
- IplImage* imgRGB8u=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
- IplImage* depthShow=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
- IplImage* imageShow=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
- cvNamedWindow("depth",1);
- cvNamedWindow("image",1);
- char key=0;
- //【2】
- // context
- xn::Context context;
- result = context.Init();
- CheckOpenNIError( result, "initialize context" );
- // creategenerator
- xn::DepthGenerator depthGenerator;
- result = depthGenerator.Create( context );
- CheckOpenNIError( result, "Create depth generator" );
- xn::ImageGenerator imageGenerator;
- result = imageGenerator.Create( context );
- CheckOpenNIError( result, "Create image generator" );
- //【3】
- //map mode
- XnMapOutputMode mapMode;
- mapMode.nXRes = 640;
- mapMode.nYRes = 480;
- mapMode.nFPS = 30;
- result = depthGenerator.SetMapOutputMode( mapMode );
- result = imageGenerator.SetMapOutputMode( mapMode );
- //【4】
- // correct view port
- depthGenerator.GetAlternativeViewPointCap().SetViewPoint( imageGenerator );
- //【5】
- //read data
- result = context.StartGeneratingAll();
- //【6】
- result = context.WaitNoneUpdateAll();
- while( (key!=27) && !(result = context.WaitNoneUpdateAll( )) )
- {
- //get meta data
- depthGenerator.GetMetaData(depthMD);
- imageGenerator.GetMetaData(imageMD);
- //【7】
- //OpenCV output
- memcpy(imgDepth16u->imageData,depthMD.Data(),640*480*2);
- cvConvertScale(imgDepth16u,depthShow,255/4096.0,0);
- memcpy(imgRGB8u->imageData,imageMD.Data(),640*480*3);
- cvCvtColor(imgRGB8u,imageShow,CV_RGB2BGR);
- cvShowImage("depth", depthShow);
- cvShowImage("image",imageShow);
- key=cvWaitKey(20);
- }
- //destroy
- cvDestroyWindow("depth");
- cvDestroyWindow("image");
- cvReleaseImage(&imgDepth16u);
- cvReleaseImage(&imgRGB8u);
- cvReleaseImage(&depthShow);
- cvReleaseImage(&imageShow);
- context.StopGeneratingAll();
- context.Shutdown();
- return 0;
- }
現(xiàn)在我們來解釋一下:
【1】<XnCppWrapper.h>便是OpenNI的文件頭了,使用OpenNI的話,目前只要include這個就行。
【2】DepthGenerator和ImageGenerator,小斤稱之為圖像生成器,前者負責(zé)深度圖像,后者負責(zé)彩色圖像。創(chuàng)建一個生成器非常簡單,首先我們要初始化一個Context上下文,然后把Context作為Create函數(shù)的參數(shù),便可以創(chuàng)建生成器了。
【3】XnMapOutputMode是用來設(shè)定生成器的參數(shù)的,這邊小斤設(shè)定了分辨率為640*480(標準),30fps采樣。
【4】depthGenerator.GetAlternativeViewPointCap().SetViewPoint( imageGenerator)這句話也許會讓大家疑惑,它是用來調(diào)整視角的。為什么要調(diào)整呢?因為Kinect的三只眼長在不同的地方,所以畫幅一致的深度攝像頭和彩色攝像頭,它們看出來的景物是有偏差的,這里OpenNI提供了函數(shù)進行對齊。這里,小斤把深度生成器的視角,設(shè)定為彩色生成器的視角。
【5】調(diào)用StartGeneratingAll()后,生成器們便開始上班了,如果要結(jié)束,就StopGeneratingAll()函數(shù)。
【6】盡管生成器們在工作了,但他們一直忙著各讀各的,沒有人協(xié)調(diào),自己不會乖乖把最新的資料給我們。我們調(diào)用getMetaData()方法前,需要使用WaitAnyUpdateAll()、WaitOneUpdateAll()、WaitNoneUpdateAll()和WiatAndUpdateAll()中的一種。功能如其名,這邊小斤使用的是WaitNoneUpdateAll()函數(shù),它比較暴力,不管生成器有沒有讀到新數(shù)據(jù),我這邊先更新了再說。大家可以試試其它三個,看看效果。
【7】這邊使用OpenNI獲得圖像MetaData數(shù)據(jù)后,小斤通過一系列函數(shù),轉(zhuǎn)換為OpenCV的IplImage圖像類型,然后輸出。
對于深度MetaData,這邊使用cvConvertScale轉(zhuǎn)換尺度,成為灰度值[0,255]的灰度圖。對于彩色MetaData,使用cvCvtColor轉(zhuǎn)換色彩空間即可。按ESC鍵可以退出循環(huán),結(jié)束程序。
最終效果如下:
在灰度圖中灰度值0顯示為黑色,255為白色,所以,離Kinect近的地方(桌面)顯示為黑色,中間為不同程度的灰色,遠處(天花板)顯示為白色。(精彩Kinect資訊請繼續(xù)關(guān)注納金網(wǎng)http://m.594ljc.cn/)
-
分享到:
全部評論:0條