как использовать Kinect с openni и opencv

для начала мне просто нужно захватить RGBstream и преобразовать его в последовательность opencv image. это не должно быть так сложно, но я нашел больше одного кода в Интернете, но они не работают на моем компьютере. Я не знаю, где ошибка.

Не могли бы вы предложить мне учебник по действительно простому коду, который позволит мне понять, как использовать библиотеки Kinect? сначала попробовал Kinect sdk, через некоторое время выбрал OPENNI.

помогите мне, спасибо!

PS: я использую c++ И VISUAL STUDIO 2010


person Community    schedule 20.03.2014    source источник


Ответы (2)


AFAIK из коробки OpenCV поддерживает OpenNI 1.5.x. Если вы не установили OpenNI, сделайте это в первую очередь именно в таком порядке (что важно):

  1. Установите OpenNI 1.5.7
  2. Установите NITE (совместимо с 1.5.7)
  3. Если вы используете датчик Kinect (а не Asus), также установите драйвер Avin SensorKinect.

На этом этапе у вас должен быть установлен OpenNI, так что запустите один из примеров.

Готовая библиотека opencv по умолчанию не скомпилирована с поддержкой OpenCV, поэтому вам нужно будет собрать opencv из исходного кода, чтобы включить поддержку OpenNI.

Установите CMakeGUI, если вы еще этого не сделали. Это позволит вам легко настроить процесс сборки opencv. Запустите его, перейдите в исходную папку opencv, выберите каталог назначения для размещения файлов сборки и нажмите «Настроить».

У вас должен быть большой список вариантов. Если вы прокрутите, вы должны увидеть обнаруженную папку установки OpenNI (если нет, вы должны исправить путь), а также вы должны и WITH_OPENNI флаг, который вы можете включить.

Когда вы закончите, нажмите «Сгенерировать», чтобы сгенерировать файлы проекта Visual Studio, необходимые для простой компиляции библиотеки opencv.

Для получения более подробной информации о сборке opencv из исходного кода в Windows также ознакомьтесь с официальная документация

Когда вы закончите компиляцию, у вас должен быть opencv, созданный с поддержкой openni, и вы сможете запустить что-то простое, например:

#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

   }
}

Также см. этот аналогичный ответ. Если вам нужно использовать OpenNI 2.x, см. следующие ресурсы:

person George Profenza    schedule 20.03.2014
comment
Поскольку сайт OpenNI не работает, вот несколько ссылок на установщики OpenNI версии 1.5.7: github. com/JavaOpenCVBook/code/tree/master/OpenNI - person dannyxyz22; 13.01.2015

Вот, я думаю, самый простой и эффективный способ использования kinect с OpenCV.

  • Вам НЕ нужно пересобирать OpenCV с флагом WITH_OPENNI: вам просто нужно установить 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();
}

И для тех, кто предпочитает использовать C API OpenCV со структурами 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();
}

Я надеюсь, что это будет полезно для большинства.

Наслаждаться !

person Bouty    schedule 14.06.2014