如何在python中使用cv2知道文件中的帧总数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25359288/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 20:06:33  来源:igfitidea点击:

How to know total number of Frame in a file with cv2 in python

pythonopencvvideoframeframe-rate

提问by Niraj

How to know total number of Frame in a file ( .avi) through Python using open cv module.

如何使用 open cv 模块通过 Python 了解文件 (.avi) 中的帧总数。

If possible what all the information (resolution, fps,duration,etc) we can get of a video file through this.

如果可能的话,我们可以通过此获取视频文件的所有信息(分辨率、fps、持续时间等)。

回答by berak

import cv2

cap = cv2.VideoCapture(fn)

if not cap.isOpened(): 
    print "could not open :",fn
    return

length = int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_COUNT))
width  = int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT))
fps    = cap.get(cv2.cv.CV_CAP_PROP_FPS)

see herefor more info.

请参阅此处了解更多信息。

also, all of it with a grain of salt, not all those props are mandatory, some might not be available with your capture / video codec

此外,所有这些都带有一丝盐分,并非所有这些道具都是强制性的,有些可能不适用于您的捕获/视频编解码器

回答by rbaleksandar

Another solution that doesn't depend on the sometimes buggy CV_CAP_PROPgetters is to traverse your whole video file in a loop

另一个不依赖于有时有问题的CV_CAP_PROPgetter 的解决方案是循环遍历整个视频文件

  • Increase a frame countervariable every time a valid frame is encountered and stop when an invalid one comes (end of the video file).
  • Gathering information about the resolutionis trickier because some codecs support variable resolution (similar to VBR in audio files where the bitrate is not a constant but instead covers some predefined range).

    • constant resolution- you need only the first frame to determine the resolution of the whole video file in this case so traversing the full video is not required
    • variable resolution- you need to get the resolution of every single frame (width and height) and calculate an average to get the average resolution of the video
  • FPScan be calculated however here you have the same problem as with the resolution - constant (CFR) vs variable (VFR). This is more of a mutli-threading problem omho. Personally I would use a frame counter, which increased after each valid frame while at an interval of 1 second a timer (running in a background thread) would trigger saving the current counter's value and then resetting it. You can store the values in a list in order to calculate the average/constant frame rate at the end when you will also know the total number of frames the video has.

  • 每次遇到有效帧时增加帧计数器变量,并在无效帧出现时停止(视频文件结尾)。
  • 收集有关分辨率的信息比较棘手,因为一些编解码器支持可变分辨率(类似于音频文件中的 VBR,其中比特率不是常数而是覆盖一些预定义的范围)。

    • 恒定分辨率- 在这种情况下,您只需要第一帧来确定整个视频文件的分辨率,因此不需要遍历整个视频
    • 可变分辨率- 您需要获取每一帧(宽度和高度)的分辨率并计算平均值以获得视频的平均分辨率
  • 可以计算FPS,但是在这里您遇到与分辨率相同的问题 - 常数 (CFR) 与变量 (VFR)。这更像是一个多线程问题。就我个人而言,我会使用一个帧计数器,它在每个有效帧之后增加,而计时器(在后台线程中运行)会以 1 秒的间隔触发保存当前计数器的值,然后将其重置。您可以将这些值存储在列表中,以便在最后计算平均/恒定帧速率,同时您还将知道视频的总帧数。

The disadvantage of this rather simplistic way of doing things is that you have to traverse the whole file, which - in case it's several hours long - will definitely be noticeable by the user. In this case you can be smart about it and do that in a background process while letting the user do something else while your application is gathering this information about the loaded video file.

这种相当简单的做事方式的缺点是您必须遍历整个文件,如果它长达几个小时,用户肯定会注意到。在这种情况下,您可以聪明一点,在后台进程中执行此操作,同时让用户在您的应用程序收集有关已加载视频文件的信息时执行其他操作。

The advantage is that no matter what video file you have as long as OpenCV can read from it you will get quite accurate results unlike the CV_CAP_PROPwhich may or may not work as you expect it to.

