opencv 調用openni圖像-xtion

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章