Промяната на разделителната способност на openni2 не работи

Искам да чета рамка с дълбочина при 640x480.
Използвам Windows 8.1 64bit, openni2 32bit, 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?

Благодаря за помощта, Tal.

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

Използвам също този ред и получавам същите резултати:

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(); и вижте отново данните за режимите на дълбочина.   -  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 ‹‹ Wait failed! (времето за изчакване е ‹‹ SAMPLE_READ_WAIT_TIMEOUT ‹‹ ms) ‹‹ 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.

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

е активиран. По подразбиране е нула. След това задайте Resolution = 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