Openni2读取记录(.oni)的顺序错误

时间:2014-12-09 14:19:30

标签: c++ opencv openni

我在阅读使用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配置文件中的分辨率来测试分辨率。这里的彩色图像会很好,但深度图像很少会更新。

0 个答案:

没有答案