2014-05-12 11 views
5

Jaki byłby najszybszy/efektywny pod względem pamięci sposób na uzyskanie średniej z wielu ramek 16-bitowego obrazu TIFF w postaci tablicy numpy?Uśrednianie na wielostronicowych stronach TIFF w Pythonie

Do tej pory podałem kod podany poniżej. Ku mojemu zaskoczeniu metoda 2 była szybsza niż metoda1.

Ale dla profilowania nigdy nie zakładaj, przetestuj to! Tak więc chcę przetestować więcej. Warto spróbować Wand? Nie uwzględniłem tutaj, ponieważ po zainstalowaniu ImageMagick-6.8.9-Q16 i MAGICK_HOME env var nadal nie importuje ... Dowolna inna biblioteka dla tiff wielostronicowych w Pythonie? GDAL może trochę za dużo na to.

(edycja) Dołączyłem libtiff. Nadal metoda2 najszybsza i dość wydajna pod względem pamięci.

from time import time 

#import cv2 ## no multi page tiff support 
import numpy as np 
from PIL import Image 
#from scipy.misc import imread ## no multi page tiff support 
import tifffile # http://www.lfd.uci.edu/~gohlke/code/tifffile.py.html 
from libtiff import TIFF # https://code.google.com/p/pylibtiff/ 

fp = r"path/2/1000frames-timelapse-image.tif" 

def method1(fp): 
    ''' 
    using tifffile.py by Christoph (Version: 2014.02.05) 
    (http://www.lfd.uci.edu/~gohlke/code/tifffile.py.html) 
    ''' 
    with tifffile.TIFFfile(fp) as imfile: 
     return imfile.asarray().mean(axis=0) 


def method2(fp): 
    'primitive peak memory friendly way with tifffile.py' 
    with tifffile.TIFFfile(fp) as imfile: 

     nframe, h, w = imfile.series[0]['shape'] 
     temp = np.zeros((h,w), dtype=np.float64) 

     for n in range(nframe): 
      curframe = imfile.asarray(n) 
      temp += curframe 

     return (temp/nframe) 


def method3(fp): 
    ' like method2 but using pillow 2.3.0 ' 
    im = Image.open(fp) 

    w, h = im.size 
    temp = np.zeros((h,w), dtype=np.float64) 

    n = 0 
    while True: 
     curframe = np.array(im.getdata()).reshape(h,w) 
     temp += curframe 
     n += 1 
     try: 
      im.seek(n) 
     except: 
      break 

    return (temp/n) 


def method4(fp): 
    ''' 
    https://code.google.com/p/pylibtiff/ 
    documentaion seems out dated. 
    ''' 

    tif = TIFF.open(fp) 
    header = tif.info() 

    meta = dict() # extracting meta 
    for l in header.splitlines(): 
     if l: 
      if l.find(':')>0: 
       parts = l.split(':') 
       key = parts[0] 
       value = ':'.join(parts[1:]) 
      elif l.find('=')>0: 
       key, value =l.split('=') 
      meta[key] = value  

    nframes = int(meta['frames']) 
    h = int(meta['ImageLength']) 
    w = int(meta['ImageWidth']) 

    temp = np.zeros((h,w), dtype=np.float64) 

    for frame in tif.iter_images(): 
     temp += frame 

    return (temp/nframes) 

t0 = time() 
avgimg1 = method1(fp) 
print time() - t0 
# 1.17-1.33 s 

t0 = time() 
avgimg2 = method2(fp) 
print time() - t0 
# 0.90-1.53 s usually faster than method1 by 20% 

t0 = time() 
avgimg3 = method3(fp) 
print time() - t0 
# 21 s 

t0 = time() 
avgimg4 = method4(fp) 
print time() - t0 
# 1.96 - 2.21 s # may not be accurate. I got warning for every frame with the tiff file I tested. 

np.testing.assert_allclose(avgimg1, avgimg2) 
np.testing.assert_allclose(avgimg1, avgimg3) 
np.testing.assert_allclose(avgimg1, avgimg4) 
+1

[ 'pylibtiff'] (https://code.google.com/p/pylibtiff/) pozwala także iteracyjne na stronach wielostronicowego pliku TIFF, jak będzie [' PIL. ImageSequence'] (http://effbot.org/imagingbook/imagesequence.htm). –

+1

Jeśli naprawdę nie masz wielu klatek i są one bardzo małe, zapętlenie w Pythonie przez ramki nie będzie dużym czynnikiem w twoim czasie pracy. Jak dowiedziałeś się z metody 1, zapisanie wszystkich klatek do pamięci jednocześnie okazało się wolniejsze, nawet jeśli pętla następowała w C. Nie sądzę, że znajdziesz coś działającego znacznie lepiej niż twoja metoda2. – Jaime

+0

Powinienem spróbować pylibtiff. Metoda 2 wydaje się wtedy wystarczająco dobra. ale tego nie byłem tak dobry, aby usłyszeć od innych. Dzięki! – otterb

Odpowiedz

-1

Prosta logika by mnie postawić swoje pieniądze na metodzie 1 lub 3, ponieważ metody 2 i 4 mają for-pętle w nich. For-loops Zawsze czyń kod wolniejszym, jeśli masz więcej danych wejściowych.

pewno tam dla metody 1: czysty, jasny, aby przeczytać ...

być naprawdę pewny, tylko je przetestować powiedziałbym. Jeśli nie masz ochoty na testowanie, wybrałbym metodę pierwszą.

poważaniem,

Powiązane problemy