C++ OpenCV:VideoCapture::get(CV_CAP_PROP_FPS) 返回 0 FPS
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19662193/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
OpenCV: VideoCapture::get(CV_CAP_PROP_FPS) returns 0 FPS
提问by swtdrgn
I am trying to get the fps from my camera so that I can pass it to the VideoWriter
for outputting the video. However, I am getting 0 fps by calling VideoCapture::get(CV_CAP_PROP_FPS)
from my camera. If I hardcode it, my video may be too slow or too fast.
我试图从我的相机获取 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);
}
How can I get VideoCapture::get(CV_CAP_PROP_FPS)
to return the right fps or give a fps to the VideoWriter
that works universally for all webcams?
我如何才能VideoCapture::get(CV_CAP_PROP_FPS)
返回正确的 fps 或VideoWriter
为所有网络摄像头普遍适用的 fps 提供?
回答by littleimp
CV_CAP_PROP_FPS only works on videos as far as I know. If you want to capture video data from a webcam you have to time it correctly yourself. For example use a timer to capture a frame from the webcam every 40ms and then save as 25fps video.
据我所知,CV_CAP_PROP_FPS 仅适用于视频。如果您想从网络摄像头捕获视频数据,您必须自己正确计时。例如,使用计时器每 40 毫秒从网络摄像头捕获一帧,然后保存为 25fps 的视频。
回答by Jose Gómez
You can use VideoCapture::set(CV_CAP_PROP_FPS)
to set the desired FPS for a webcam. However, you can't use get for some reason.
您可以使用VideoCapture::set(CV_CAP_PROP_FPS)
为网络摄像头设置所需的 FPS。但是,由于某种原因,您不能使用 get。
Note that sometimes the driver will choose a different FPS than what you have requested depending on the limitations of the webcam.
请注意,有时根据网络摄像头的限制,驱动程序会选择与您要求的 FPS 不同的 FPS。
My workaround:capture frames during a few seconds (4 is fine in my tests, with 0.5 seconds of initial delay), and estimate the fps the camera outputs.
我的解决方法:在几秒钟内捕获帧(4 在我的测试中很好,初始延迟为 0.5 秒),并估计相机输出的 fps。
回答by Jameson
I've never observed CV_CAP_PROP_FPS
to work. I have tried with various flavors of OpenCV 2.4.x (currently 2.4.11) using file inputs.
我从来没有观察CV_CAP_PROP_FPS
到工作。我尝试过使用文件输入的各种 OpenCV 2.4.x(当前为 2.4.11)。
As a workaround in one scenario, I directly used libavformat (from ffmpeg) to get the frame rate, which I can then use in my other OpenCV code:
作为一种情况的解决方法,我直接使用 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;
}
Aside from that, undoubtedly one of the slowest possible (although sure to work) methods to get the average fps, would be to step through each frame and divide the current frame number by the current time:
除此之外,毫无疑问,获得平均 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 ...
}
You'd probably only want to do the latter if the other methods of directly finding the fps failed, and further, there were no better way to summarily get overall duration and frame count information.
如果直接查找 fps 的其他方法失败,您可能只想执行后者,此外,没有更好的方法来概括地获取总体持续时间和帧数信息。
The example above works on a file -- to adapt to a camera, you could use elapsed wallclock time since beginning of capture, instead of getting CV_CAP_PROP_POS_MSEC
. Then the average fps for the session would be the elapsed wall clock time divided by the current frame number.
上面的示例适用于文件 - 为了适应相机,您可以使用自捕获开始以来经过的挂钟时间,而不是获取CV_CAP_PROP_POS_MSEC
. 然后会话的平均 fps 将是经过的挂钟时间除以当前帧数。
回答by Athul Soori
For live video from webcam use cap.get(cv2.CAP_PROP_FPS)
对于来自网络摄像头的实时视频,请使用 cap.get(cv2.CAP_PROP_FPS)