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的主要内容,如果未能解决你的问题,请参考以下文章
cmake错误:opencv2/opencv.hpp:opencv2/opencv.hpp:没有这样的文件或目录