получить массив из последовательности изображений в папке - PullRequest
0 голосов
/ 08 декабря 2018

У меня есть папка, скажем video1 с кучей изображений в порядке frame_00.png, frame_01.png, ...

Мне нужен 4-мерный массив в формате (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)

Ответы [ 2 ]

0 голосов
/ 10 декабря 2018

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.

0 голосов
/ 08 декабря 2018

Существует более старая SO-нить , в которой много деталей (возможно, даже слишком много) по этой самой теме.Вместо того, чтобы голосовать, чтобы закрыть этот вопрос в качестве дуплика, я кратко опишу основные пункты этого потока:

  • Самая быстрая общедоступная функция чтения изображений - imread из *Пакет 1007 *.
  • Чтение изображений и добавление их в обычный список Python (как вы уже делаете) - это самый быстрый способ чтения большого количества изображений.
  • Однако, учитывая, что вы в конечном итоге преобразуете список изображений в массив изображений, каждый возможный метод создания массива изображений почти такой же быстрый, как и любой другой
    • Хотя, что интересно, если вы возьметеПодход к назначению изображений непосредственно в предварительно выделенный массив, на самом деле имеет значение, какие индексы (то есть, какое измерение) вы назначаете с точки зрения получения оптимальной производительности.

Итак, в основном вымы не сможем работать намного быстрее, работая в чистом однопоточном Python.Вы можете получить повышение от перехода на cv2.imread (вместо PIL.Image.open).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...