OpenCV VideoWriter 帧率问题
Posted
技术标签:
【中文标题】OpenCV VideoWriter 帧率问题【英文标题】:OpenCV VideoWriter Framerate Issue 【发布时间】:2013-06-13 16:12:28 【问题描述】:我正在尝试将 1080p 网络摄像头中的视频录制到文件中。我在视频中设置了一个计时器,并且在每次试验中,视频播放器报告的时间戳(我使用的是 VLC)与视频中的时间不同步。它总是关闭几秒钟(通常视频内计时器比播放器报告的时间快)。
如下所示,我将 C++ 程序设置为在一个线程中捕获视频,并在另一个线程中录制。这工作正常,因为我的 CPU 使用率约为 200%(可能最大?)。我使用的是配备 OS X 10.8 @ 1.8 GHz Intel Core i7 的 Macbook Air。
我尝试将帧速率更改为 15fps,这会导致视频非常不稳定/缓慢。我还尝试将CV_CAP_PROP_FRAME_WIDTH
和CV_CAP_PROP_FRAME_HEIGHT
设置为较低的分辨率,这会导致视频速度变慢。看起来 1080p @ 30fps 可以产生良好的稳定视频,但它的播放速度总是比预期的要快。我也尝试在record << frame;
之后输入waitKey(10);
,但没有任何影响。
关于如何及时匹配视频有什么建议吗?
谢谢! 阿卡什
#include "opencv/cv.h"
#include "opencv/highgui.h"
#include <boost/thread.hpp>
using namespace cv;
void captureFunc(Mat *frame, VideoCapture *capture)
for(;;)
// get a new frame from camera
(*capture) >> (*frame);
int main(int, char**)
VideoCapture capture(0); // open the default camera
if( !capture.isOpened() )
printf("Camera failed to open!\n");
return -1;
capture.set(CV_CAP_PROP_FPS,30); //set capture rate to 30fps
Mat frame;
capture >> frame; // get first frame for size
// initialize recording of video
VideoWriter record("test.avi", CV_FOURCC('D','I','V','X'), 30, frame.size(), true);
if( !record.isOpened() )
printf("VideoWriter failed to open!\n");
return -1;
boost::thread captureThread(captureFunc, &frame, &capture); //start capture thread
sleep(1); //just to make sure capture thread is ready
for(;;)
// add frame to recorded video
record << frame;
return 0;
【问题讨论】:
尝试使用不同的编解码器和不同的 fps(25 可能是一个不错的选择)。 我尝试了 25 FPS 并使用 XVID 作为编解码器。对于大约 1.5 分钟的视频,它可以正常工作(有些部分快几秒,有些部分慢,所以平均下来),但在任何更短或更长的视频中,VLC 播放视频的时间都会比实际时间长 3-6 秒(例如计时器在视频中显示 5 分钟已过,但 VLC 将播放 5 分 6 秒) 在我录制 5 分钟视频的测试中,时间是同步的,直到大约 3 分 10 秒后。之后,差距有时会达到 6 秒,最终以大约 5 秒不同步结束。 【参考方案1】:经过一番调试,我解决了我的问题; VideoWriter 对输入帧的速率很挑剔,这是一个问题。
【讨论】:
+1 再次回答问题。但我注意到您的解决方案可能存在竞争条件,因为摄像头获取线程可能会在 VideoWriter 访问它的同时刷新 Mat“帧”。 这篇文章很棒,但如果你能写在这里并提供一个指向你网站的链接会更好。如果您更改了网址,则信息将丢失! 万一链接失效,写出来的内容基本上完全符合您的期望:必须在您初始化的格式中指定的 FPS 间隔准确地调用视频编写器“writeFrame()”它与。有道理。 @JonathanLeaders 这根本没有任何意义,如果我想制作一个两小时长的视频,我可以在 10 分钟内生成帧,我将不得不等待两个小时才能得到我的输出?非常奇怪。 确实没有意义。我认为问题在于您将frame
写入您的视频文件,无论它是否有新内容。发生的情况是您的输出中有几个视频帧,它们是相同的,因为您是从相同的输入帧创建它们的。你需要的不是玩时间。您需要的是同步读取和写入,以便您仅在有 new 框架时才写入。 (你可以用线程来做,但最简单的方法看起来像capture >> frame; process(frame); record << frame:
。【参考方案2】:
您需要同步您的读写功能。您的代码尽可能快地读取,并尽可能快地写入。您的输出视频可能看起来很慢,因为写入输出比读取输入更快(因为capture >>
正在等待您的相机),并且记录了几个相同的帧。
无需等待或同步即可编写意味着您可能会多次编写相同的内容(我认为这里发生的情况),或者丢失帧。
如果你想继续拥有线程,你可以,但你需要让你的写进程等待,直到有东西新要写。
同样,为了避免丢失帧或写入损坏的帧,您需要读取过程等到写入完成,以便可以安全地覆盖frame
。
由于线程无论如何都需要相互等待,所以线程根本没有意义。
我宁愿推荐这种更简单的方法:
for (;;)
capture >> frame;
process(frame); // whatever smart you need
record << frame;
如果您需要并行性,您将需要更复杂的同步机制,并且可能需要为您的帧设置某种 fifo。
【讨论】:
这是正确答案。正如 Gauthier 所写,代码中没有任何机制可以确保每次读取只有一次写入,因此每一帧我被写入的次数是不可预测的。以上是关于OpenCV VideoWriter 帧率问题的主要内容,如果未能解决你的问题,请参考以下文章