我想在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,同一台计算机,操作系统和设备上读取深度图像。
答案 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;
}
答案 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。其实是用
开头的当您将任一模式设置为640 * 480时,它仍然可以使用,即
或
但是当您希望它们都是最高分辨率时:
查看器程序开始在深度模式下遇到锐减帧(在我的情况下),但是由于查看器以非阻塞方式检索深度帧(默认代码以阻塞方式编写),因此您仍然看到颜色正常更新,而深度每两秒或更长时间更新一次。
总结
您只能将“深度”或“颜色”设置为640 * 480,将另一个设置为320 * 240。