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

Python 从文件夹中的图像序列获取numpy数组,python,numpy,image-processing,keras,python-imaging-library,Python,Numpy,Image Processing,Keras,Python Imaging Library,我有一个文件夹,比如说video1,里面有一堆图像,顺序是frame\u 00.png,frame\u 01.png,… 我想要的是一个4D numpy数组,格式为(帧数,w,h,3) 这就是我所做的,但我认为这是相当缓慢的,有没有更快或更有效的方法来实现同样的事情 folder = "video1/" import os images = sorted(os.listdir(folder)) #["frame_00", "frame_01", "frame_02", ...] from P

我有一个文件夹,比如说
video1
,里面有一堆图像,顺序是
frame\u 00.png,frame\u 01.png,…

我想要的是一个4D numpy数组,格式为
(帧数,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)
关于这个话题,有一个非常详细(甚至有点太多)的例子。与其投票以dup结束这个问题,我将简要介绍一下该主题的主要要点:

  • 最快的常用图像读取功能是
    cv2
    软件包中的
    imread
  • 在中读取图像,然后将其添加到普通Python列表中(正如您已经在做的那样),是读取大量图像的最快方法
  • 但是,考虑到最终要将图像列表转换为图像数组,构建图像数组的所有可能方法几乎都与其他方法一样快
    • 尽管非常有趣的是,如果您采取将图像直接分配给预分配数组的方法,那么实际上分配给哪个索引(即哪个维度)对于获得最佳性能非常重要
因此,基本上,在纯单线程Python中工作时,您将无法获得更快的速度。切换到
cv2.imread
(代替
PIL.Image.open
)可能会让您受益匪浅。

在这个主题上有一个非常详细的说明(甚至可能有点太多)。与其投票以dup结束这个问题,我将简要介绍一下该主题的主要要点:

  • 最快的常用图像读取功能是
    cv2
    软件包中的
    imread
  • 在中读取图像,然后将其添加到普通Python列表中(正如您已经在做的那样),是读取大量图像的最快方法
  • 但是,考虑到最终要将图像列表转换为图像数组,构建图像数组的所有可能方法几乎都与其他方法一样快
    • 尽管非常有趣的是,如果您采取将图像直接分配给预分配数组的方法,那么实际上分配给哪个索引(即哪个维度)对于获得最佳性能非常重要

因此,基本上,在纯单线程Python中工作时,您将无法获得更快的速度。切换到
cv2.imread
(代替
PIL.Image.open
)可能会给你带来好处。

PNG是一种非常慢的格式,因此如果你能使用几乎任何其他格式,你会看到很大的加速

例如,以下是程序的opencv版本,它从命令行参数获取文件名:

#!/usr/bin/python3

import sys
import cv2
import numpy as np

video_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.063s
user    0m5.758s
sys 0m0.839s
所以6秒可以读取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.532s
user    0m1.060s
sys 0m0.843s
1.5秒,因此速度提高了四倍

您可能会通过以下方式获得小的加速:

我明白了:

$ time ./readframes.py sample/*.tif
(100, 2048, 1450, 3)

real    0m1.360s
user    0m1.629s
sys 0m2.153s
还有10%左右


最后,正如其他海报所说,您可以并行加载框架。这对TIFF没有多大帮助,但肯定会提高PNG的速度。

PNG是一种非常慢的格式,因此如果您可以使用几乎任何其他格式,您将看到一个巨大的加速

例如,以下是程序的opencv版本,它从命令行参数获取文件名:

#!/usr/bin/python3

import sys
import cv2
import numpy as np

video_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.063s
user    0m5.758s
sys 0m0.839s
所以6秒可以读取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.532s
user    0m1.060s
sys 0m0.843s
1.5秒,因此速度提高了四倍

您可能会通过以下方式获得小的加速:

我明白了:

$ time ./readframes.py sample/*.tif
(100, 2048, 1450, 3)

real    0m1.360s
user    0m1.629s
sys 0m2.153s
还有10%左右


最后,正如其他海报所说,您可以并行加载框架。这对TIFF没有多大帮助,但肯定会提升PNG。

您可以尝试
scipy.misc.imread
而不是使用
PIL
。否则,我看不到任何明显的加速代码的方法。你也可以尝试并行读取帧。事实上,正如@trailing_whitespace所建议的那样,
imread
比PIL快约15%。我使用scipy.misc.imread代替PIL,当我加载图像时,它的形状如下(50、100、3),并且方向正确。转置图像会给我(100,50,3),这是输入ML模型的正确形状,但图像显示时的方向不再正确。关于如何解决这个问题有什么想法吗?@trailing_空格
scipy.misc.imread
cv2.imread
之间有什么区别吗(比如,它们是否共享一个实现)?这表明
cv2.imread
是可用的最快的图像读取功能。您可以尝试
scipy.misc.imread
而不是使用
PIL
。否则,我看不到任何明显的加速代码的方法。你也可以尝试并行读取帧。事实上,正如@trailing_whitespace所建议的那样,
imread
比PIL快约15%。我使用scipy.misc.imread代替PIL,当我加载图像时,它的形状如下(50、100、3),并且方向正确。转置图像会给我(100,50,3),这是输入ML模型的正确形状,但图像显示时的方向不再正确。关于如何解决这个问题有什么想法吗?@trailing_空格
scipy.misc.imread
cv2.imread
之间有什么区别吗(比如,它们是否共享一个实现)?这表明
cv2.imread
是可用的最快的图像读取功能。