从文件夹中的图像序列中获取一个 numpy 数组

我有一个文件夹,video1按顺序说一堆图像frame_00.png, frame_01.png, ...


我想要的是格式的 4D numpy 数组 (number of frames, w, h, 3)


这就是我所做的,但我认为它很慢,有没有更快或更有效的方法来实现同样的目标?


folder = "video1/"


import os

images = sorted(os.listdir(folder)) #["frame_00", "frame_01", "frame_02", ...]


from PIL import Image 

import numpy as np 


video_array = []

for image in images:

    im = Image.open(folder + image)

    video_array.append(np.asarray(im)) #.transpose(1, 0, 2))


video_array = np.array(video_array)

print(video_array.shape)

#(75, 50, 100, 3)


白板的微信
浏览 183回答 2
2回答

Smart猫小萌

我将简要介绍该线程的主要要点:最快的常用图像读取功能imread来自cv2包。读取图像然后将它们添加到一个普通的 Python 列表中(正如您已经在做的那样)是读取大量图像的最快方法。然而,鉴于您最终将图像列表转换为图像数组,构建图像数组的每种可能方法几乎与任何其他方法一样快尽管有趣的是,如果您采用直接将图像分配给预分配数组的方法,实际上分配给哪个索引(即哪个维度)对于获得最佳性能很重要。所以基本上,在纯单线程 Python 中工作时,您将无法获得更快的速度。您可能会从切换到cv2.imread(代替PIL.Image.open)获得提升。

慕神8447489

PNG 是一种非常慢的格式,因此如果您几乎可以使用其他任何格式,您将看到明显的加速。例如,这是您的程序的 opencv 版本,它从命令行参数获取文件名:#!/usr/bin/python3import sysimport cv2import numpy as npvideo_array = []for filename in sys.argv[1:]:    im = cv2.imread(filename)    video_array.append(np.asarray(im)) video_array = np.array(video_array)print(video_array.shape)我可以像这样运行它:$ mkdir sample$ for i in {1..100}; do cp ~/pics/k2.png sample/$i.png; done$ time ./readframes.py sample/*.png(100, 2048, 1450, 3)real    0m6.063suser    0m5.758ssys 0m0.839s所以 6s 读取 100 张 PNG 图像。如果我尝试使用 TIFF:$ for i in {1..100}; do cp ~/pics/k2.tif sample/$i.tif; done$ time ./readframes.py sample/*.tif(100, 2048, 1450, 3)real    0m1.532suser    0m1.060ssys 0m0.843s1.5 秒,所以快了四倍。您可能会通过pyvips获得小幅加速:#!/usr/bin/python3import sysimport pyvipsimport numpy as np# map vips formats to np dtypesformat_to_dtype = {    'uchar': np.uint8,    'char': np.int8,    'ushort': np.uint16,    'short': np.int16,    'uint': np.uint32,    'int': np.int32,    'float': np.float32,    'double': np.float64,    'complex': np.complex64,    'dpcomplex': np.complex128,}   # vips image to numpy arraydef vips2numpy(vi):    return np.ndarray(buffer=vi.write_to_memory(),                      dtype=format_to_dtype[vi.format],                      shape=[vi.height, vi.width, vi.bands])video_array = []for filename in sys.argv[1:]:    vi = pyvips.Image.new_from_file(filename, access='sequential')    video_array.append(vips2numpy(vi)) video_array = np.array(video_array)print(video_array.shape)我懂了:$ time ./readframes.py sample/*.tif(100, 2048, 1450, 3)real    0m1.360suser    0m1.629ssys 0m2.153s还有10%左右。最后,正如其他海报所说,您可以并行加载帧。这不会对 TIFF 有多大帮助,但它肯定会提升 PNG。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python