我原以为这是微不足道的,但我遇到了一些麻烦。
我想将视频文件读入内存并将其存储在数组中。我希望数组是指向 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);
我可以想象,因为它显示的是最后一张图像,所以数组中的所有指针都是相同的,因此,它正在修改相同的内存。但是,当我打印指针时,它们是不同的。
最佳答案
您的代码中存在更多缺陷。其中至少有两个是:
vidCap.get(CV_CAP_PROP_FRAME_COUNT);
大多数时候不会返回正确的帧数。就是这样,ffmpeg不能做得更好了。对于某些编解码器,它可以工作,而对于某些编解码器,则不能。Mat 矩阵有一个有趣的行为。它们实际上是指向矩阵数据的指针,而不是对象。当您说
new Mat
时,您只是创建了一个新指针。结合 videoCap 始终返回同一内存区域这一事实,仅使用新数据,您实际上将拥有一个指向最后一帧的指针 vector 。
您必须在单独的图像中捕获帧并复制到保留位置:
std::vector<cv::Mat> frames;
cap >> frame;
frames.push_back(frame.clone());
请注意从指针数组到对象 vector 的变化。这避免了预先读取帧数的需要,也使代码更安全。
关于c++ - OpenCV - 创建一个 Mat 对象数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9138537/