优点是无论您拥有什么视频文件,只要 OpenCV 可以从中读取,您都会获得非常准确的结果,CV_CAP_PROP这与您期望的结果可能会或可能不会工作不同。

回答by phev8

With a newer OpenCV version (I use 3.1.0) it works like this:

使用较新的 OpenCV 版本(我使用 3.1.0),它的工作方式如下:

import cv2

cap = cv2.VideoCapture("video.mp4")
length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
print( length )

And similar for other video properties cv2.CAP_PROP_*

和其他视频属性类似 cv2.CAP_PROP_*

回答by MGLondon

Here is how it works with Python 3.6.5 (on Anaconda) and OpenCV 3.4.2. [Note]: You need to drop the "CV_" from the "CV_CAP_PROP_xx" for any property as given on the official OpenCV website.

以下是它如何与 Python 3.6.5(在 Anaconda 上)和 OpenCV 3.4.2 配合使用。[注意]:对于 OpenCV 官方网站上给出的任何属性,您需要从“CV_CAP_PROP_xx”中删除“CV_” 。

import cv2
cap = cv2.VideoCapture("video.mp4")
property_id = int(cv2.CAP_PROP_FRAME_COUNT) 
length = int(cv2.VideoCapture.get(cap, property_id))
print( length )

回答by nathancy

There are two methods to determine the number of frames in a video file

有两种方法可以确定视频文件中的帧数

  • Method #1: Utilize built-in OpenCV properties to access video file meta information which is fast and efficient but inaccurate
  • Method #2: Manually loop over each frame in the video file with a counter which is slow and inefficient but accurate
  • 方法#1:利用内置的OpenCV属性访问视频文件元信息,快速高效但不准确
  • 方法#2:使用计数器手动循环视频文件中的每一帧,该计数器缓慢且低效但准确

Method #1 is fast and relys on OpenCV's video property functionalitywhich almost instantaneously determines the number of frames in a video file. However, there is an accuracy trade-off since it is dependent on your OpenCV and video codec versions. On the otherhand, manually counting each frame will be 100% accurate although it will be significantly slower. Here's a function that attempts to perform Method #1 by default, if it fails, it will automatically utilize method #2

方法 #1 速度很快,并且依赖于 OpenCV 的视频属性功能,该功能几乎可以立即确定视频文件中的帧数。但是,存在准确性权衡,因为它取决于您的 OpenCV 和视频编解码器版本。另一方面,手动计算每一帧将是 100% 准确的,尽管它会慢得多。这是一个默认尝试执行方法 #1 的函数,如果失败,它将自动使用方法 #2

def frame_count(video_path, manual=False):
    def manual_count(handler):
        frames = 0
        while True:
            status, frame = handler.read()
            if not status:
                break
            frames += 1
        return frames 

    cap = cv2.VideoCapture(video_path)
    # Slow, inefficient but 100% accurate method 
    if manual:
        frames = manual_count(cap)
    # Fast, efficient but inaccurate method
    else:
        try:
            frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
        except:
            frames = manual_count(cap)
    cap.release()
    return frames


Benchmarks

基准

if __name__ == '__main__':
    import timeit
    import cv2

    start = timeit.default_timer()
    print('frames:', frame_count('fedex.mp4', manual=False))
    print(timeit.default_timer() - start, '(s)')

    start = timeit.default_timer()
    print('frames:', frame_count('fedex.mp4', manual=True))
    print(timeit.default_timer() - start, '(s)')

Method #1 results

方法 #1 结果

frames: 3671
0.018054921 (s)

Method #2 results

方法#2 结果

frames: 3521
9.447095287 (s)

Note the two methods differ by 150 frames and Method #2 is significantly slower than Method #1. Therefore if you need speed but willing to sacrifice accuracy, use Method #1. In situations where you're fine with a delay but need the exact number of frames, use Method #2

请注意,这两种方法相差 150 帧,并且方法 #2 比方法 #1 慢得多。因此,如果您需要速度但愿意牺牲准确性,请使用方法 #1。在您可以接受延迟但需要确切帧数的情况下,请使用方法 #2