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_WIDTHCV_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 &gt;&gt; frame; process(frame); record &lt;&lt; frame:【参考方案2】:

您需要同步您的读写功能。您的代码尽可能快地读取,并尽可能快地写入。您的输出视频可能看起来很慢,因为写入输出比读取输入更快(因为capture &gt;&gt; 正在等待您的相机),并且记录了几个相同的帧。

无需等待或同步即可编写意味着您可能会多次编写相同的内容(我认为这里发生的情况),或者丢失帧。

如果你想继续拥有线程,你可以,但你需要让你的写进程等待,直到有东西要写。

同样,为了避免丢失帧或写入损坏的帧,您需要读取过程等到写入完成,以便可以安全地覆盖frame

由于线程无论如何都需要相互等待,所以线程根本没有意义。

我宁愿推荐这种更简单的方法:

for (;;) 
    capture >> frame;
    process(frame);  // whatever smart you need
    record << frame;

如果您需要并行性,您将需要更复杂的同步机制,并且可能需要为您的帧设置某种 fifo。

【讨论】:

这是正确答案。正如 Gauthier 所写,代码中没有任何机制可以确保每次读取只有一次写入,因此每一帧我被写入的次数是不可预测的。

以上是关于OpenCV VideoWriter 帧率问题的主要内容,如果未能解决你的问题,请参考以下文章

opencv进行视频拍摄

Opencv保存视频

OPENCV,无法打开类 VideoWriter

OpenCV VideoWriter 不写任何东西

OpenCV:来自 VideoWriter 的写入是不是应该在独立线程中运行?

OpenCV videoWriter编解码器问题