OpenNI的深度图显示有主要有两种方法:
1.深度值直接赋值方法(同上一篇):
缺点:深度图层次不明显,主要由于位移操作导致
- #include <stdlib.h>
- #include <iostream>
- #include <string>
- #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);
- //----------------------------------------------------------------------
- //---------------转换为Mat操作,3种方式----------------------------
- //------------------------------------------------------------------------
- if(depthMD.Data()!=NULL)
- {
- //方法【1】通过Mat定义
- //convert ImageMetaData to Mat
- uchar *q = (uchar *) imageMD.Data();
- Mat rgbMat1(480,640,CV_8UC3,q);
- Mat rgbMatShow1;
- cvtColor(rgbMat1,rgbMatShow1,CV_RGB2BGR);
- imshow("testColorMat",rgbMatShow1);
- //convert DepthMetaData to Mat
- unsigned short* p = (unsigned short*) depthMD.Data();
- Mat depthMat1(480,640,CV_16SC1,p);
- Mat depthMatShow1(480,640,CV_8UC1);
- convertScaleAbs(depthMat1,depthMatShow1,255/4096.0);//这一步很重要;
- normalize(depthMatShow1,depthMatShow1,255,0,CV_MINMAX);
- imshow("testDepthMat",depthMatShow1);
- //方法【2】通过坐标(x,y),ImageMetaData貌似不太支持;
- Mat depthMat2(480,640,CV_16SC1);
- Mat depthMatShow2(480,640,CV_8UC1);
- UINT16* depth_p;
- for (int y=0; y<480; y++)
- {
- depth_p = depthMat2.ptr<UINT16>(y);
- for (int x=0; x<640; x++)
- {
- depth_p[x]=(UINT16)depthMD(x,y);//核心赋值
- }
- }
- convertScaleAbs(depthMat2,depthMatShow2,255/4096.0);//这一步很重要;
- normalize(depthMatShow2,depthMatShow2,255,0,CV_MINMAX);
- imshow("testDepthMat2",depthMatShow2);
- //方法【3】通过指针操作;
- //RGB
- Mat rgbMat3(480,640,CV_8UC3);
- Mat rgbMatShow3;
- uchar *rgb_p;
- UINT8 *src_p;
- src_p = (UINT8*) imageMD.Data();
- for (int y=0; y<480; y++)
- {
- rgb_p = rgbMat3.ptr<uchar>(y);
- for (int x=0; x<640; x++)
- {
- *rgb_p++ =(uchar) *src_p++;
- *rgb_p++ =(uchar) *src_p++;
- *rgb_p++ =(uchar) *src_p++;
- }
- }
- cvtColor(rgbMat3,rgbMatShow3,CV_RGB2BGR);
- imshow("testColorMat3",rgbMatShow3);
- Mat depthMat3(480,640,CV_16SC1);
- Mat depthMatShow3(480,640,CV_8UC1);
- UINT16* depthSrc_p;
- uchar* depth3_p;
- depthSrc_p = (UINT16*)depthMD.Data();
- for (int y=0; y<480; y++)
- {
- depth3_p = depthMatShow3.ptr<uchar>(y);
- for (int x=0; x<640; x++)
- {
- depth3_p[x]= (uchar)((*depthSrc_p)*255/4096);//
- depthSrc_p++;
- }
- }
- //convertScaleAbs(depthMat3,depthMatShow3,255/4096.0);//这一步很重要;
- normalize(depthMatShow3,depthMatShow3,255,0,CV_MINMAX);
- imshow("testDepthMat3",depthMatShow3);
- }
- //OpenCV output
- // ----------------------------------------------------------------------
- // ---------------转换为IplImage操作----------------------------
- // ------------------------------------------------------------------------
- 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);
- }
- }
2.通过NiSample的直方图赋值方法:
优点:生成的深度图层次比较明显。
代码附带深度阈值分割
- #include <stdlib.h>
- #include <iostream>
- #include <string>
- #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;
- //【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
- // 若使用imageGenerator则深度图有一圈黑
- depthGenerator.GetAlternativeViewPointCap().SetViewPoint( depthGenerator );
- //【5】
- //read data
- result = context.StartGeneratingAll();
- //【6】
- result = context.WaitNoneUpdateAll();
- Mat depthMat1u(480,640,CV_8UC1);
- Mat depthMat3u(480,640,CV_8UC3);
- char key=0;
- while((key!=27) && !(result = context.WaitNoneUpdateAll()) )
- {
- //get meta data
- depthGenerator.GetMetaData(depthMD);
- imageGenerator.GetMetaData(imageMD);
- //直接Mat赋值操作
- uchar *q = (uchar *) imageMD.Data();
- Mat rgbMat1(480,640,CV_8UC3,q);
- Mat rgbMatShow1;
- cvtColor(rgbMat1,rgbMatShow1,CV_RGB2BGR);
- imshow("testColorMat",rgbMatShow1);
- //通过OpenNI Sample 中 NUISampleViewer 的 pDepthHist[*pDepth]操作.
- XnDepthPixel nZRes = depthMD.ZRes();
- float* pDepthHist = (float*)malloc(nZRes * sizeof(float));
- const XnDepthPixel* pDepth = depthMD.Data();
- xnOSMemSet(pDepthHist, 0, nZRes*sizeof(float));
- unsigned int nNumberOfPoints = 0;
- for (XnUInt y = 0; y < depthMD.YRes(); ++y)
- {
- for (XnUInt x = 0; x < depthMD.XRes(); ++x, ++pDepth)
- {
- if (*pDepth != 0)
- {
- pDepthHist[*pDepth]++;
- nNumberOfPoints++;
- }
- }
- }
- for (int nIndex=1; nIndex<nZRes; nIndex++)
- {
- pDepthHist[nIndex] += pDepthHist[nIndex-1];
- }
- if (nNumberOfPoints)
- {
- for (int nIndex=1; nIndex<nZRes; nIndex++)
- {
- pDepthHist[nIndex] = (unsigned int)(256 * (1.0f - (pDepthHist[nIndex] / nNumberOfPoints)));
- }
- }
- const XnDepthPixel* pDepthRow = depthMD.Data();
- for (XnUInt y = 0; y < depthMD.YRes(); ++y)
- {
- const XnDepthPixel* pDepth = pDepthRow;
- uchar* depthMat1u_p = depthMat1u.ptr<uchar>(y);
- for (XnUInt x = 0; x < depthMD.XRes(); ++x, ++pDepth)
- {
- if (1/**pDepth != 0*/)
- {
- uchar nHistValue =(uchar) pDepthHist[*pDepth];
- depthMat1u_p[x] = nHistValue;//NiSample是将B、G两个通道都赋值生成黄色深度图
- }
- }
- pDepthRow += depthMD.XRes();
- }
- //normalize(depthMat1u,depthMat1u,255,0,CV_MINMAX);
- Point maxLoc;
- double maxV;
- minMaxLoc(depthMat1u,0,&maxV,0,&maxLoc);
- Mat mask(480,640,CV_8UC1);
- threshold(depthMat1u,mask,0.9*maxV,255,THRESH_BINARY);
- imshow("mask",mask);
- cvtColor(depthMat1u,depthMat3u,CV_GRAY2BGR);
- circle(depthMat3u,maxLoc,5,Scalar(0,255,0),-1);
- imshow("depthMaxloc",depthMat3u);
- key=waitKey(20);
- }
- }