OpenCV - 创建一个垫对象数组

Posted

技术标签:

【中文标题】OpenCV - 创建一个垫对象数组【英文标题】:OpenCV - Creating an Array of Mat Objects 【发布时间】:2012-02-04 04:57:34 【问题描述】:

我原以为这是微不足道的,但我遇到了一些麻烦。

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

但是,当我显示图像(例如,数组中的第一张图像)时,它会显示 last 帧。我哪里错了?这是显示图像的代码:

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

我想,因为它显示的是最后一张图像,所以数组中的所有指针都是相同的,因此它正在修改相同的内存。但是,当我打印指针时,它们是不同的。

【问题讨论】:

您可能在以下线程中遇到了问题。 ***.com/questions/1356543/… 【参考方案1】:

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

    vidCap.get(CV_CAP_PROP_FRAME_COUNT); 在大多数情况下不会返回正确的帧数。就是这样,ffmpeg不能做得更好。对于某些编解码器,它可以工作,而对于某些编解码器,则不能。

    Mat 矩阵有一个有趣的行为。它们实际上是指向矩阵数据的指针,而不是对象。当您说new Mat 时,您只需创建一个新指针。结合 videoCap 始终返回相同内存区域的事实,仅使用新数据,您实际上将有一个指向最后一帧的指针向量。

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

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

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

【讨论】:

感谢您的回答!我发现“cap >> frame”填充了每个 Mat 对象的参数,但没有复制数据。为了解决这个问题,我从堆中获取了一些内存,将数据复制到该内存,然后设置“frame.data = myMemoryPtr”,其中 myMemoryPtr 是指向已分配内存的指针。 这与 frame.copyTo() 相同。我更喜欢我的版本,因为它很干净,而且 OpenCV 会在不再使用时自动释放内存 关于你的第一点,有没有办法解决这个问题?如何找到视频中的帧数? 没有什么值得努力的。但是您可以使用动态数组来保存帧。vector 与 Mat** 一样好。【参考方案2】:

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

编辑:找到使用指针的解决方法:

Mat* array = new Mat[arraySize];

【讨论】:

我是否理解正确,您创建此帖子是为了提出与此页面顶部的问题不同的问题,然后对其进行了编辑,以回答您自己的问题,该问题没有回答本页顶部? 即使我错了,请拿tour阅读How to Answer。 这没有提供问题的答案。您可以search for similar questions,或参考页面右侧的相关和链接问题找到答案。如果您有一个相关但不同的问题,ask a new question,并包含指向此问题的链接以帮助提供上下文。见:Ask questions, get answers, no distractions

以上是关于OpenCV - 创建一个垫对象数组的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV 填充垫,与 VideoWriter 一起使用

OpenCV的Mat对象如何定义数组?

角垫复选框动态与ngModel

OpenCv c++ 为基本打印垫功能创建一个 C 包装器?

opencv学习-第四节:图像对象的创建与赋值

角材料:垫选择不选择默认