2013-01-21 9 views
17

Ich habe ein Bild in numpy mit einigen Pixeln in meinem resultierenden Array gelesen.Gibt es eine bequeme Möglichkeit, eine Nachschlagetabelle auf ein großes Array in numpy anzuwenden?

ich eine Lookup-Tabelle mit 256 Werten berechnet. Jetzt möchte ich folgendes tun:

for i in image.rows: 
    for j in image.cols: 
     mapped_image[i,j] = lut[image[i,j]] 

Ja, das ist im Grunde, was ein lut tut.
Nur Problem ist: Ich möchte es effizient zu tun und rufen Sie diese Schleife in Python wird mich warten, für einige Sekunden, bis es zu beenden.

ich von numpy.vectorize() wissen, es ist einfach eine Komfortfunktion, die den gleichen Python-Code aufruft.

Antwort

25

Sie können nur image indizieren in lut verwenden, wenn lut ist 1D.
Hier ist ein Starter auf Indizierung in NumPy:
http://www.scipy.org/Tentative_NumPy_Tutorial#head-864862d3f2bb4c32f04260fac61eb4ef34788c4c

In [54]: lut = np.arange(10) * 10 

In [55]: img = np.random.randint(0,9,size=(3,3)) 

In [56]: lut 
Out[56]: array([ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90]) 

In [57]: img 
Out[57]: 
array([[2, 2, 4], 
     [1, 3, 0], 
     [4, 3, 1]]) 

In [58]: lut[img] 
Out[58]: 
array([[20, 20, 40], 
     [10, 30, 0], 
     [40, 30, 10]]) 

Geist auch die Indizierung beginnt bei 0

+3

* face-Schreibtisch * Das ist so einfach, ich könnte schreien. Ich habe die ganze Zeit in die andere Richtung gedacht und es wird nicht funktionieren. Aber numpy macht Dinge elementweise, also ist das die offensichtliche Lösung. Vielleicht war ich gestern zu müde. ;) – Profpatsch

+0

Eigentlich scheint es auch für mehrdimensionale LUTS zu funktionieren, zumindest mit numply 1.9.2 – Claude

+0

Sehr elegante Lösung, danke! – gcucurull

13

in der richtigen TheodrosZelleke Antwort, aber ich wollte nur ein wenig undokumentierte Weisheit, um es hinzuzufügen. Numpy stellt eine Funktion zur Verfügung, np.take, die laut der Dokumentation "macht das gleiche Ding wie Phantasie Indizierung."

Naja, fast, aber das gleiche nicht ganz:

>>> import numpy as np 
>>> lut = np.arange(256) 
>>> image = np.random.randint(256, size=(5000, 5000)) 
>>> np.all(lut[image] == np.take(lut, image)) 
True 
>>> import timeit 
>>> timeit.timeit('lut[image]', 
...    'from __main__ import lut, image', number=10) 
4.369504285407089 
>>> timeit.timeit('np.take(lut, image)', 
...    'from __main__ import np, lut, image', number=10) 
1.3678052776554637 

np.take über 3x schneller ist! Meiner Erfahrung nach ermöglicht die Verwendung von 3D-Luts zum Konvertieren von Bildern von RGB in andere Farbräume das Hinzufügen einer Logik zum Konvertieren des 3D-Look-Ups in ein 1D-Flat-Up-Look-Up, um eine X10-Beschleunigung zu erzielen.

+1

Oh, wow, ich habe eine Weile tiefer in 'np.put' geschaut, weil ich dachte, das könnte funktionieren. Wenn nicht, habe ich die anderen Funktionen nicht überprüft. -.- – Profpatsch

+6

Diese Timings sind jetzt zwei Jahre alt: neuere Versionen von NumPy, beginnend mit 1.9, haben eine viel bessere fancy Indexing-Maschinerie, die jetzt vergleichbar ist so schnell wie mit 'take'. – Jaime

Verwandte Themen