我正在尝试从相机中获取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?
答案 0 :(得分:4)
据我所知,CV_CAP_PROP_FPS仅适用于视频。如果您想从网络摄像头捕获视频数据,您必须自己正确计时。例如,使用计时器每40毫秒从网络摄像头捕获一帧,然后保存为25fps视频。
答案 1 :(得分:2)
您可以使用VideoCapture::set(CV_CAP_PROP_FPS)
为网络摄像头设置所需的FPS。但是,出于某种原因你不能使用get。
请注意,根据网络摄像头的限制,有时驾驶员会根据您的要求选择不同的FPS。
我的解决方法:在几秒钟内捕获帧(我的测试中有4帧正常,初始延迟为0.5秒),并估算相机输出的帧数。
答案 2 :(得分: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将是经过的挂钟时间除以当前帧数。
答案 3 :(得分:0)
对于来自网络摄像头的实时视频,请使用cap.get(cv2.CAP_PROP_FPS)