2014-10-20 3 views
1

В последнее время я играю с фотографией во времени, используя медианную укладку изображений на группу изображений или извлеченные видеокадры. Я создал небольшой скрипт, который хорошо работает с относительными нескольких изображений:Управление памятью Python со срединным укладчиком изображений

from PIL import Image 
import os 
import numpy as np 
#Create a list of the images' data 
imglist = [] 
for fname in os.listdir("input\\"): 
    imglist.append(np.array(Image.open("input\\"+fname))) 
#Find the median of all image data in the stack, save it 
median = np.uint8(np.median(imglist, axis=0)) 
Image.fromarray(median).save("median.png","PNG") 

Очевидная проблема здесь состоит в том, что, если загружаются слишком много изображений в памяти сразу, они заполняют мой скудный 8 Гб оперативной памяти. Я пробовал подходы, которые включают разделение данных изображения на куски и вычисление медианы одного куска за раз и разделение данных изображения по цветному каналу, но когда есть много изображений для обработки, количество вызовов файлов, которые требуется для сохранения данные на образ диска по изображению приводят к массовому замедлению.

Мне интересно, можно ли каким-либо образом использовать весовую схему для вычисления медианы для нескольких изображений за раз, затем повторять результаты или использовать трюк, например виртуальную память, файлы с отображением памяти или что-то еще иначе устранить это чрезмерное использование памяти. Есть идеи?

+0

Престола [ этот ответ] (http://stackoverflow.com/a/638050/1142167). –

ответ

0

Как насчет использования http://www.h5py.org/, интерфейс HDF5 для Python? HDF5 - это формат данных, предназначенный для обработки массивных наборов данных с сеткой, а с h5py вы можете манипулировать этими данными с помощью NumPy. NetCDF тоже хорош, и интегрирует HDF5.

Какое разрешение изображения и сколько из них есть?

Вот решение вашей проблемы, которая использует netCDF4 нарезать из (400,400) областей коллекции изображений, добавляет их в файл NetCDF и занимает срединное в конце:

import glob 
from netCDF4 import Dataset 
import numpy as np 
from PIL import Image 

WIDTH = 800 
HEIGHT = 450 

root = Dataset('test.nc', 'w') 

root.createDimension('x', WIDTH) 
root.createDimension('y', HEIGHT) 
root.createDimension('channels', 3) 
t = root.createDimension('t', None) 

img = root.createVariable('image', 'u1', ('t','y','x','channels')) 

images = glob.glob('images/*') 

for i,fname in enumerate(images): 
    im = Image.open(fname) 
    im_array = np.asarray(im) 
    img[i] = im_array 

median = np.median(img, axis=0) 
im = Image.fromarray(np.uint8(median)) 
im.save('out.png') 
+0

Я сейчас смотрю часовую регистрацию веб-камеры в Сиднее, Австралия. Запись на отдельные составляющие составляет 54 000 кадров с разрешением 800x450. HDF5 может работать, но я не вижу способа подсчета медианов с ним, хотя многие команды аналогичны numpy. Полагаю, я мог бы просто делать это по пикселям за раз, что может сработать. –

+1

Ознакомьтесь с кодом, который я добавил выше. Я использовал его, чтобы взять медиану большого количества изображений. Файл NetCDF становится большим, но использование ОЗУ остается низким. Интересная техника, мне бы хотелось увидеть результаты, которые вы получили. – velotron