2012-02-04 3 views
4

Я бы подумал, что это тривиально, но у меня проблемы с ним.OpenCV - Создание массива объектов Mat

Я хочу прочитать видеофайл в память и сохранить его в массиве. Я хочу, чтобы массив имел указатели на объекты Mat.

Это код, я использую:

cv::VideoCapture vidCap = cv::VideoCapture("file.avi"); 
int frames = (int)vidCap.get(CV_CAP_PROP_FRAME_COUNT); 
cv::Mat** frameArray = new cv::Mat*[frames]; 
for (int num = 0; num < frames; num++) { 
    frameArray[num] = new cv::Mat; 
    vidCap >> *(frameArray[num]); 
} 

Однако, когда я отобразить изображение (например, первое изображение в массиве), он отображает последний кадр. Где я иду не так? Это код для отображения изображения:

cv::namedWindow("Movie", 1); 
cv::imshow("Movie", *(frameArray[0])); 
cv::waitKey(0); 

Я предположил бы, что, так как он показывает последнее изображение, все указатели в массиве одинаковы и, следовательно, он модифицирует ту же память. Однако, когда я печатаю указатели, они разные.

Заранее за вашу помощь.

+0

У вас может возникнуть проблема, обсуждаемая в следующем потоке. http://stackoverflow.com/questions/1356543/cvgetcaptureproperty-always-return-0-for-cv-cap-prop-frame-count –

ответ

3

В коде есть еще недостатки. По крайней мере, два из них являются:

  1. vidCap.get(CV_CAP_PROP_FRAME_COUNT); не возвращает правильное количество кадров, большую часть времени. Вот и все, ffmpeg не может сделать лучше. Для некоторых кодеков он работает, для некоторых - нет.

  2. Матовые матрицы имеют интересное поведение. Они фактически указывают на данные матрицы, а не на объекты. Когда вы говорите new Mat, вы просто создаете новый указатель. И в сочетании с тем фактом, что videoCap все время возвращается в одну и ту же область памяти, только с новыми данными, у вас будет вектор указателей, указывающих на последний кадр.

Вы должны захватить кадр в отдельном изображении и скопировать в зарезервированном место:

std::vector<cv::Mat> frames; 
cap >> frame; 
frames.push_back(frame.clone()); 

Обратите внимание на изменение из массива указателей на вектор объектов. Это позволяет избежать необходимости предварительного считывания количества кадров, а также делает код более безопасным.

+1

Спасибо за ваш ответ! Я обнаружил, что «cap >> frame» заполняет каждый параметр объекта Mat, но не копировал данные. Чтобы обойти это, я получил некоторую память из кучи, скопировал данные в эту память, а затем установил «frame.data = myMemoryPtr», где myMemoryPtr - это указатель на выделенную память. – JonaGik

+2

это то же самое, что и frame.copyTo(). Я предпочитаю свою версию, так как она чистая, и OpenCV автоматически освобождает память, когда она больше не используется. – Sam

+0

Ваш звук звучит лучше. – JonaGik

Смежные вопросы