Изменение разрешения на openni2 не работает

Я хочу прочитать кадр глубины в разрешении 640x480.
Я использую 64-разрядную версию Windows 8.1, 32-разрядную версию openni2, kinect: PSMP05000, PSCM04900 (PrimeSense).

Я беру ссылку на код отсюда:
не может установить разрешение VGA
Простое чтение

В сочетании с этим кодом:
main.cpp
OniSampleUtilities.h
SimpleRead.vcxproj
должен быть скомпилирован, если вы устанавливаете openni2 32bit отсюда:
OpeniNI 2

#include "iostream"
#include "OpenNI.h"
#include "OniSampleUtilities.h" 

#define SAMPLE_READ_WAIT_TIMEOUT 2000 //2000ms

using namespace openni;
using namespace std;

int main()
{
    Status rc = OpenNI::initialize();
    if (rc != STATUS_OK)
    {
        cout << "Initialize failed:" << endl << OpenNI::getExtendedError() << endl;
        return 1;
    }

    Device device;
    rc = device.open(ANY_DEVICE);
    if (rc != STATUS_OK)
    {
        cout << "Couldn't open device" << endl << OpenNI::getExtendedError() << endl;
        return 2;
    }

    VideoStream depth;

    if (device.getSensorInfo(SENSOR_DEPTH) != NULL)
    {
        rc = depth.create(device, SENSOR_DEPTH);
        if (rc != STATUS_OK)
        {
            cout << "Couldn't create depth stream" << endl << OpenNI::getExtendedError() << endl;
            return 3;
        }
    }

    rc = depth.start();
    if (rc != STATUS_OK)
    {
        cout << "Couldn't start the depth stream" << endl << OpenNI::getExtendedError() << endl;
        return 4;
    }

    VideoFrameRef frame;

    // set resolution
    // depth modes
    cout << "Depth modes" << endl;
    const openni::SensorInfo* sinfo = device.getSensorInfo(openni::SENSOR_DEPTH); // select index=4 640x480, 30 fps, 1mm
    const openni::Array< openni::VideoMode>& modesDepth = sinfo->getSupportedVideoModes();
    for (int i = 0; i<modesDepth.getSize(); i++) {
        printf("%i: %ix%i, %i fps, %i format\n", i, modesDepth[i].getResolutionX(), modesDepth[i].getResolutionY(),
            modesDepth[i].getFps(), modesDepth[i].getPixelFormat()); //PIXEL_FORMAT_DEPTH_1_MM = 100, PIXEL_FORMAT_DEPTH_100_UM
    }
    rc = depth.setVideoMode(modesDepth[0]);
    if (openni::STATUS_OK != rc)
    {
        cout << "error: depth fromat not supprted..." << endl;
    }
    system("pause");
    while (!wasKeyboardHit())
    {
        int changedStreamDummy;
        VideoStream* pStream = &depth;
        rc = OpenNI::waitForAnyStream(&pStream, 1, &changedStreamDummy, SAMPLE_READ_WAIT_TIMEOUT);
        if (rc != STATUS_OK)
        {
            cout << "Wait failed! (timeout is " << SAMPLE_READ_WAIT_TIMEOUT << " ms)" << endl << OpenNI::getExtendedError() << endl;
            continue;
        }

        rc = depth.readFrame(&frame);
        if (rc != STATUS_OK)
        {
            cout << "Read failed!" << endl << OpenNI::getExtendedError() << endl;
            continue;
        }

        if (frame.getVideoMode().getPixelFormat() != PIXEL_FORMAT_DEPTH_1_MM && frame.getVideoMode().getPixelFormat() != PIXEL_FORMAT_DEPTH_100_UM)
        {
            cout << "Unexpected frame format" << endl;
            continue;
        }

        DepthPixel* pDepth = (DepthPixel*)frame.getData();

        int middleIndex = (frame.getHeight()+1)*frame.getWidth()/2;

        printf("[%08llu] %8d\n", (long long)frame.getTimestamp(), pDepth[middleIndex]);
    }

    depth.stop();
    depth.destroy();
    device.close();
    OpenNI::shutdown();

    return 0;
}

Существует 6 режимов работы:

0: 320x240, 30 fps, 100 format
1: 320x240, 30 fps, 101 format
2: 320x240, 60 fps, 100 format
3: 320x240, 60 fps, 101 format
4: 640x480, 30 fps, 100 format
5: 640x480, 30 fps, 101 format

