首页 > 解决方案 > 比 C++ 中的 OpenCV 库更快地获取总帧数和 FPS

问题描述

我需要检查哪些视频可以分析,哪些不能给出视频中的总帧数和视频的 fps。我创建了一个 c++ 程序来进行检查。分析每个视频不是一种选择,因为分析非常耗时。

我使用 OpenCV 库作为初学者:

    cv::VideoCapture vid_to_analyze;
    vid_to_analyze.open( me_vid.vid_path.string() );
    me_vid.total_frames= static_cast<int>(vid_to_analyze.get(CV_CAP_PROP_FRAME_COUNT));
    me_vid.fps=vid_to_analyze.get(CV_CAP_PROP_FPS);

    if (!vid_to_analyze.isOpened())
    {
        std::cout << "Skipping vid: "<< me_vid.vid_path.string()<<", couldn't open it" << std::endl;
    }
    if (me_vid.fps != me_vid.fps || me_vid.fps <= 0)
    {
        std::cout << "For video " << me_vid.vid_path.string() << std::endl;
        std::cout << "FPS of the video file cannot be determined, assuming 30"<< std::endl;
        me_vid.fps = 30;
    }

    vid_to_analyze.release();

然而,当调试时它变得非常缓慢(程序在没有附加调试器的情况下运行得更快,但考虑到它需要覆盖的视频数量仍然非常慢)。我认为这与每次打开(发布)视频时创建和删除 4 个线程有关。

如果我对实际从视频中获取帧数只是帧数和 fps 不感兴趣,如何以更快的方式获得总帧数和 fps (实际上不创建 4 个线程!!)。

有没有办法从 c++ 中使用 ffmpeg 库,那会更快吗?从哪里开始?

编辑:Valgrind 似乎同意,因为 (Ir=)91.66% 的时间花费在该vid_to_analyze.open阶段

标签: c++opencvvideoffmpeg

解决方案


视频的属性称为元数据

您可以通过限制视频文件格式来优化元数据的获取。

I/O 是您花费时间的地方。大部分 I/O 时间超出了程序的控制(留给操作系统和其他设备)。

以下是一些快速获取帧数的建议:
1. 为文件格式的元数据分配内存。
2. 块从文件中读取元数据到你的内存中。
3. 从元数据部分获取帧数。
前提是您的视频格式已经预先计算了帧数。

否则,请尽量保持 I/O 流:
1. 读入视频数据,如果可能,多帧。
2. 统计缓冲区的帧数。
3. 重复 #1。

您可以执行双缓冲和线程来加快速度:
1. “读取”线程将数据读入缓冲区。
缓冲区满后,它会读入另一个缓冲区。

  1. “处理”线程处理缓冲区中的数据。
    处理线程可能希望等待,直到有可用的缓冲区。

目标是提供足够的缓冲区,以便“读取”线程不会停止。“处理”线程将在“读取”线程正在读取时进行帧计数。(在等待 I/O 操作完成时有足够的时间进行处理。)

另外,查看“内存映射文件”。这是操作系统将文件视为内存的概念,必要时将文件块加载到内存中。


推荐阅读