简体   繁体   中英

How to seek a frame in video using `imageio`?

I have a video and I would like to extract only specific frames from the video.

Currently what I do is:

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)

Is there a way to 'seek' to only the frames I want like it is done in opencv as shown here ?

You can get specific frames by using the index kwarg 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)

If you want more performance, you could use pyav as backend instead of the default 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)

Timings (for 10 repeats each):

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

This, ofc, has the drawback of re-opening the file each time, which you can avoid using 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)

Unfortunately, the imopen route currently doesn't work for pyav, because of a bug that I missed while writing the plugin. However, since I am aware of it now, I should be able to write a fix in the coming days :)

Edit: The bug now has a PR that will fix the problem. Once merged and released, you can also use

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM