我正在编写一个程序,涉及使用OpenCV从网络摄像机实时处理视频。我希望能够(在处理过程中的任何时间)捕获先前的图像(例如,说十秒)并保存到视频文件中。
我目前正在使用队列作为缓冲区(以推送'cv :: Mat'数据),但这显然效率不高,因为几秒钟的图像很快会耗尽所有PC内存。我尝试使用'cv :: imencode'压缩图像,但使用PNG没有太大区别,我需要一个使用硬盘驱动器内存的解决方案,并且可以高效地进行实时操作。
有人能提出一个非常简单有效的解决方案吗?
编辑:
这样每个人都明白我现在在做什么;这是10秒缓冲区的代码:
void run()
{
cv::VideoCapture cap(0);
double fps = cap.get(CV_CAP_PROP_FPS);
int buffer_lenght = 10; // in seconds
int wait = 1000.0/fps;
QTime time;
forever{
time.restart();
cv::mat image;
bool read = cap.read(image);
if(!read)
break;
bool locked = _mutex.tryLock(10);
if(locked){
if(image.data){
_buffer.push(image);
if((int)_buffer.size() > (fps*buffer_lenght))
_buffer.pop();
}
_mutex.unlock();
}
int time_taken = time.elapsed();
if(time_taken<wait)
msleep(wait-time_taken);
}
cap.release();
}
queue<cv::Mat> _buffer
和QMutex _mutex
是全局变量。如果您熟悉QT,信号和插槽等,我有一个抓取缓冲区的插槽,并使用cv :: VideoWriter将其保存为视频。
编辑:
我认为理想的解决方案是让queue<cv::Mat> _buffer
使用硬盘内存而不是 pc内存。不确定哪个星球可行? :/
答案 0 :(得分:3)
我建议使用x264或类似内容进行实时压缩。 x264经常用于real-time encoding视频流,并且通过正确的设置,可以在中等功率处理器中编码多个流或1080p视频流。 我建议在doom9's forum或类似的论坛中提问。
x264是一个免费的h.264编码器,可以实现100:1或更好(与原始)压缩。 x264的输出可以存储在您的内存队列中,其效率远高于未压缩(或无损压缩)的视频。
答案 1 :(得分:0)
<强>已更新强>
您可以做的一件事是使用imwrite
将图像存储到硬盘,并将其文件名更新到队列中。当队列已满时,在弹出文件名时删除图像
在您的视频刻录插槽中,加载从队列中弹出的图像并将其写入VideoWriter
实例
您提到需要使用硬盘内存
在这种情况下,请考虑使用 OpenCV HighGUI VideoWriter 。您可以创建一个VideoWriter实例,如下所示:
VideoWriter record("RobotVideo.avi", CV_FOURCC('D','I','V','X'),
30, frame.size(), true);
将图像捕获写入如下:
record.write(image);
在网站上找到documentation和sample program。