将视频文件推入向量时,向量内存不足?

时间:2013-05-07 12:55:54

标签: c++ opencv image-processing computer-vision

我使用下面的代码从相机读取每个帧并将其推送到矢量。这样做是为了在稍后的时间点处理向量中的所有收集的帧。

我使用以下代码从相机中收集帧。但是在2005帧之后,代码会抛出以下错误。

  

OpenCV错误:内存不足(无法分配921604字节)   OutOfMemoryError,文件   D:\ Opencv \ modules \ core \ src \ alloc.cpp,第52行

以下是我用来收集帧并将其推入矢量的代码。

#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/contrib/contrib.hpp"

#include <stdio.h>
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <stdlib.h>

 using namespace std;
 using namespace cv; 


 int main()
 {     

     VideoCapture capture(0); 
     if(!capture.isOpened()) 
         return -1; 
     vector <Mat>  frame;       
     int delay = 10;  
         int count = 0;

                Mat src;     

                while(true) { 
                    capture >> src;                                     
                    frame.push_back(src.clone());                                                            

                    imshow("VIDEO", src);
                    if( waitKey( delay ) >= 0) break; 
                    count = count+1;
                    cout << count << endl;
                } 


                /* I need to process each frame stored inside the vector*/

      destroyWindow("VIDEO");
      capture.release();

   return 0;
 }

3 个答案:

答案 0 :(得分:5)

你可能正在耗尽内存,就像错误所暗示的那样。如果每帧是640 * 480(即非常低的res),那么2005 * 640 * 480 * 3(每像素字节数)= 1,847,808,000(即在连续块中分配1.8GB的RAM)。

同样,每次向量必须调整自身大小时,需要进行足够大的分配来保存新数据,然后将旧数据复制到新向量,然后释放旧分配,有效地将所需内存量增加一倍

答案 1 :(得分:2)

如上所述,您的程序已达到操作系统为您的进程保留的RAM限制。你可以做一些事情来减少这个问题:

1 - Encode the image to a more compact format,与.jpg一样。这将减少帧使用的内存。

2 - Save your buffer on disk。由于这可能很慢,并且您不想丢失帧速率,因此您可能需要在生产者/消费者计划中使用新线程。

3 - 降低图像的分辨率。我不知道您的具体用例,但缩小的图像可适用于许多计算机视觉算法。无需存储所有颜色信息。

4 - 只存储图像的有趣点:这是计算机视觉社区中非常常见的方法。同样,我不知道你想要完成什么,但也许你可以对每个帧的图像进行一些预处理并只存储相关的点?也许你需要一些GPU实现的预处理算法来实时保持帧速率。

请记住,即使您大幅减少每帧存储的内存量,您最终仍会耗尽内存。如果不保存磁盘上的信息,这几乎可以保证。

答案 2 :(得分:2)

原始框架尺寸很大。您通常应该预分配至少2帧而不是4,这取决于相机源的抖动量。多媒体系统始终预先分配内存。

所以你通常应该做..

for(int i=0; i<NUM_FRAMES; i++
    frames.push_back(new Mat()); //handle exceptions from new.

然后使用框架回收

int i=0;
int curr_frame=i;

while(true) { 
   capture >> *(frames[i]); 

   //show frame

   i = (i+1)%NUM_FRAMES;

   //process frames[curr_frame]..
}

您应该实时进行处理,最好是在单独的线程上进行。因此,您的处理时间必须与相机捕获率大致相符。也就是说,您不应该处理某个帧,而是被相机覆盖。如果算法的处理时间是可变的,例如在视频编码器中,则抖动缓冲有助于。将有足够数量的缓冲区(NUM_FRAMES),以便编码器可以赶上。