我使用下面的代码从相机读取每个帧并将其推送到矢量。这样做是为了在稍后的时间点处理向量中的所有收集的帧。
我使用以下代码从相机中收集帧。但是在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;
}
答案 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),以便编码器可以赶上。