2012-02-04 100 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 – 2012-02-04 06:25:47

回答

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 2012-02-04 10:18:34

+2

与frame.copyTo()相同。我更喜欢我的版本,因为它很干净,而OpenCV在不再使用时会自动释放内存。 – Sam 2012-02-04 15:55:55

+0

您的听起来更好。 – JonaGik 2012-02-05 01:12:25