我试图从我的相机获取fps,以便我可以将它传递给VideoWriter
输出video。 不过,我通过从相机调用VideoCapture::get(CV_CAP_PROP_FPS)
来获得0 fps。 如果我硬编码,我的video可能太慢或太快。
#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或给FPS的VideoWriter
,普遍适用于所有的摄像头?
据我所知,CV_CAP_PROP_FPS只适用于视频。 如果你想从网络摄像头捕捉视频数据,你必须自己正确的时间。 例如,使用计时器每40毫秒从网络摄像头捕获帧,然后保存为25fps的视频。
您可以使用VideoCapture::set(CV_CAP_PROP_FPS)
为网络摄像头设置所需的FPS。 但是,由于某种原因你不能使用get。
请注意,有时驾驶员会根据网络摄像机的限制选择不同的FPS。
我的解决方法:在几秒钟内捕捉帧(在我的测试中,4是罚款,0.5秒的初始延迟),并估计相机输出的fps。
我从来没有观察到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的其他方法失败了,那么你可能只想做后者,而且没有更好的方法来总结整个持续时间和帧数信息。
上面的例子在一个文件上工作 – 为了适应一个摄像头,你可以使用自从捕获开始以来经过的wallclock时间,而不是获取CV_CAP_PROP_POS_MSEC
。 那么会话的平均fps将是经过的挂钟时间除以当前帧数。
对于来自摄像头的实时视频,请使用cap.get(cv2.CAP_PROP_FPS)