OpenCV:VideoCapture::get(CV_CAP_PROP_FPS) 返回 0 FPS

Posted

技术标签:

【中文标题】OpenCV:VideoCapture::get(CV_CAP_PROP_FPS) 返回 0 FPS【英文标题】:OpenCV: VideoCapture::get(CV_CAP_PROP_FPS) returns 0 FPS 【发布时间】:2013-11-08 20:13:12 【问题描述】:

我正在尝试从我的相机中获取 fps,以便我可以将其传递给 VideoWriter 以输出视频。但是,通过从我的相机调用VideoCapture::get(CV_CAP_PROP_FPS),我得到了 0 fps。如果我对其进行硬编码,我的视频可能会太慢或太快。

#include "opencv2/opencv.hpp"
#include <stdio.h>
#include <stdlib.h>

using namespace std;
using namespace cv;

int main(int argc, char *argv[])

    cv::VideoCapture cap;
    int key = 0;

    if(argc > 1)
        cap.open(string(argv[1]));
    
    else
    
        cap.open(CV_CAP_ANY);
    
    if(!cap.isOpened())
    
        printf("Error: could not load a camera or video.\n");
    

    Mat frame;
    cap >> frame;
    waitKey(5);

    namedWindow("video", 1);
    double fps = cap.get(CV_CAP_PROP_FPS);
    CvSize size = cvSize((int)cap.get(CV_CAP_PROP_FRAME_WIDTH),(int)cap.get(CV_CAP_PROP_FRAME_HEIGHT));

    int codec = CV_FOURCC('M', 'J', 'P', 'G');
    if(!codec) waitKey(0); return 0; 
    std::cout << "CODEC: " << codec << std::endl;
    std::cout << "FPS: " << fps << std::endl;
    VideoWriter v("Hello.avi",-1,fps,size);
    while(key != 'q')
        cap >> frame;
        if(!frame.data)
        
            printf("Error: no frame data.\n");
            break;
        
        if(frame.empty()) break; 
        v << frame;
        imshow("video", frame);
        key = waitKey(5);
    
    return(0);

如何让 VideoCapture::get(CV_CAP_PROP_FPS) 返回正确的 fps 或为 VideoWriter 提供适用于所有网络摄像头的 fps?

【问题讨论】:

【参考方案1】:

据我所知,CV_CAP_PROP_FPS 仅适用于视频。如果您想从网络摄像头捕获视频数据,您必须自己正确计时。例如,使用计时器每 40 毫秒从网络摄像头捕获一帧,然后保存为 25fps 视频。

【讨论】:

该提议几乎可以保证会产生不流畅的视频,因为视频中捕获的 fps 与网络摄像头的捕获 fps 不匹配。 你能详细说明一下吗?为什么会产生生涩的视频? 网络摄像头使用固定或定义的帧率进行捕捉。对于给定的分辨率,捕获将以 15 fps、25 fps、60 fps... 这取决于网络摄像头的速度、链接的带宽、驱动程序和设置。如果网络摄像头的帧率与您拍摄的帧不匹配,有时您可能会两次拍摄同一帧,有时您可能会跳帧,因此运动会不流畅。 获得平滑运动的方法是设置所需的 FPS(如果驱动程序允许,请参阅我在 ***.com/a/22920585/1816603 中的回复)并以网络摄像头提供的帧速率(或分隔线)进行捕捉其中,例如 60 -> 30, 50 -> 25, 30 -> 15)。 好的,谢谢您的解释。不过,我仍然需要手动计时,对吧?【参考方案2】:

您可以使用VideoCapture::set(CV_CAP_PROP_FPS) 为网络摄像头设置所需的 FPS。但是,由于某种原因,您不能使用 get。

请注意,有时驱动程序会根据网络摄像头的限制选择与您要求的不同的 FPS。

我的解决方法:在几秒钟内捕获帧(在我的测试中可以捕获 4 帧,初始延迟为 0.5 秒),并估计相机输出的 fps。

【讨论】:

【参考方案3】:

我从未观察到CV_CAP_PROP_FPS 工作。我尝试过使用文件输入的各种风格的 OpenCV 2.4.x(当前为 2.4.11)。

作为一种解决方法,我直接使用 libavformat(来自 ffmpeg)来获取帧速率,然后我可以在我的其他 OpenCV 代码中使用它:

static double get_frame_rate(const char *filePath) 
    AVFormatContext *gFormatCtx = avformat_alloc_context();
    av_register_all();

    if (avformat_open_input(&gFormatCtx, filePath, NULL, NULL) != 0) 
        return -1;
     else if (avformat_find_stream_info(gFormatCtx, NULL) < 0) 
        return -1;
     

    for (int i = 0; i < gFormatCtx->nb_streams; i++) 
        if (gFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) 
            AVRational rate = gFormatCtx->streams[i]->avg_frame_rate;
            return (double)av_q2d(rate);
        
    

    return -1;

除此之外,毫无疑问,获得平均 fps 的最慢的方法之一(尽管肯定有效)是逐步遍历每一帧并将当前帧数除以当前时间:

for (;;) 
    currentFrame = cap.get(CV_CAP_PROP_POS_FRAMES);
    currentTime = cap.get(CV_CAP_PROP_POS_MSEC);
    fps = currentFrame / (currentTime / 1000);

    # ... code ...
    # stop this loop when you're satisfied ...

如果直接查找 fps 的其他方法失败,您可能只想执行后者,此外,没有更好的方法来总结总体持续时间和帧数信息。

上面的例子适用于一个文件——为了适应相机,你可以使用从开始捕捉开始的挂钟时间,而不是得到CV_CAP_PROP_POS_MSEC。那么会话的平均 fps 将是经过的挂钟时间除以当前帧数。

【讨论】:

有用的信息。但是,该问题将(网络)摄像头称为输入,而不是使用视频文件。 @JoseGómez 最后一段不是为你做的,嗯? 是的,我错过了那个;这听起来很合理。基本上,您建议的是计算有效帧率,对吗?这是我最终采用的类似方法。请注意,我必须在初始延迟后才开始计算帧速率,以使数字准确(可能是由于一些初始化)。似乎很奇怪,为了像从网络摄像头获取视频流设置的当前帧速率这样简单的事情,必须经历这么多麻烦。 通常等待第一帧的时间最长。我在几个网络摄像头上测量了它,如果我们从第一帧开始 开始测量实时时间(不是墙上时间 - CPU 时间),则间隔非常一致。另请注意,有时cap.set(CV_CAP_PROP_FPS, /*someting*/) 有效。例如。在具有 V4L2 的 Linux 上,但前提是相机可以在物理上带来那么多 FPS。【参考方案4】:

对于来自网络摄像头的实时视频,请使用 cap.get(cv2.CAP_PROP_FPS)

【讨论】:

这就是 OP 所做的。这将返回 0。

以上是关于OpenCV:VideoCapture::get(CV_CAP_PROP_FPS) 返回 0 FPS的主要内容,如果未能解决你的问题,请参考以下文章

opencv 配置

OpenCV实战——OpenCV与图像处理

cmake错误:opencv2/opencv.hpp:opencv2/opencv.hpp:没有这样的文件或目录

opencv相机标定

opencv4opencv视频教程 C++(opencv教程)1opencv介绍和环境搭建

如何使用opencv实现图像匹配