我在阅读使用asus Xtion PRO LIVE在openni2中使用Recorder类创建的录音时遇到问题。问题是每隔约50帧从记录中读取一个错误的帧,这是通过将生成的图像(转换为opencv矩阵)存储为带有索引的.png图像(使用opencv imwrite函数)来测试的。下面显示的是我的代码,我也尝试了在" OpenNI2中发布的代码:在.oni Recording"题。这也行不通。视频流,设备,videoFrameRefs和回放控制器都在初始化函数中初始化。如有必要,我也可以发布此内容。
openni::VideoStream depthStream;
openni::VideoStream colorStream;
openni::Device device;
openni::VideoFrameRef m_depthFrame;
openni::VideoFrameRef m_colorFrame;
openni::PlaybackControl *controler;
typedef struct _ImagePair {
cv::Mat GrayscaleImage;
cv::Mat DepthImage;
cv::Mat RGBImage;
float AverageDistance;
std::string FileName;
int index;
}ImagePair;
ImagePair SensorData::getNextRawImagePair(){
ImagePair result;
openni::Status rc;
std::cout<<"Getting next raw image pair...";
rc = controler->seek(depthStream, rawPairIndex);
if(!correctStatus(rc,"Seek depth"))return result;
openni::VideoStream** m_streams = new openni::VideoStream*[2];
m_streams[0] = &depthStream;
m_streams[1] = &colorStream;
bool newDepth=false,newColor=false;
while(!newDepth || !newColor){
int changedIndex;
openni::Status rc = openni::OpenNI::waitForAnyStream(m_streams, 2, &changedIndex);
if (rc != openni::STATUS_OK)
{
printf("Wait failed\n");
//return 1;
}
switch (changedIndex)
{
case 0:
rc = depthStream.readFrame(&m_depthFrame);
if(!correctStatus(rc,"Read depth")){
return result;
}
newDepth = true;
break;
case 1:
rc = colorStream.readFrame(&m_colorFrame);
if(!correctStatus(rc,"Read color")){
return result;
}
newColor = true;
break;
default:
printf("Error in wait\n");
}
}
//convert rgb to bgr cv::matrix
cv::Mat cv_image;
const openni::RGB888Pixel* colorImageBuffer = (const openni::RGB888Pixel*)m_colorFrame.getData();
cv_image.create(m_colorFrame.getHeight(), m_colorFrame.getWidth(), CV_8UC3);
memcpy( cv_image.data, colorImageBuffer,3*m_colorFrame.getHeight()*m_colorFrame.getWidth()*sizeof(uint8_t) );
//convert to BGR opencv color order
cv::cvtColor(cv_image,cv_image,cv::COLOR_RGB2BGR);
result.RGBImage = cv_image.clone();
//convert to grayscale
cv::cvtColor(cv_image,cv_image,cv::COLOR_BGR2GRAY);
result.GrayscaleImage =cv_image.clone();
//convert depth to cv::Mat INT16
const openni::DepthPixel* depthImageBuffer = (const openni::DepthPixel*)m_depthFrame.getData();
cv_image.create(m_depthFrame.getHeight(), m_depthFrame.getWidth(), CV_16UC1);
memcpy( cv_image.data, depthImageBuffer,m_depthFrame.getHeight()*m_depthFrame.getWidth()*sizeof(INT16) );
result.DepthImage = cv_image.clone();
result.index = rawPairIndex;
rawPairIndex++;
std::cout<<"done"<<std::endl;
return result;
}
我也尝试过没有使用waitForAnyStream部分,但这只会让它变得更糟。我试图加载的文件超过1GB,不确定是否有问题。行为似乎是随机的,因为错误图像的索引并不总是相同。
更新: 我改变了搜索功能,以寻找颜色流而不是深度流。我还确保每个流只在waitForAnyStream函数中等待一次,方法是将m_streams中的对应点设置为null。
我发现有可能找到每个帧的实际帧索引(.getFrameIndex),所以我能够比较索引。在获得1000张图像后,其中18个错误的彩色图像,其中17个的索引错误为53,1的错误为46.深度图像的索引误差几乎为9。
我发现的第二件事是在waitForAnyStream函数之前添加1 ms的睡眠(也尝试了10ms但结果相同)之后返回的索引发生了显着变化。指数不再产生大的跳跃,但彩色图像的标准偏移为53,深度图像的偏移量为9.
当我更改搜索功能以在深度流中搜索时,然后延迟颜色流的常数误差为46,深度流的误差为1.没有延迟,颜色流的误差为45,深度流没有错误,偶尔出现1个错误峰值。
当我不使用seek和waitForAnyStream时,我也查看了索引,但只是按照#34; OpenNI2:在.oni Recording&#34;中读取的答案。这表明当通过多次调用m_readframe来读取文件时,第一个颜色帧具有索引59而不是0.在检查之后,结果表明第0帧确实存在并且是比第59帧更早的帧。所以只需打开文件并使用readframe根本不起作用。然而,没有索引错误,就像我将睡眠添加到我自己的实现时一样。
UPDATE2: 我得出结论,openni2库无法正常工作或我安装错误。这是因为我在将Xtion设置为两个流的分辨率为640x480时也遇到了问题。当我这样做时,深度图像每隔约100秒才更新一次。我已经为我的原始问题编写了一个快速修复方法,只需过滤掉索引错误的帧并继续下一个图像。
我仍然想知道如何解决这个问题,所以如果你知道请告诉我。
更新3: 我用来设置帧率和fps进行录制的代码是:
//colorstream
openni::VideoMode color_videoMode = m_colorStream.getVideoMode();
color_videoMode.setResolution(WIDTH,HEIGHT);
color_videoMode.setFps(30);
m_colorStream.setVideoMode(color_videoMode);
//depth stream
openni::VideoMode depth_videoMode = m_depthStream.getVideoMode();
depth_videoMode.setResolution(WIDTH,HEIGHT);
depth_videoMode.setFps(30);
m_depthStream.setVideoMode(depth_videoMode);
我忘了提到我还通过运行sampleviewer示例程序(我想,几个月前)和更改xml配置文件中的分辨率来测试分辨率。这里的彩色图像会很好,但深度图像很少会更新。