在2022年,你也可以选择使用ImageIO来做到这一点,恕我直言,这是更加轻松和易读的。
import imageio.v3 as iio
for idx, frame in enumerate(iio.imiter("imageio:cockatoo.mp4")):
iio.imwrite(f"extracted_images/frame{idx:03d}.jpg", frame)
旁注1:"imageio:cockatoo.mp4"是imageio为测试和演示目的提供的标准图像。您可以简单地将其替换为“path/to/your/video.mp4”。
旁注2:你必须安装一个ImageIO的可选依赖项来读取视频数据,这可以通过pip install ImageIO -ffmpeg或pip install av来完成。
你可以对照OpenCV计算时间,你会发现,在这方面,OpenCV也没有太多好处:
Read-Only Timings
=================
OpenCV: 0.453
imageio_ffmpeg: 0.765
imageio_pyav: 0.272
Read + Write Timings
====================
OpenCV: 3.237
imageio_ffmpeg: 1.597
imageio_pyav: 1.506
默认情况下,OpenCV和ImageIO+av读取时的速度差不多。两者都在底层直接绑定到FFmpeg库,所以这并不奇怪。然而,ImageIO允许您调整FFmpeg的默认线程模型(thread_type="FRAME"),这在批量读取时要快得多。
更重要的是,ImageIO在编写JPEG方面比OpenCV快得多。这是因为pillow比OpenCV快,ImageIO利用了这一点。在这种情况下,写图像占据了运行时的主导地位,因此使用ImageIO而不是OpenCV时,整体性能提高了2倍。
下面是代码供参考:
import imageio.v3 as iio
import cv2
import timeit
from pathlib import Path
# create a common local file for benchmarking
video_file = "shared_video.mp4"
if not Path(video_file).exists():
frames = iio.imread("imageio:cockatoo.mp4")
meta = iio.immeta("imageio:cockatoo.mp4", exclude_applied=False)
iio.imwrite(video_file, frames, fps=meta["fps"])
repeats = 10
def read_cv2():
vidcap = cv2.VideoCapture(video_file)
success, image = vidcap.read()
idx = 0
while success:
cv2.imwrite(f"extracted_images/frame{idx:03d}.jpg", image)
success, image = vidcap.read()
idx += 1
def read_imageio_ffmpeg():
for idx, frame in enumerate(iio.imiter(video_file, plugin="FFMPEG")):
iio.imwrite(f"extracted_images/frame{idx:03d}.jpg", frame)
def read_imageio_pyav():
for idx, frame in enumerate(
iio.imiter(video_file, plugin="pyav", format="rgb24", thread_type="FRAME")
):
iio.imwrite(f"extracted_images/frame{idx:03d}.jpg", frame)
time_cv2 = (
timeit.timeit("read_cv2()", setup="from __main__ import read_cv2", number=repeats)
/ repeats
)
time_imageio_ffmpeg = (
timeit.timeit(
"read_imageio_ffmpeg()",
setup="from __main__ import read_imageio_ffmpeg",
number=repeats,
)
/ repeats
)
time_imageio_pyav = (
timeit.timeit(
"read_imageio_pyav()",
setup="from __main__ import read_imageio_pyav",
number=repeats,
)
/ repeats
)
print(
f"""
Timings
=======
OpenCV: {time_cv2:<3.3f}
imageio_ffmpeg: {time_imageio_ffmpeg:<3.3f}
imageio_pyav: {time_imageio_pyav:<3.3f}
"""
)