在QT下测试openni+opencv,显示采集的深度图和彩色图
(1) 新建工程。
因为考虑到opencv可以直接调用函数显示图片,因此采用在QT下新建一个空工程。
(2) 配置.pro文件。
此步骤是建立在已配置好opencv库和openni库的基础上的,依次添加的库为:
INCLUDEPATH += /usr/local/include \
/usr/local/include/opencv \
/usr/local/include/opencv2 \
/usr/include/ni \
/usr/include/nite \
LIBS += /usr/local/lib/libopencv_highgui.so\
/usr/local/local/libopencv_core.so \
/usr/local/lib/libopencv_imgproc_so \
/usr/lib/libXnVNite_1_5_2.so \
/usr/lib/libOpenNI.so \
以上的库配置是根据个人的安装文件而来的,因为我安装的opencv是2.4.9版本的,然后Openni是1.0版本的,配置前查看自己的文件是否是这个名称。如何找文件的安装路径,在ubuntu下,一般opencv是安装在文件系统 /usr/local/lib/ 路径,openni安装在 文件系统/usr/lib/下。
(3) 使用OpenNI读取颜色图和深度图的步骤如下:
a) 添加openni的头文件#include
b) 定义一个Context对象,并调用该对象的Init()方法来进行初始化。
c) 用context创建生成器,包括深度图像和彩色图像生成器。
d) 定义一个XnMapOutputMode格式对象,设置好分图像分辨率和帧率。
e) 设置颜色和深度图的输出模式,调用的方法是SetMapOutputMode()。
f) 因为深度摄像头和彩色摄像头不在同一个地方,看出来的景物是有偏差的,因此必须对深度图像进行校正,校正的方法.GetAlternativeViewPointCap().SetViewPoint()。
g) 调用context对象的StartGeneratingAll()来开启设备读取数据开关。
h) 调用context对象的更新数据方法,比如WaitAndupdateAll()方法。
i) 定义颜色图和色彩图的ImageMetaData对象,并利用对应的节点对象的方法GetMetaData(),将获取到的数据保存到对应的ImageData对象中。
j) 如果需要将深度图转换成灰度图来显示,则需要自己将深度值转换成0~255的单通道或者多通道数据,然后直接用来显示。
(4) 程序实例测试
#include
#include
#include
//【1】XnCppWrapper.h是openni的头文件。
#include
#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 )
{
XnStatusresult = XN_STATUS_OK;
xn::DepthMetaDatadepthMD;
xn::ImageMetaDataimageMD;
//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);
charkey=0;
//【2】
//DepthGenerator和ImageGenerator,前者是深度图像生成器,后者是彩色图像生成器。创建一个生成器,首先要初始化一个context上下文,然后把context作为create函数的参数,便可以创建生成器。
xn::Contextcontext;
result= context.Init();
CheckOpenNIError(result, "initialize context" );
//creategenerator
xn::DepthGeneratordepthGenerator;
result= depthGenerator.Create( context );
CheckOpenNIError(result, "Create depth generator" );
xn::ImageGeneratorimageGenerator;
result= imageGenerator.Create( context );
CheckOpenNIError(result, "Create image generator" );
//【3】
//XnMapOutputMode 用于设定生成器的参数
XnMapOutputModemapMode;
mapMode.nXRes= 640;
mapMode.nYRes= 480;
mapMode.nFPS= 30;
result= depthGenerator.SetMapOutputMode( mapMode );
result= imageGenerator.SetMapOutputMode( mapMode );
//【4】
// correct view port,为什么要调整视角,因为kinect的三只眼长在不同的地方,深度摄像头和彩色摄像头看出来的景物是有偏差的。这里把深度生成器的视角转换成彩色摄像头的视角。
depthGenerator.GetAlternativeViewPointCap().SetViewPoint(imageGenerator );
//【5】
//readdata
result= context.StartGeneratingAll();
//【6】不管数据有没有读到新数据,只管更新。
result= context.WaitNoneUpdateAll();
while((key!=27) && !(result = context.WaitNoneUpdateAll( )) )
{
//getmeta data
depthGenerator.GetMetaData(depthMD);
imageGenerator.GetMetaData(imageMD);
//【7】
//OpenCVoutput
memcpy(imgDepth16u->imageData,depthMD.Data(),640*480*2);
//void*memcpy(void *dest, const void *src, size_t n);
//从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中
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();
return0;
}
显示:
保存图片可以采用直接保存,可以完整保存图片的大小尺寸等。如果只是为了演示等,可以直接截屏alt+printscreen,默认的格式是以png格式保存的。
(5) 参考的网站
比较权威的网站:http://blog.csdn.net/chenxin_130/article/details/6696187