Kinect開(kāi)發(fā)教程二:OpenNI讀取深度圖像與彩色圖像
大家應(yīng)該發(fā)現(xiàn)Kinect上長(zhǎng)了三只眼睛,其中一個(gè)是彩色攝像頭,另外兩個(gè)深度攝像頭,一個(gè)負(fù)責(zé)發(fā)射紅外光,一個(gè)負(fù)責(zé)接收,這樣,我們便能通過(guò)Kinect得到一幅彩色圖像和一幅深度圖像。現(xiàn)在小斤來(lái)講下第一個(gè)范例,就是是通過(guò)OpenNI得到彩色和深度圖像咯,代碼不長(zhǎng),其中一部分參考了Heresky童鞋的文章《透過(guò) OpneNI 合併 Kinect 深度以及彩色影像資料》,此外,又補(bǔ)充了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)在我們來(lái)解釋一下:
【1】<XnCppWrapper.h>便是OpenNI的文件頭了,使用OpenNI的話(huà),目前只要include這個(gè)就行。
【2】DepthGenerator和ImageGenerator,小斤稱(chēng)之為圖像生成器,前者負(fù)責(zé)深度圖像,后者負(fù)責(zé)彩色圖像。創(chuàng)建一個(gè)生成器非常簡(jiǎn)單,首先我們要初始化一個(gè)Context上下文,然后把Context作為Create函數(shù)的參數(shù),便可以創(chuàng)建生成器了。
【3】XnMapOutputMode是用來(lái)設(shè)定生成器的參數(shù)的,這邊小斤設(shè)定了分辨率為640*480(標(biāo)準(zhǔn)),30fps采樣。
【4】depthGenerator.GetAlternativeViewPointCap().SetViewPoint( imageGenerator)這句話(huà)也許會(huì)讓大家疑惑,它是用來(lái)調(diào)整視角的。為什么要調(diào)整呢?因?yàn)镵inect的三只眼長(zhǎng)在不同的地方,所以畫(huà)幅一致的深度攝像頭和彩色攝像頭,它們看出來(lái)的景物是有偏差的,這里OpenNI提供了函數(shù)進(jìn)行對(duì)齊。這里,小斤把深度生成器的視角,設(shè)定為彩色生成器的視角。
【5】調(diào)用StartGeneratingAll()后,生成器們便開(kāi)始上班了,如果要結(jié)束,就StopGeneratingAll()函數(shù)。
【6】盡管生成器們?cè)诠ぷ髁?,但他們一直忙著各讀各的,沒(méi)有人協(xié)調(diào),自己不會(huì)乖乖把最新的資料給我們。我們調(diào)用getMetaData()方法前,需要使用WaitAnyUpdateAll()、WaitOneUpdateAll()、WaitNoneUpdateAll()和WiatAndUpdateAll()中的一種。功能如其名,這邊小斤使用的是WaitNoneUpdateAll()函數(shù),它比較暴力,不管生成器有沒(méi)有讀到新數(shù)據(jù),我這邊先更新了再說(shuō)。大家可以試試其它三個(gè),看看效果。
【7】這邊使用OpenNI獲得圖像MetaData數(shù)據(jù)后,小斤通過(guò)一系列函數(shù),轉(zhuǎn)換為OpenCV的IplImage圖像類(lèi)型,然后輸出。
對(duì)于深度MetaData,這邊使用cvConvertScale轉(zhuǎn)換尺度,成為灰度值[0,255]的灰度圖。對(duì)于彩色MetaData,使用cvCvtColor轉(zhuǎn)換色彩空間即可。按ESC鍵可以退出循環(huán),結(jié)束程序。
最終效果如下:
在灰度圖中灰度值0顯示為黑色,255為白色,所以,離Kinect近的地方(桌面)顯示為黑色,中間為不同程度的灰色,遠(yuǎn)處(天花板)顯示為白色。(精彩Kinect資訊請(qǐng)繼續(xù)關(guān)注納金網(wǎng)http://trusteddivorcelawyers.com/)
-
分享到:
您需要登錄后才可以發(fā)帖 登錄 | 立即注冊(cè)
- 用戶(hù)名:
- 密 碼:
- 驗(yàn)證碼: 看不清? 點(diǎn)擊更換
- 忘記密碼?
全部評(píng)論:0條