opencv 使用PyAV的视频中的帧数

5gfr0r5j  于 2023-02-05  发布在  其他
关注(0)|答案(3)|浏览(334)

我使用PyAV库是因为它是Python中可用的最快的库之一。
下面是我想使用的代码的一个简单示例:

import av

video = av.open("My_Super_Video.mp4")

total_frames = # ????

for i, frame in enumerate(video.decode(video=0)):
    img = frame.to_image()  # PIL image

    print("Frame: %d/%d ..." % (i, total_frames))

我当然可以使用其他库来加载这个库,但是如果可能的话,我更喜欢使用PyAV,因为它的处理速度很快。

    • 问题1:**是否可以通过PyAV获得帧数?如果可以,如何获得?
    • 问题2:**在这种情况下,我会考虑使用另一个库来逐帧加载和处理视频。哪个库可以让我以最快的速度完成上述工作。我知道以下几个库,但不知道它们的比较结果如何:

1.* * PIMS在PyAV之上,可以添加一些有趣的特性吗?
1.* * MoviePy
(仅限于适合RAM的视频),但性能呢?
1.* * Imageio**(可能与上述限制相同),但perf怎么办?
1.* * OpenCV**(可能与上述限制相同),但性能如何?
1.其他人?

vsmadaxz

vsmadaxz1#

要获取第一个视频流的帧,请执行以下操作:

container = av.open("My_Super_Video.mp4")
total_frames = container.streams.video[0].frames
kpbwa7wx

kpbwa7wx2#

你可以用Stream.frames属性得到流中的帧数。
图片来源:www.example.comhttp://docs.mikeboers.com/pyav/develop/api/stream.html#av.stream.Stream

qyzbxkaa

qyzbxkaa3#

老问题,但只回答了一部分。让我来回答第二个问题。
问题1:是否可以通过PyAV获得帧数?如果可以,如何获得?

import av

with av.open("My_Super_Video.mp4") as container:
    total_frames = container.streams.video[0].frames

问题2:在这种情况下,我会考虑使用另一个库来逐帧加载和处理视频。哪个库可以让我以最快的速度完成上述操作。我知道以下几个库,但不知道它们的比较结果如何:[...]

ImageIO timings:  0.497
PyAV timings:     0.908
MoviePy timings:  0.766
OpenCV timings:   0.766
OpenCV timings:   0.569 (no conversion to RGB)
    • ImageIO速度最快**;很简单。OpenCV很接近(慢14%),但前提是你能在BGR中进行处理。如果你必须在RGB中工作,那么转换成本会很高(慢54%)。🥵).

也就是说,它高度依赖于工作负载,您应该始终使用特定的设置进行基准测试。实际上,与您处理每帧所花费的时间相比,差异通常可以忽略不计。
下面是一些基准测试代码,供感兴趣的读者参考:

import cv2
import av
import imageio.v3 as iio
from moviepy.editor import VideoFileClip
from PIL import Image
from timeit import Timer

# create a test video (roughly 11 sec and sane encoding)
frames = iio.imread("imageio:cockatoo.mp4", plugin="pyav")
iio.imwrite("test_video.mp4", frames, plugin="pyav", codec="h264")

def iio_read():
    total_frames = iio.improps("test_video.mp4", plugin="pyav").shape[0]
    for idx, frame in enumerate(iio.imiter("test_video.mp4", plugin="pyav")):
        foo = Image.fromarray(frame)

        # Note: I will not print in the benchmark. This will skew the result
        # print("Frame: %d/%d ..." % (idx, total_frames))

def av_read():
    with av.open("test_video.mp4") as container:
        total_frames = container.streams.video[0].frames
        for frame in container.decode(video=0):
            foo = frame.to_image()

def moviepy_read():
    # Can not read frame_count
    for frame in VideoFileClip("test_video.mp4").iter_frames():
        foo = Image.fromarray(frame)

def cv2_read():
    cap = cv2.VideoCapture("test_video.mp4")
    
    total_frames = cap.get(cv2.CAP_PROP_FRAME_COUNT)
    success, frame = cap.read()
    idx = 0
    while success:
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        foo = Image.fromarray(frame)
        success, frame = cap.read()
        idx += 1

def cv2_read2():
    cap = cv2.VideoCapture("test_video.mp4")
    
    total_frames = cap.get(cv2.CAP_PROP_FRAME_COUNT)
    success, frame = cap.read()
    idx = 0
    while success:
        foo = Image.fromarray(frame)
        success, frame = cap.read()
        idx += 1

repeats = 10
time_moviepy = min(Timer("moviepy_read()", globals=globals()).repeat(repeats, number=1))
time_cv2 = min(Timer("cv2_read()", globals=globals()).repeat(repeats, number=1))
time_cv2_no_convert = min(Timer("cv2_read2()", globals=globals()).repeat(repeats, number=1))
time_iio = min(Timer("iio_read()", globals=globals()).repeat(repeats, number=1))
time_av = min(Timer("av_read()", globals=globals()).repeat(repeats, number=1))

print(
f"""
ImageIO timings:  {time_iio:.3f}
PyAV timings:     {time_av:.3f}
MoviePy timings:  {time_moviepy:.3f}
OpenCV timings:   {time_cv2:.3f}
OpenCV timings:   {time_cv2_no_convert:.3f} (no conversion to RGB)
"""
)

软件包版本:

av==10.0.0
moviepy==1.0.3
Pillow==9.4.0
opencv-python==4.7.0.68
imageio==2.25.0

相关问题