Opencv 調用Openni圖像-Xtion
本例是使用opencv函數調用openni的圖像。
通常在使用xtion或kinect時總是隻在openni下使用,爲
了能在opencv環境下使用xtion搜索了相關資源,通過
實驗,總結如下(在ubuntu14.04,qt下):
方案一:
OpenNI 2與OpenCV結合的第一個程序
開始之前,讓我們自己開始再熟練熟練OpenNI 2的基本使用,主要包括以下幾個步驟:
1. 初始化OpenNI環境: openni::OpenNI::initialize();
2. 聲明並打開Device設備: openni::Device devAnyDevice; devAnyDevice.open( openni::ANY_DEVICE );
3. 創建並打開深度數據流:openni::VideoStream streamDepth; streamDepth.create( devAnyDevice, openni::SENSOR_DEPTH ); streamDepth.start();
4. 讀取數據流信息並保存在VideoFrameRef中:openni::VideoFrameRef frameDepth;streamDepth.readFrame( &frameDepth );
5. 獲取深度(或顏色等)數據,開始我們自己的開發之旅: const openni::DepthPixel* pDepth = (const openni::DepthPixel*)frameDepth.getData();
6. 當結束使用數據時,首先關閉、銷燬數據流:streamDepth.destroy();
7. 接着關閉設備: devAnyDevice.close();
8. 最後關閉OpenNI: openni::OpenNI::shutdown();
#include <iostream>
#include "OpenNI.h"
int main( int argc, char** argv )
{
// 初始化OpenNI環境
openni::OpenNI::initialize();
// 聲明並打開Device設備,我用的是Kinect。
openni::Device devAnyDevice;
devAnyDevice.open( openni::ANY_DEVICE );
// 創建並打開深度數據流
openni::VideoStream streamDepth;
streamDepth.create( devAnyDevice, openni::SENSOR_DEPTH );
streamDepth.start();
// 同樣的創建並打開彩色圖像數據流
openni::VideoStream streamColor;
streamColor.create( devAnyDevice, openni::SENSOR_COLOR );
streamColor.start();
// 循環讀取數據流信息並保存在VideoFrameRef中
openni::VideoFrameRef frameDepth;
openni::VideoFrameRef frameColor;
for( int i = 0; i < 1000; ++ i )
{
// 讀取數據流
streamDepth.readFrame( &frameDepth );
streamColor.readFrame( &frameColor );
// 獲取data array
const openni::DepthPixel* pDepth
= (const openni::DepthPixel*)frameDepth.getData();
const openni::RGB888Pixel* pColor
= (const openni::RGB888Pixel*)frameColor.getData();
// 顯示深度信息和對應的彩色R、G、B數值
int idx = frameDepth.getWidth() * ( frameDepth.getHeight() + 1 ) / 2;
std::cout << pDepth[idx] << "( "
<< (int)pColor[idx].r << ","
<< (int)pColor[idx].g << ","
<< (int)pColor[idx].b << ")"
<< std::endl;
}
// 關閉數據流
streamDepth.destroy();
streamColor.destroy();
// 關閉設備
devAnyDevice.close();
// 最後關閉OpenNI
openni::OpenNI::shutdown();
return 0;
}
案列:利用OpenCV函數顯示深度圖像和彩色圖像。直接上代碼:
#include "stdafx.h"
#include <iostream>
#include "OpenNI.h"
// 載入OpenCV頭文件
#include "opencv2/opencv.hpp"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace openni;
using namespace cv;
int main( int argc, char** argv )
{
// 初始化OpenNI環境
OpenNI::initialize();
// 聲明並打開Device設備,我用的是Kinect。
Device devAnyDevice;
devAnyDevice.open(ANY_DEVICE );
// 創建深度數據流
VideoStream streamDepth;
streamDepth.create( devAnyDevice, SENSOR_DEPTH );
// 創建彩色圖像數據流
VideoStream streamColor;
streamColor.create( devAnyDevice, SENSOR_COLOR );
// 設置深度圖像視頻模式
VideoMode mModeDepth;
// 分辨率大小
mModeDepth.setResolution( 640, 480 );
// 每秒30幀
mModeDepth.setFps( 30 );
// 像素格式
mModeDepth.setPixelFormat( PIXEL_FORMAT_DEPTH_1_MM );
streamDepth.setVideoMode( mModeDepth);
// 同樣的設置彩色圖像視頻模式
VideoMode mModeColor;
mModeColor.setResolution( 640, 480 );
mModeColor.setFps( 30 );
mModeColor.setPixelFormat( PIXEL_FORMAT_RGB888 );
streamColor.setVideoMode( mModeColor);
// 圖像模式註冊
if( devAnyDevice.isImageRegistrationModeSupported(
IMAGE_REGISTRATION_DEPTH_TO_COLOR ) )
{
devAnyDevice.setImageRegistrationMode( IMAGE_REGISTRATION_DEPTH_TO_COLOR );
}
// 打開深度和圖像數據流
streamDepth.start();
streamColor.start();
// 創建OpenCV圖像窗口
namedWindow( "Depth Image", CV_WINDOW_AUTOSIZE );
namedWindow( "Color Image", CV_WINDOW_AUTOSIZE );
// 獲得最大深度值
int iMaxDepth = streamDepth.getMaxPixelValue();
// 循環讀取數據流信息並保存在VideoFrameRef中
VideoFrameRef frameDepth;
VideoFrameRef frameColor;
while( true )
{
// 讀取數據流
streamDepth.readFrame( &frameDepth );
streamColor.readFrame( &frameColor );
// 將深度數據轉換成OpenCV格式
const cv::Mat mImageDepth( frameDepth.getHeight(), frameDepth.getWidth(), CV_16UC1, (void*)frameDepth.getData());
// 爲了讓深度圖像顯示的更加明顯一些,將CV_16UC1 ==> CV_8U格式
cv::Mat mScaledDepth;
mImageDepth.convertTo( mScaledDepth, CV_8U, 255.0 / iMaxDepth );
// 顯示出深度圖像
cv::imshow( "Depth Image", mScaledDepth );
// 同樣的將彩色圖像數據轉化成OpenCV格式
const cv::Mat mImageRGB(frameColor.getHeight(), frameColor.getWidth(), CV_8UC3, (void*)frameColor.getData());
// 首先將RGB格式轉換爲BGR格式
cv::Mat cImageBGR;
cv::cvtColor( mImageRGB, cImageBGR, CV_RGB2BGR );
// 然後顯示彩色圖像
cv::imshow( "Color Image", cImageBGR );
// 終止快捷鍵
if( cv::waitKey(1) == 'q')
break;
}
// 關閉數據流
streamDepth.destroy();
streamColor.destroy();
// 關閉設備
devAnyDevice.close();
// 最後關閉OpenNI
openni::OpenNI::shutdown();
return 0;
}
注:在做此實驗中,由於自身opencv和openni2的環境部署問題,出現一系列包導入路徑問題:
INCLUDEPATH += /usr/include\
/usr/include/opencv\
/usr/include/opencv2\
/usr/include/openni2\#需加
LIBS += /usr/lib/x86_64-linux-gnu/libopencv_highgui.so.2.4\
/usr/lib/x86_64-linux-gnu/libopencv_core.so \
/usr/lib/x86_64-linux-gnu/libopencv_imgproc.so\
/usr/lib/x86_64-linux-gnu/libopencv_video.so\
/usr/lib/x86_64-linux-gnu/libopencv_objdetect.so\
/usr/lib/libOpenNI2.so#需加
方案二:此處不在解釋,直接上代碼,ps:由於用到openni1中的函數,實驗沒有完成:
OpenNI獲取的圖像結合OpenCV顯示
copenni.cpp:
#include <XnCppWrapper.h>
#include <QtGui/QtGui>
#include <iostream>
using namespace xn;
using namespace std;
class COpenNI
{
public:
~COpenNI() {
context.Release();//釋放空間
}
bool Initial() {
//初始化
status = context.Init();
if(CheckError("Context initial failed!")) {
return false;
}
context.SetGlobalMirror(true);//設置鏡像
//產生圖片node
status = image_generator.Create(context);
if(CheckError("Create image generator error!")) {
return false;
}
//產生深度node
status = depth_generator.Create(context);
if(CheckError("Create depth generator error!")) {
return false;
}
//視角校正
status = depth_generator.GetAlternativeViewPointCap().SetViewPoint(image_generator);
if(CheckError("Can't set the alternative view point on depth generator")) {
return false;
}
return true;
}
bool Start() {
status = context.StartGeneratingAll();
if(CheckError("Start generating error!")) {
return false;
}
return true;
}
bool UpdateData() {
status = context.WaitNoneUpdateAll();
if(CheckError("Update date error!")) {
return false;
}
//獲取數據
image_generator.GetMetaData(image_metadata);
depth_generator.GetMetaData(depth_metadata);
return true;
}
public:
DepthMetaData depth_metadata;
ImageMetaData image_metadata;
private:
//該函數返回真代表出現了錯誤,返回假代表正確
bool CheckError(const char* error) {
if(status != XN_STATUS_OK ) {
QMessageBox::critical(NULL, error, xnGetStatusString(status));
cerr << error << ": " << xnGetStatusString( status ) << endl;
return true;
}
return false;
}
private:
XnStatus status;
Context context;
DepthGenerator depth_generator;
ImageGenerator image_generator;
};
main.cpp:
#include <QCoreApplication>
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <opencv2/core/core.hpp>
#include "copenni.cpp"
#include <iostream>
using namespace cv;
using namespace xn;
int main (int argc, char **argv)
{
COpenNI openni;
if(!openni.Initial())
return 1;
namedWindow("color image", CV_WINDOW_AUTOSIZE);
namedWindow("color edge detect", CV_WINDOW_AUTOSIZE);
namedWindow("depth image", CV_WINDOW_AUTOSIZE);
namedWindow("depth edge detect", CV_WINDOW_AUTOSIZE);
if(!openni.Start())
return 1;
while(1) {
if(!openni.UpdateData()) {
return 1;
}
/*獲取並顯示色彩圖像*/
Mat color_image_src(openni.image_metadata.YRes(), openni.image_metadata.XRes(),
CV_8UC3, (char *)openni.image_metadata.Data());
Mat color_image;
cvtColor(color_image_src, color_image, CV_RGB2BGR);
imshow("color image", color_image);
/*對色彩圖像進行canny邊緣檢測並顯示*/
Mat color_image_gray, color_image_edge;
cvtColor(color_image_src, color_image_gray, CV_RGB2GRAY);//因爲在進行邊緣檢測的時候只能使用灰度圖像
Canny(color_image_gray, color_image_edge, 5, 100);
imshow("color edge detect", color_image_edge);
/*獲取並顯示深度圖像*/
Mat depth_image_src(openni.depth_metadata.YRes(), openni.depth_metadata.XRes(),
CV_16UC1, (char *)openni.depth_metadata.Data());//因爲kinect獲取到的深度圖像實際上是無符號的16位數據
Mat depth_image, depth_image_edge;
depth_image_src.convertTo(depth_image, CV_8U, 255.0/8000);
imshow("depth image", depth_image);
/*計算深度圖像的canny邊緣並顯示*/
Canny(depth_image, depth_image_edge, 5, 100);
imshow("depth edge detect", depth_image_edge);
waitKey(30);
}
}
參考:
Kinect+OpenNI學習筆記之4(OpenNI獲取的圖像結合OpenCV顯示)
OpenNI 2與OpenCV結合的第一個程序
使用opencv顯示openni獲取的圖像
Kinect開發教程二:OpenNI讀取深度圖像與彩色圖像並顯示
附錄:openni庫
OpenNI