为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

白板的微信 2021-09-11 13:23:08
我有一个文件夹,video1按顺序说一堆图像frame_00.png, frame_01.png, ...我想要的是格式的 4D numpy 数组 (number of frames, w, h, 3)这就是我所做的,但我认为它很慢,有没有更快或更有效的方法来实现同样的目标?folder = "video1/"import osimages = 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)
查看完整描述

2 回答

?
Smart猫小萌

TA贡献1911条经验 获得超7个赞

我将简要介绍该线程的主要要点:

  • 最快的常用图像读取功能imread来自cv2包。

  • 读取图像然后将它们添加到一个普通的 Python 列表中(正如您已经在做的那样)是读取大量图像的最快方法。

  • 然而,鉴于您最终将图像列表转换为图像数组,构建图像数组的每种可能方法几乎与任何其他方法一样快

    • 尽管有趣的是,如果您采用直接将图像分配给预分配数组的方法,实际上分配给哪个索引(即哪个维度)对于获得最佳性能很重要。

所以基本上,在纯单线程 Python 中工作时,您将无法获得更快的速度。您可能会从切换到cv2.imread(代替PIL.Image.open)获得提升。


查看完整回答
反对 回复 2021-09-11
?
慕神8447489

TA贡献1780条经验 获得超1个赞

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

所以 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.532s

user    0m1.060s

sys 0m0.843s

1.5 秒,所以快了四倍。


您可能会通过pyvips获得小幅加速:


#!/usr/bin/python3


import sys

import pyvips

import numpy as np


# map vips formats to np dtypes

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

def 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.360s

user    0m1.629s

sys 0m2.153s

还有10%左右。


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


查看完整回答
反对 回复 2021-09-11
  • 2 回答
  • 0 关注
  • 182 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号