关于opencv使用CAP_PROP_FPS得到的摄像头帧率为0的解答和解决方案

这不是目录

  • 是个锤子的前言=-=
  • 一、CAP_PROP_FPS = 0的问题
  • 二、具体原因描述
    • 1.摄像头的不确定性
    • 2.解决方案
  • 总结


是个锤子的前言=-=

相信随着opencv的完善,越来越多的人会开始使用opencv作为一个视觉系统的解决方案,相比matlab,opencv有着自由度更高,更接近底层的编程特点(大概是C语言C++混编的优点吧),那么来说一下最近发现的一个BUG性问题,或者该说是无法解决的特性


一、CAP_PROP_FPS = 0的问题

CAP_PROP_FPS一般用于两种场景,一个是对视频的读取,读取视频并对视频的相关编码过程进行分析(比如我需要知道这个视频有多少帧,然后才能计算出物体移动的速度等等情况),这种情况下,VedioCapture::get(CAP_PROP_FPS)往往是有效的,可以准确读出视频的帧率。但是还有一种常见的使用情况,就是在通过使用USB摄像头的时候,VedioCapture::get(CAP_PROP_FPS)就有可能读不到FPS了,这种情况不算常见,但也不少见,在Linux系统下,能使用V4L2来进行强制编辑摄像头(不过我并没有使用过Linuxopencv,这点无法展开说明),而Windows系统则是使用Dshow来强制使用 Direct Show 打开摄像头,因而Dshow的方法不能保证获得摄像头的帧率

二、具体原因描述

1.摄像头的不确定性

这个在国内的论坛不好找,特别是现在 爬虫满天飞 的时代,同一篇文章可以在百度出现连续三页网页,我真的是无话可说,只能去科学上网查找资料了,一个是 github ,不过在github上面多数是解决opencvbug和特性的帖子,对这个问题并没有具体分析,虽然有人有相似的情况出现,但是并不是一样的结果,

他只是写错代码而已。。。。。。

那我们只能去其他论坛找答案了,那就Google吧

Webcams capture using a fixed or defined framerate. For a given resolution, capture will happen at 15 fps, 25 fps, 60 fps… That depends on the speed of the webcam, bandwidth of the link, driver, and settings. If the framerate of the webcam does not match the frames that you capture, sometimes you may capture the same frame twice, and sometimes you may skip frames, so the movement will not be smooth。

///
这里说的是,网络摄像头捕捉使用固定或定义的帧率。对于一个给定的分辨率,捕获将在15fps, 25fps, 60fps…这取决于网络摄像头的速度,链接的带宽,驱动程序和设置。如果网络摄像头的帧率与你所捕捉的帧不匹配,有时你可能会捕捉同一帧两次,有时你可能会跳过帧,所以运动不会顺利。

那也就是摄像头的帧率读取实际上并不是十分稳定的,根据带宽、线程等特点会有帧率的丢失或者冗余,因此Windows环境下读取帧率多数会不成功,例如以下代码:

#include
#include


using namespace cv;
using namespace std;

int main()
{
	VideoCapture cap1(0 + CAP_DSHOW);//这里Dshow的使用可能会出现问题,应该是语法错误
	if (!cap1.isOpened())
	{
		return -1;
	}
	Mat frame1;
	double FPS = cap1.get(CAP_PROP_FPS);
	cout << FPS << endl;
	while (1)
	{
		cap1 >> frame1;
		namedWindow("fuck");
		imshow("video1", frame1);
	
		waitKey(17);
	}
	return 0;
}

读取结果为

FPS = 0;

2.解决方案

解决方法也很简单,自己写一个帧率计算的算法,不过,准不准是另一回事了;

第一种写法,就是自己写一个计时器,可以用opencv的内置来写

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 ...
}

第二种写法,说实话,具体的看不懂,只能看个蒙懂,主要是不知道

AVFormatContext这个类不知道是哪里来的,也没去查(懒

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;
}

这段代码要是看得懂留个评论说明一下吧,真没接触过

总结

没有总结,只有对爬虫复制别人博客的无尽怨恨,吐了,整页百度都是同一篇文章

你可能感兴趣的:(opencv,视觉检测,opencv,c++)