【问题标题】:how to use Kinect with openni and opencv如何将 Kinect 与 openni 和 opencv 一起使用
【发布时间】:2014-04-27 05:02:36
【问题描述】:

首先,我只需要捕获 RGBstream 并将其转换为一系列 opencv 图像。它不应该那么难,但我在网上找到了更多的代码,但它们不在我的电脑上运行。不知道错在哪里。

你能给我推荐一个非常简单的代码教程,让我了解如何使用 Kinect 库吗? 一开始我尝试了Kinect sdk,过了一会儿选择OPENNI

帮帮我,谢谢!

ps:我正在使用 c++VISUAL STUDIO 2010

【问题讨论】:

    标签: c++ opencv kinect rgb openni


    【解决方案1】:

    AFAIK 开箱即用 OpenCV 支持 OpenNI 1.5.x。 如果您还没有安装 OpenNI,请先按以下特定顺序安装(这很重要):

    1. 安装OpenNI 1.5.7
    2. 安装 NITE(兼容 1.5.7)
    3. 如果您使用的是 Kinect(而不是华硕)传感器,请同时安装 Avin's SensorKinect driver

    此时您应该已经安装了 OpenNI,所以继续运行其中一个示例。

    默认情况下,预构建的 opencv 库未使用 OpenCV 支持编译,因此您需要从源代码构建 opencv 以启用 OpenNI 支持。

    如果您还没有安装CMakeGUI,请安装。这将允许您轻松配置 opencv 构建过程。运行它,浏览到 opencv 源文件夹,选择一个目标目录来放置你的构建文件并点击配置。

    您应该有一个很大的选项列表。如果滚动,您应该会看到检测到的 OpenNI 安装文件夹(如果没有,您应该修复路径),并且您应该可以启用 WITH_OPENNI 标志。

    当你完成按下生成后,它应该会生成你需要轻松编译 opencv 库的 Visual Studio 项目文件。

    有关在 windows 上从源代码构建 opencv 的更多详细信息,请查看official documentation

    当你完成编译后,你应该已经构建了带有 openni 支持的 opencv,并且你应该能够运行一些简单的东西:

    #include "opencv2/core/core.hpp"
    #include "opencv2/highgui/highgui.hpp"
    #include "opencv2/imgproc/imgproc.hpp"
    
    #include <iostream>
    
    using namespace cv;
    using namespace std;
    
    int main(){
        cout << "opening device(s)" << endl;
    
        VideoCapture sensor1;
        sensor1.open(CV_CAP_OPENNI);
    
        if( !sensor1.isOpened() ){
            cout << "Can not open capture object 1." << endl;
            return -1;
        }
    
        for(;;){
            Mat depth1;
    
            if( !sensor1.grab() ){
                cout << "Sensor1 can not grab images." << endl;
                return -1;
            }else if( sensor1.retrieve( depth1, CV_CAP_OPENNI_DEPTH_MAP ) ) imshow("depth1",depth1);
    
            if( waitKey( 30 ) == 27 )   break;//ESC to exit
    
       }
    }
    

    另见this similar answer。 如果您需要使用 OpenNI 2.x,请参阅以下资源:

    【讨论】:

    【解决方案2】:

    这是我认为将 kinect 与 OpenCV 一起使用的最简单有效的方法。

    • 您不必使用 WITH_OPENNI 标志重新构建 OpenCV:您只需要安装 OpenNI(使用 1.3.2.1-4 版本进行测试)。
    • 没有进行多余的内存复制或分配:仅分配标头,然后复制指向数据的指针。

    该代码允许您连续收集深度和彩色图像,但如果您只想要其中一个流,则无需打开另一个流。

    这是带有 C++ OpenCV API 和 Mat 对象的代码:

    #include <openni2/OpenNI.h>
    #include <opencv2/opencv.hpp>
    
    
    using namespace openni;
    
    main()
    {
        OpenNI::initialize();
        puts( "Kinect initialization..." );
        Device device;
        if ( device.open( openni::ANY_DEVICE ) != 0 )
        {
            puts( "Kinect not found !" ); 
            return -1;
        }
        puts( "Kinect opened" );
        VideoStream depth, color;
        color.create( device, SENSOR_COLOR );
        color.start();
        puts( "Camera ok" );
        depth.create( device, SENSOR_DEPTH );
        depth.start();
        puts( "Depth sensor ok" );
        VideoMode paramvideo;
        paramvideo.setResolution( 640, 480 );
        paramvideo.setFps( 30 );
        paramvideo.setPixelFormat( PIXEL_FORMAT_DEPTH_100_UM );
        depth.setVideoMode( paramvideo );
        paramvideo.setPixelFormat( PIXEL_FORMAT_RGB888 );
        color.setVideoMode( paramvideo );
        puts( "Réglages des flux vidéos ok" );
    
        // If the depth/color synchronisation is not necessary, start is faster :
        device.setDepthColorSyncEnabled( false );
    
        // Otherwise, the streams can be synchronized with a reception in the order of our choice :
        //device.setDepthColorSyncEnabled( true );
        //device.setImageRegistrationMode( openni::IMAGE_REGISTRATION_DEPTH_TO_COLOR );
    
        VideoStream** stream = new VideoStream*[2];
        stream[0] = &depth;
        stream[1] = &color;
        puts( "Kinect initialization completed" );
    
    
        if ( device.getSensorInfo( SENSOR_DEPTH ) != NULL )
        {
            VideoFrameRef depthFrame, colorFrame;
            cv::Mat colorcv( cv::Size( 640, 480 ), CV_8UC3, NULL );
            cv::Mat depthcv( cv::Size( 640, 480 ), CV_16UC1, NULL );
            cv::namedWindow( "RGB", CV_WINDOW_AUTOSIZE );
            cv::namedWindow( "Depth", CV_WINDOW_AUTOSIZE );
    
            int changedIndex;
            while( device.isValid() )
            {
                OpenNI::waitForAnyStream( stream, 2, &changedIndex );
                switch ( changedIndex )
                {
                    case 0:
                        depth.readFrame( &depthFrame );
    
                        if ( depthFrame.isValid() )
                        {
                            depthcv.data = (uchar*) depthFrame.getData();
                            cv::imshow( "Depth", depthcv );
                        }
                        break;
    
                    case 1:
                        color.readFrame( &colorFrame );
    
                        if ( colorFrame.isValid() )
                        {
                            colorcv.data = (uchar*) colorFrame.getData();
                            cv::cvtColor( colorcv, colorcv, CV_BGR2RGB );
                            cv::imshow( "RGB", colorcv );
                        }
                        break;
    
                    default:
                        puts( "Error retrieving a stream" );
                }
                cv::waitKey( 1 );
            }
    
            cv::destroyWindow( "RGB" );
            cv::destroyWindow( "Depth" );
        }
        depth.stop();
        depth.destroy();
        color.stop();
        color.destroy();
        device.close();
        OpenNI::shutdown();
    }
    

    对于那些喜欢使用 OpenCV 的 C API 和 IplImage 结构的人:

    #include <openni2/OpenNI.h>
    #include <opencv/cv.h>
    #include <opencv/highgui.h>
    
    
    using namespace openni;
    
    main()
    {
        OpenNI::initialize();
        puts( "Kinect initialization..." );
        Device device;
        if ( device.open( openni::ANY_DEVICE ) != 0 )
        {
            puts( "Kinect not found !" ); 
            return -1;
        }
        puts( "Kinect opened" );
        VideoStream depth, color;
        color.create( device, SENSOR_COLOR );
        color.start();
        puts( "Camera ok" );
        depth.create( device, SENSOR_DEPTH );
        depth.start();
        puts( "Depth sensor ok" );
        VideoMode paramvideo;
        paramvideo.setResolution( 640, 480 );
        paramvideo.setFps( 30 );
        paramvideo.setPixelFormat( PIXEL_FORMAT_DEPTH_100_UM );
        depth.setVideoMode( paramvideo );
        paramvideo.setPixelFormat( PIXEL_FORMAT_RGB888 );
        color.setVideoMode( paramvideo );
        puts( "Réglages des flux vidéos ok" );
    
        // If the depth/color synchronisation is not necessary, start is faster :
        device.setDepthColorSyncEnabled( false );
    
        // Otherwise, the streams can be synchronized with a reception in the order of our choice :
        //device.setDepthColorSyncEnabled( true );
        //device.setImageRegistrationMode( openni::IMAGE_REGISTRATION_DEPTH_TO_COLOR );
    
        VideoStream** stream = new VideoStream*[2];
        stream[0] = &depth;
        stream[1] = &color;
        puts( "Kinect initialization completed" );
    
    
        if ( device.getSensorInfo( SENSOR_DEPTH ) != NULL )
        {
            VideoFrameRef depthFrame, colorFrame;
            IplImage* colorcv = cvCreateImageHeader( cvSize( 640, 480 ), IPL_DEPTH_8U, 3 );
            IplImage* depthcv = cvCreateImageHeader( cvSize( 640, 480 ), IPL_DEPTH_16U, 1 );
            cvNamedWindow( "RGB", CV_WINDOW_AUTOSIZE );
            cvNamedWindow( "Depth", CV_WINDOW_AUTOSIZE );
    
            int changedIndex;
            while( device.isValid() )
            {
                OpenNI::waitForAnyStream( stream, 2, &changedIndex );
                switch ( changedIndex )
                {
                    case 0:
                        depth.readFrame( &depthFrame );
    
                        if ( depthFrame.isValid() )
                        {
                            depthcv->imageData = (char*) depthFrame.getData();
                            cvShowImage( "Depth", depthcv );
                        }
                        break;
    
                    case 1:
                        color.readFrame( &colorFrame );
    
                        if ( colorFrame.isValid() )
                        {
                            colorcv->imageData = (char*) colorFrame.getData();
                            cvCvtColor( colorcv, colorcv, CV_BGR2RGB );
                            cvShowImage( "RGB", colorcv );
                        }
                        break;
    
                    default:
                        puts( "Error retrieving a stream" );
                }
                cvWaitKey( 1 );
            }
    
            cvReleaseImageHeader( &colorcv );
            cvReleaseImageHeader( &depthcv );
            cvDestroyWindow( "RGB" );
            cvDestroyWindow( "Depth" );
        }
        depth.stop();
        depth.destroy();
        color.stop();
        color.destroy();
        device.close();
        OpenNI::shutdown();
    }
    

    希望对大家有用。

    享受吧!

    【讨论】:

      猜你喜欢
      • 2015-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多