Kinect開發教程八:OpenNI2顯示深度、彩色及融合映像

來源:互聯網
上載者:User

      在《Kinect開發教程二:OpenNI讀取深度映像與彩色映像並顯示》中,小斤介紹了OpenNI讀取深度與彩色映像資料的方法,並且藉助OpenCV進行顯示。

      OpenNI2在介面上與OpenNI有了較大變化,具體更新可以查看《OpenNI Migration Guide》。從擷取深度,彩色感應器的資料而言,小斤覺得調用更為直觀,但對於Kinect,一大缺憾是不支援OpenNI2提供的深度與彩色映像配準的方法(體現在下文中的device.isImageRegistrationModeSupported()方法)。

      但使用Kinect的童鞋也不必沮喪,在OpenNI2.1 beta中,小斤看到了新增的convertDepthToColorCoordinates()方法可以做一些深度與彩色座標資料的轉化,它的效果應該是與device.setImageRegistrationMode( IMAGE_REGISTRATION_DEPTH_TO_COLOR )類似的,有興趣的童鞋可以嘗試一下。

      在顯示方面,小斤還是使用OpenCV,這次是使用OpenCV的C++介面進行操作。

/*************************OpenNI2 Deep, Color and Fusion ImageAuthor: Xin Chen, 2013.2Blog: http://blog.csdn.net/chenxin_130*************************/#include <stdlib.h>#include <iostream>#include <string>#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 imageVideoFrameRef oniDepthImg;    VideoFrameRef oniColorImg;//OpenCV imagecv::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 modeVideoMode modeColor;    modeColor.setResolution( 640, 480 );    modeColor.setFps( 30 );    modeColor.setPixelFormat( PIXEL_FORMAT_RGB888 );    oniColorStream.setVideoMode( modeColor);//【4】// set depth and color imge registration modeif( device.isImageRegistrationModeSupported(IMAGE_REGISTRATION_DEPTH_TO_COLOR ) ){device.setImageRegistrationMode( IMAGE_REGISTRATION_DEPTH_TO_COLOR );}// start color stream    result = oniColorStream.start();  while( key!=27 ) {  // read frameif( oniColorStream.readFrame( &oniColorImg ) == STATUS_OK ){// convert data into OpenCV typecv::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 BGRcv::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 destroycv::destroyWindow("depth");cv::destroyWindow("image");cv::destroyWindow("fusion");    //OpenNI2 destroy    oniDepthStream.destroy();    oniColorStream.destroy();    device.close();    OpenNI::shutdown();return 0;}

      小斤由上到下解釋一把:

      【1】使用OpenNI::initialize()方法進行初始化,對於錯誤處理,可以使用OpenNI::getExtendedError()方法。在這裡,Device對象開啟任意一個可用裝置。

      【2】在OpenNI2中,可以通過建立VideoStream視頻流對象來讀取裝置的深度映像和色彩映像資料。

      【3】對於VideoStream視頻流對象,我們可以裝置它的Mode,包括解析度,FPS,像素格式等等。對於像素格式的類型,可以使用VideoStream的getSensorInfo()方法獲得,目前Kinect只有PIXEL_FORMAT_DEPTH_1_MM可供選擇。

      【4】如果裝置支援深度與彩色映像配準的話,小斤在這裡使用OpenNI2內建的介面進行配准。在while迴圈中,各個VideoStream對象通過readFrame()來讀取對應的映像資料。

      【5】將OpenNI的映像資料轉換為OpenCV可顯示的映像格式。對於彩色映像,可以先將資料塞入OpenCV三通道(8位)RGB對象,再轉換到BGR來顯示。對於深度映像,先放入單通道(16位)對象(這是因為深度資料的範圍較大),最近將深度值等比例縮小到[0,255]的範圍中,作為灰階圖顯示。

      【6】最後的映像融合,由於addWeighted()方法需要兩個輸入映像是同一類型,所以小斤首先將深度灰階圖(單通道),轉化為BGR映像,這樣就與彩色映像一致了。再通過該方法進行融合,小斤使用的比例是0.5,0.5,也就是融合映像的每個像素點的值,都是(深度映像該點的像素值*0.5)+ (彩色映像該點的像素值*0.5)。

----------------------------------

作者:小斤(陳忻)

新浪圍脖:@小斤陳

本文屬於原創文章,如需轉載引用請註明原文作者和連結,謝謝。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.