OpenCV - creating an array of Mat objects

I would think this is trivial, but I have problems with that.

I want to read a video file in memory and store it in an array. I want the array to have pointers to Mat objects.

This is the code I'm using:

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]); } 

However, when I display an image (for example, the first image in an array), it displays the last frame. Where am I going wrong? This is the code to display the image:

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

I would suggest that since it displays the last image, all the pointers in the array are the same, and therefore it modifies the same memory. However, when I print pointers, they are different.

Thanks in advance for your help.

+4
source share
1 answer

There are still flaws in the code. At least two of them:

  • vidCap.get(CV_CAP_PROP_FRAME_COUNT); doesn't return the correct number of frames, most of the time. What is it, ffmpeg can't do better. For some codecs it works, for some it doesn't.

  • Matte matrices have interesting behavior. They actually point to matrix data, not objects. When you say new Mat , you simply create a new pointer. And in combination with the fact that videoCap all the time returns to the same memory area, only with new data, you will have a vector of pointers pointing to the last frame.

You must capture the frame in a separate image and copy to a reserved location:

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

Pay attention to changing the array of pointers to the vector of objects. This avoids the need to read the number of frames in advance, and also makes the code more secure.

+3
source

Source: https://habr.com/ru/post/1394733/


All Articles