更改openni2上的解决方案无法正常工作

时间:2014-07-23 10:54:32

标签: c++ visual-studio-2010 visual-studio-2013 openni

我想在640x480读取深度帧。
我使用的是Windows 8.1 64bit,openni2 32bit,kinect:PSMP05000,PSCM04900(PrimeSense)

我从这里获取代码参考:
cannot set VGA resolution
Simple Read

结合此代码:
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

它只能从modes = 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,同一台计算机,操作系统和设备上读取深度图像。

5 个答案:

答案 0 :(得分:3)

也许我错了,但我几乎可以确定问题是你正在做的顺序。

我认为您应该更改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胭脂红相机测试。

答案 1 :(得分:1)

在我的情况下(USB 3.0端口中的Asus Xtion PRO,OpenNI2,Windows 8.1),似乎OpenNI2(或其驱动程序)出现了问题,导致我无法更改代码中的分辨率。如果颜色分辨率设置为640x480,则NiViewer简单挂起或帧速率显着下降。

但是,在Windows上,我设法通过更改OpenNI2 / Tools / OpenNI2 / Drivers文件夹中PS1080.ini中的设置来更改分辨率。在ini文件中,对于华硕,请确保

UsbInterface = 2

已启用。默认情况下,它为零。然后为深度和图像部分设置Resolution = 1。

我的Asus Xtion固件是v5.8.22。

答案 2 :(得分:1)

我已经尝试了@ 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。总之,我认为华硕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;
}

Here is the result:

答案 3 :(得分:0)

我遇到了同样的问题,但现在通过引用OpenNI2中的NiViewer示例解决了这个问题。显然,在您启动流(深度或颜色)之后,您必须停止它以更改分辨率然后开始

<system.web>
     <authentication mode="None" />
     <compilation debug="true" targetFramework="4.5.1" />
     <httpRuntime targetFramework="4.5.1" executionTimeout="240000" maxRequestLength="1073741824" />
     <identity impersonate="false" />
 </system.web>

我确认这适用于OpenNI2上的华硕Xtion。

希望这有帮助!

答案 4 :(得分:0)

最终结论:

实际上,这是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

  • 深度:320 * 240
  • 颜色:640 * 480

但是当您希望它们都是最高分辨率时:

  • 深度:640 * 480
  • 颜色:640 * 480

查看器程序开始在深度模式下遇到锐减帧(在我的情况下),但是由于查看器以非阻塞方式检索深度帧(默认代码以阻塞方式编写),因此您仍然看到颜色正常更新,而深度每两秒或更长时间更新一次。

总结

您只能将“深度”或“颜色”设置为640 * 480,将另一个设置为320 * 240。