OpenCV-创建材质对象阵列

OpenCV - Creating an Array of Mat Objects

本文关键字:对象 阵列 创建 OpenCV-      更新时间:2023-10-16

我本以为这很琐碎,但我遇到了一些麻烦。

我想把一个视频文件读入内存,并把它存储在一个数组中。我希望数组是指向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);

我可以想象,由于它显示的是最后一个图像,数组中的所有指针都是相同的,因此,它修改的是相同的内存。然而,当我打印指针时,它们是不同的。

您的代码中还有更多的缺陷。其中至少有两个是:

  1. vidCap.get(CV_CAP_PROP_FRAME_COUNT);在大多数情况下不会返回正确的帧数。就是这样,ffmpeg做得再好不过了。对于某些编解码器来说,它是有效的,对于某些编解码来说,它不起作用。

  2. Mat矩阵有一个有趣的行为。它们实际上是指向矩阵数据的指针,而不是对象。当你说new Mat时,你只是创建了一个新的指针。再加上videoCap始终返回相同的内存区域,只返回新数据,您实际上会有一个指向最后一帧的指针向量。

您必须在单独的图像中捕获帧,并将其复制到保留位置:

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

请注意从指针数组到对象向量的变化。这避免了事先读取帧数的需要,也使代码更加安全。

但实际上有创建Mat数组的方法吗?在我的情况下,我真的看不到其他选项,但试图访问数组中的一个项会将数组视为一个Mat,并认为我正在尝试访问它的数据。

编辑:使用指针找到了一个解决方法:

Mat* array = new Mat[arraySize];