如何使用“imageio”在视频中查找帧?

use*_*r42 3 python opencv video-processing python-imageio

我有一个视频,我想从视频中仅提取特定的帧。

目前我所做的是:

index = [1,2,3,4,5,6,7,8]
img_list = []
for i, frame in enumerate(iio.imiter("imageio:cockatoo.mp4")):
    if i in index:
        img_list.append(frame)

img_array = np.asarray(img_list)
Run Code Online (Sandbox Code Playgroud)

有没有办法只“寻找”我想要的帧,就像在 opencv 中完成的那样,如此处所示

Fir*_*ger 6

您可以使用indexkwarg of获取特定帧imread

import imageio.v3 as iio
import numpy as np

index = [1,2,3,4,5,6,7,8]
img_list = []
for idx in index:
    img_list.append(iio.imread("imageio:cockatoo.mp4", index=idx))

img_array = np.stack(img_list)
Run Code Online (Sandbox Code Playgroud)

如果您想要更高的性能,您可以使用pyav作为后端而不是默认的imageio-ffmpeg

import imageio.v3 as iio
import numpy as np

index = [1,2,3,4,5,6,7,8]
img_list = []
for idx in index:
    img_list.append(iio.imread("imageio:cockatoo.mp4", index=idx, plugin="pyav"))

img_array = np.stack(img_list)
Run Code Online (Sandbox Code Playgroud)

计时(每次重复 10 次):

>>> timeit.timeit('[iio.imread("imageio:cockatoo.mp4", index=idx) for idx in index]', setup="from __main__ import index, iio", number=10) 
9.865169799999876
>>> timeit.timeit('[iio.imread("imageio:cockatoo.mp4", index=idx, plugin="pyav") for idx in index]', setup="from __main__ import index, iio", number=10) 
2.250104900000224
Run Code Online (Sandbox Code Playgroud)

ofc 的缺点是每次都需要重新打开文件,您可以避免使用imopen

import imageio.v3 as iio
import numpy as np

index = [1,2,3,4,5,6,7,8]

with iio.imopen("imageio:cockatoo.mp4", "r") as img_file:
    img_list = [img_file.read(index=idx) for idx in index]

img_array = np.stack(img_list)
Run Code Online (Sandbox Code Playgroud)

不幸的是,imopen由于我在编写插件时错过了一个错误,该路线目前不适用于 pyav。但是,既然我现在意识到了这一点,我应该能够在未来几天内编写修复程序:)

编辑:该错误现已修复。您现在可以使用

import imageio.v3 as iio
import numpy as np

index = [1,2,3,4,5,6,7,8]

with iio.imopen("imageio:cockatoo.mp4", "r", plugin="pyav") as img_file:
    img_list = [img_file.read(index=idx) for idx in index]

img_array = np.stack(img_list)
Run Code Online (Sandbox Code Playgroud)