我们都知道OpenNI2与OpenCV可以通过Kinect获取深度与彩色图像。
但区别是OpenCV更强大满足需求更多,但是只能一帧一帧的保存。
而OpenNI2有一个videostream对象可以以视频类型保存数据。
因为我需要以视频类型保存数据,所以我选择OpenNI2来获取深度和彩色图像。
问题:
根据小斤(Kinect开发教程八:OpenNI2显示深度、彩色及融合图像)教程的代码:
/*************************
OpenNI2 Deep, Color and Fusion Image
Author: Xin Chen, 2013.2
Blog: http://blog.csdn.net/chenxin_130
*************************/
#include
#include
#include
#include "OpenNI.h"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace std;
using namespace cv;
using namespace openni;
void CheckOpenNIError( Status result, string status )
{
if( result != STATUS_OK )
cerr << status << " Error: " << OpenNI::getExtendedError() << endl;
}
int main( int argc, char** argv )
{
Status result = STATUS_OK;
//OpenNI2 image
VideoFrameRef oniDepthImg;
VideoFrameRef oniColorImg;
//OpenCV image
cv::Mat cvDepthImg;
cv::Mat cvBGRImg;
cv::Mat cvFusionImg;
cv::namedWindow("depth");
cv::namedWindow("image");
cv::namedWindow("fusion");
char key=0;
//【1】
// initialize OpenNI2
result = OpenNI::initialize();
CheckOpenNIError( result, "initialize context" );
// open device
Device device;
result = device.open( openni::ANY_DEVICE );
//【2】
// create depth stream
VideoStream oniDepthStream;
result = oniDepthStream.create( device, openni::SENSOR_DEPTH );
//【3】
// set depth video mode
VideoMode modeDepth;
modeDepth.setResolution( 640, 480 );
modeDepth.setFps( 30 );
modeDepth.setPixelFormat( PIXEL_FORMAT_DEPTH_1_MM );
oniDepthStream.setVideoMode(modeDepth);
// start depth stream
result = oniDepthStream.start();
// create color stream
VideoStream oniColorStream;
result = oniColorStream.create( device, openni::SENSOR_COLOR );
// set color video mode
VideoMode modeColor;
modeColor.setResolution( 640, 480 );
modeColor.setFps( 30 );
modeColor.setPixelFormat( PIXEL_FORMAT_RGB888 );
oniColorStream.setVideoMode( modeColor);
//【4】
// set depth and color imge registration mode
if( device.isImageRegistrationModeSupported(IMAGE_REGISTRATION_DEPTH_TO_COLOR ) )
{
device.setImageRegistrationMode( IMAGE_REGISTRATION_DEPTH_TO_COLOR );
}
// start color stream
result = oniColorStream.start();
while( key!=27 )
{
// read frame
if( oniColorStream.readFrame( &oniColorImg ) == STATUS_OK )
{
// convert data into OpenCV type
cv::Mat cvRGBImg( oniColorImg.getHeight(), oniColorImg.getWidth(), CV_8UC3, (void*)oniColorImg.getData() );
cv::cvtColor( cvRGBImg, cvBGRImg, CV_RGB2BGR );
cv::imshow( "image", cvBGRImg );
}
if( oniDepthStream.readFrame( &oniDepthImg ) == STATUS_OK )
{
cv::Mat cvRawImg16U( oniDepthImg.getHeight(), oniDepthImg.getWidth(), CV_16UC1, (void*)oniDepthImg.getData() );
cvRawImg16U.convertTo( cvDepthImg, CV_8U, 255.0/(oniDepthStream.getMaxPixelValue()));
//【5】
// convert depth image GRAY to BGR
cv::cvtColor(cvDepthImg,cvFusionImg,CV_GRAY2BGR);
cv::imshow( "depth", cvDepthImg );
}
//【6】
cv::addWeighted(cvBGRImg,0.5,cvFusionImg,0.5,0,cvFusionImg);
cv::imshow( "fusion", cvFusionImg );
key = cv::waitKey(20);
}
//cv destroy
cv::destroyWindow("depth");
cv::destroyWindow("image");
cv::destroyWindow("fusion");
//OpenNI2 destroy
oniDepthStream.destroy();
oniColorStream.destroy();
device.close();
OpenNI::shutdown();
return 0;
}
运行结果:
解决办法:
在查阅了很多资料后,在stack overflow上我看到了一个问题:Change resolution on openni2 not working
运行了代码之后:(OniSampleUtilities.h就在OpenNI2安装目录下,例如我的路径是:F:\Program Files (x86)\OpenNI2\Samples\SimpleViewer
)
看到他的问题是:
我猜想是不是只运行512*424以内的格式,所以640*480便不可执行,于是我把小斤的代码中640*480全部改为320*240,运行:
显示depth图像成功!
具体的原因我也并不是很清楚,也许是OpenNI2的一个BUG吧~科科~