13

我正在尝试从我的相机中获取 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?

4

4 回答 4

4

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

于 2013-10-30T12:19:35.540 回答
2

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

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

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

于 2014-04-07T18:49:00.277 回答
1

我从来没有观察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 将是经过的挂钟时间除以当前帧数。

于 2015-10-16T11:55:17.740 回答
-2

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

于 2017-07-25T17:06:10.600 回答