Openni2 читает записи (.oni) в неправильном порядке
У меня проблемы с чтением записи, которую я сделал, используя класс Recorder в openni2 с asus Xtion PRO LIVE. Проблема заключается в том, что после того, как каждые ~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, но это только ухудшило ситуацию. Файл, который я пытаюсь загрузить, превышает 1 ГБ, но я не уверен, что это проблема. Поведение кажется случайным, потому что индексы неправильных изображений не всегда одинаковы.
ОБНОВЛЕНИЕ: я изменил функцию поиска, чтобы искать в потоке цвета вместо потока глубины. Я также обеспечил, чтобы каждый поток ожидался только один раз в функции waitForAnyStream, установив для соответствующей точки в m_streams значение null.
Я узнал, что можно найти фактический индекс кадра для каждого кадра (.getFrameIndex), поэтому я смог сравнить индексы. После получения 1000 изображений там было 18 неправильных цветных изображений, 17 из которых имели ошибку индекса 53, а 1 имела ошибку 46. Глубинные изображения имели почти постоянную ошибку индекса 9.
Второе, что я обнаружил, было то, что после добавления периода ожидания в 1 мс (также пробовал 10 мс, но результаты были такими же) перед функцией waitForAnyStream, возвращаемые индексы значительно менялись. Индексы больше не делают больших скачков, но цветные изображения имеют стандартное смещение 53, а изображения глубины имеют смещение 9.
Когда я изменяю функцию поиска для поиска в потоке глубины, тогда с задержкой цветовой поток имеет постоянную ошибку 46, а поток глубины имеет ошибку 1. Без задержки поток цвета имеет ошибку 45, а поток глубины не имеет ошибок со случайными всплесками ошибок 1.
Я также посмотрел на индексы, когда я не использую search и waitForAnyStream, а просто делаю это, как предлагается в качестве ответа в "OpenNI2: чтение в записи.oni". Это показывает, что когда файл читается простым вызовом m_readframe несколько раз, то первый цветной фрейм имеет индекс 59 вместо 0. После проверки выясняется, что фрейм 0 действительно существует и является более ранним фреймом, чем фрейм 59. Так что просто открываем файл и использование readframe не работает вообще. Однако ошибок индекса нет, как, например, когда я добавил сон в мою собственную реализацию.
ОБНОВЛЕНИЕ 2: Я пришел к выводу, что либо библиотека 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. Здесь цветные изображения будут отображаться нормально, но глубина изображения будет обновляться очень редко.