Он может читать только из режимов = 0-3.
В режиме 4,5 я получаю тайм-аут.
Как я могу прочитать кадр глубины в 640x480?

Спасибо за помощь,
Таль.

================================================== ==
новая информация:

Я также использую эту строку и получаю те же результаты:

const openni::SensorInfo* sinfo = &(depth.getSensorInfo());


Эта строка никогда не выполняется ни в каком режиме:

cout << "error: depth fromat not supprted..." << endl;


В режиме 4,5 я всегда выполняю эту строку:

cout << "Wait failed! (timeout is " << SAMPLE_READ_WAIT_TIMEOUT << " ms)" << endl << OpenNI::getExtendedError() << endl;


Я думаю, что это ошибка в openni2.
На openni1 я могу читать изображение глубины с разрешением 640x480 на том же компьютере, ОС и устройстве.


person Tal    schedule 23.07.2014    source источник
comment
вместо device.getSensorInfo(openni::SENSOR_DEPTH); попробуйте depth.getSensorInfo(); и снова посмотрите данные о режимахDepth.   -  person Mehdi Saman Booy    schedule 23.07.2014
comment
это то же самое :(. говорят точно такие же режимы. когда я использую режимы 4,5. не могу читать. Я использую эту строку: const openni::SensorInfo* sinfo = &(depth.getSensorInfo());   -  person Tal    schedule 23.07.2014
comment
попробуйте это: openni::VideoMode depth_videoMode = depth.getVideoMode(); depth_videoMode.setResolution(width, height); depth_videoMode.setFps(fps); depth.setVideoMode(depth_videoMode); и заполните ширину, высоту, fps подходящими значениями   -  person Mehdi Saman Booy    schedule 23.07.2014
comment
Я пробовал это раньше, и тот же результат. :-\   -  person Tal    schedule 23.07.2014
comment
если эта строка не выполняется, ваша программа должна работать :-? cout << "error: depth fromat not supprted..." << endl;   -  person Mehdi Saman Booy    schedule 23.07.2014
comment
эта строка не выполняется. я получаю статус ок. программа работает, и я всегда получаю эту строку: cout ‹‹ Подождите, не удалось! (время ожидания ‹‹ SAMPLE_READ_WAIT_TIMEOUT ‹‹ мс) ‹‹ endl ‹‹ OpenNI::getExtendedError() ‹‹ endl;   -  person Tal    schedule 23.07.2014
comment
какой драйвер kinect вы используете? вы используете kinect или камеру PrimeSense?   -  person api55    schedule 02.08.2014


Ответы (5)


Может быть я ошибаюсь, но я почти уверен, что проблема в том порядке, в котором вы это делаете.

Я думаю, что вы должны изменить его before depth.start() и после depth.create(device, SENSOR_DEPTH)

Если я правильно помню, после запуска бот может изменить разрешение потока.

Так что должно быть что-то вроде этого

...

if (device.getSensorInfo(SENSOR_DEPTH) != NULL)
{
    rc = depth.create(device, SENSOR_DEPTH);
    if (rc != STATUS_OK)
    {
        cout << "Couldn't create depth stream" << endl << OpenNI::getExtendedError() << endl;
        return 3;
    }
}

// set resolution
// depth modes
cout << "Depth modes" << endl;
const openni::SensorInfo* sinfo = device.getSensorInfo(openni::SENSOR_DEPTH);
const openni::Array< openni::VideoMode>& modesDepth = sinfo->getSupportedVideoModes();
rc = depth.setVideoMode(modesDepth[0]);
if (openni::STATUS_OK != rc)
{
    cout << "error: depth fromat not supprted..." << endl;
}

rc = depth.start();
if (rc != STATUS_OK)
{
    cout << "Couldn't start the depth stream" << endl << OpenNI::getExtendedError() << endl;
    return 4;
}

VideoFrameRef frame;



...

Я надеюсь, что это поможет вам, если нет, пожалуйста, добавьте комментарий. У меня есть аналогичный код, работающий в репозитории git, который я показал вам на днях, протестированный с камерой PrimeSense carmine.

person api55    schedule 02.08.2014

В моем случае (Asus Xtion PRO в порте USB 3.0, OpenNI2, Windows 8.1) кажется, что-то не так с OpenNI2 (или его драйвером), что мешает мне изменить разрешение в коде. NiViewer просто зависает или частота кадров значительно падает, если цветовое разрешение установлено на 640x480.

Однако в Windows мне удалось изменить разрешение, изменив настройки в файле PS1080.ini в папке OpenNI2/Tools/OpenNI2/Drivers. В ini-файле для Asus убедитесь,

UsbИнтерфейс = 2

включен. По умолчанию это ноль. Затем установите Разрешение = 1 для разделов глубины и изображения.

Моя прошивка Asus Xtion v5.8.22.

person songuke    schedule 19.06.2015

Я пробовал упомянутый метод @api55, и он работает. Код и результат приведены ниже.

Но возникает проблема, когда я вношу аналогичное изменение в пример кода OpenNI «SampleViewer», чтобы я мог бесплатно изменить разрешение. Ставлю разрешение 320*240 все нормально. Однако, когда я изменяю его на 640 * 480, хотя программа все еще считывает кадры (с явно меньшей скоростью), дисплей программы просто зависает.

2015-12-27 15:15:32

Затем я тестирую вышеупомянутый пример просмотра с камерой глубины kinect 1.0. Так как цветная камера имеет разрешение не менее 640*480, я не могу экспериментировать с разрешением 320*240. Но программа хорошо работает с kinect 1.0 в разрешении 640*480. В заключение я думаю, что должна быть какая-то проблема с камерой ASUS Xtion.

#include <iostream>
#include <cstdio>
#include <vector>
#include <OpenNI.h>
#include "OniSampleUtilities.h" 

#pragma comment(lib, "OpenNI2")

#define SAMPLE_READ_WAIT_TIMEOUT 2000 //2000ms

using namespace openni;
using namespace std;

int main()
{
    Status rc = OpenNI::initialize();
    if (rc != STATUS_OK)
    {
        printf("Initialize failed:\n%s\n", OpenNI::getExtendedError());
        return 1;
    }

    Device device;

    openni::Array<openni::DeviceInfo> deviceInfoList;
    OpenNI::enumerateDevices(&deviceInfoList);

    for (int i = 0; i < deviceInfoList.getSize(); i++)
    {
        printf("%d: Uri: %s\n"
            "Vendor: %s\n"
            "Name: %s\n", i, deviceInfoList[i].getUri(), deviceInfoList[i].getVendor(), deviceInfoList[i].getName());
    }

    rc = device.open(deviceInfoList[0].getUri());
    if (rc != STATUS_OK)
    {
        printf("Counldn't open device\n%s\n", OpenNI::getExtendedError());
        return 2;
    }

    VideoStream depth;

    // set resolution
    // depth modes
    printf("\nDepth modes\n");
    const openni::SensorInfo* sinfo = device.getSensorInfo(openni::SENSOR_DEPTH); // select index=4 640x480, 30 fps, 1mm
    if (sinfo == NULL)
    {
        printf("Couldn't get device info\n%s\n", OpenNI::getExtendedError());
        return 3;
    }

    rc = depth.create(device, SENSOR_DEPTH);
    if (rc != STATUS_OK)
    {
        printf("Couldn't create depth stream\n%s\n", OpenNI::getExtendedError());
        return 4;
    }


    const openni::Array< openni::VideoMode>& modesDepth = sinfo->getSupportedVideoModes();
    vector<int> item;
    for (int i = 0; i < modesDepth.getSize(); i++) {
        printf("%i: %ix%i, %i fps, %i format\n", i, modesDepth[i].getResolutionX(), modesDepth[i].getResolutionY(),
            modesDepth[i].getFps(), modesDepth[i].getPixelFormat()); //PIXEL_FORMAT_DEPTH_1_MM = 100, PIXEL_FORMAT_DEPTH_100_UM
        if (modesDepth[i].getResolutionX() == 640 && modesDepth[i].getResolutionY() == 480)
            item.push_back(i);
    }

    int item_idx = item[0];
    printf("Choose mode %d\nWidth: %d, Height: %d\n", item_idx, modesDepth[item_idx].getResolutionX(), modesDepth[item_idx].getResolutionY());

    rc = depth.setVideoMode(modesDepth[item_idx]);
    if (rc != STATUS_OK)
    {
        printf("error: depth format not supported...\n");
        return 5;
    }

    rc = depth.start();
    if (rc != STATUS_OK)
    {
        printf("Couldn't start the depth stream\n%s\n", OpenNI::getExtendedError());
        return 6;
    }

    VideoFrameRef frame;

    printf("\nCurrent resolution:\n");
    printf("Width: %d  Height: %d\n", depth.getVideoMode().getResolutionX(), depth.getVideoMode().getResolutionY());


    system("pause");
    while (!wasKeyboardHit())
    {
        int changedStreamDummy;
        VideoStream* pStream = &depth;
        rc = OpenNI::waitForAnyStream(&pStream, 1, &changedStreamDummy, SAMPLE_READ_WAIT_TIMEOUT);
        if (rc != STATUS_OK)
        {
            printf("Wait failed! (timeout is \" %d \" ms)\n%s\n", SAMPLE_READ_WAIT_TIMEOUT, OpenNI::getExtendedError());
            continue;
        }

        rc = depth.readFrame(&frame);
        if (rc != STATUS_OK)
        {
            printf("Read failed!\n%s\n", OpenNI::getExtendedError());
            continue;
        }

        if (frame.getVideoMode().getPixelFormat() != PIXEL_FORMAT_DEPTH_1_MM && frame.getVideoMode().getPixelFormat() != PIXEL_FORMAT_DEPTH_100_UM)
        {
            printf("Unexpected frame format\n");
            continue;
        }

        DepthPixel* pDepth = (DepthPixel*)frame.getData();

        int middleIndex = (frame.getHeight() + 1)*frame.getWidth() / 2;

        printf("[%08llu] %8d\n", (long long)frame.getTimestamp(), pDepth[middleIndex]);
        printf("Width: %d  Height: %d\n", frame.getWidth(), frame.getHeight());
    }

    depth.stop();
    depth.destroy();
    device.close();
    OpenNI::shutdown();

    return 0;
}

Вот результат:

person solaist    schedule 26.12.2015
comment
У меня точно такая же проблема. Не думайте, что это проблема asus xtion, потому что NiViewer хорошо работает с более высокими разрешениями. - person foothill; 25.03.2016

У меня была та же проблема, но теперь я решил ее, сославшись на пример NiViewer в OpenNI2. Видимо после того как запустишь стрим, то ли глубину, то ли цвет, его надо останавливать для смены разрешения и потом запускать

const openni::SensorInfo* sinfo = device.getSensorInfo(openni::SENSOR_DEPTH);
const openni::Array< openni::VideoMode>& modesDepth = sinfo->getSupportedVideoModes();
depth.stop();
rc = depth.setVideoMode(modesDepth[4]);
depth.start();

Я подтвердил, что это работает на Asus Xtion на OpenNI2.

Надеюсь это поможет!

person foothill    schedule 29.03.2016

Окончательный вывод:

На самом деле, это сама проблема Xtion (возможно, связанная с оборудованием).

Если вы хотите, чтобы только одна глубина или цвет были 640*480, а другая — 320*240, это сработает. Я могу опубликовать свой код, если хотите.

Подробнее

Некоторые из ответов выше допустили ошибку: даже сам NiViewer.exe не позволяет глубину 640 * 480 и цвет 640 * 480 одновременно.

Примечание: пусть вас не смущает визуализация NiViewer.exe, отображаемый видеопоток большой, но на самом деле это не означает 640*480. На самом деле он инициализирован

  • глубина: 320*240
  • цвет: 320*240

Когда вы устанавливаете любой из режимов на 640 * 480, он все еще работает, что

  • глубина: 640*480
  • цвет: 320*240

or

  • глубина: 320*240
  • цвет: 640*480

Но когда вы хотите, чтобы оба они были с самым высоким разрешением:

  • глубина: 640*480
  • цвет: 640*480

Программа просмотра начинает сталкиваться с резкой потерей кадров в режиме глубины (в моем случае), но поскольку программа просмотра извлекает кадр глубины неблочным способом (код по умолчанию написан блочным способом), вы все равно видите обновления цвета. обычно, в то время как глубина обновляется каждые две секунды или даже чаще.

Заключение

Вы можете установить либо глубину, либо цвет на 640*480, а другое на 320*240.

person Tomingsun    schedule 06.05.2019