2009-12-11 1 views
14

Ich finde die astype() - Methode von numpy Arrays nicht sehr effizient. Ich habe ein Array mit 3 Millionen Uint8 Punkt. Die Multiplikation mit einer 3x3-Matrix dauert 2 Sekunden, aber die Umwandlung des Ergebnisses von uint16 in uint8 dauert eine weitere Sekunde.numpy: Wie man einen Array-Typ schnell konvertiert

Genauer gesagt:

print time.clock() 
    imgarray = np.dot(imgarray, M)/255 
    print time.clock() 
    imgarray = imgarray.clip(0, 255) 
    print time.clock() 
    imgarray = imgarray.astype('B') 
    print time.clock() 

Skalarprodukt und Skalierung dauert 2 sec
Clipping dauert 200 ms Typumwandlung 1 sec

Gegeben von den anderen Operationen unternommen, um die Zeit in Anspruch nimmt, würde ich astype erwarten schneller sein. Gibt es eine schnellere Möglichkeit, Typumwandlung zu tun, oder liege ich falsch, wenn die Typumwandlung nicht so schwer sein sollte?

Edit: das Ziel ist es, die letzten 8 Bit-Array in eine Datei

+0

Warum Sie uint16 und wieder zurück zu gehen brauchen? Ist es möglich, 'M' als Uint8-Matrix zu haben, dann brauchen Sie die Konvertierung nicht. – u0b34a0f6ae

+0

Das Ergebnis des dot-Produkts wird den uint8-Bereich übersteigen. Ich habe ursprünglich eine Float-M-Matrix verwendet, und wenn ich zu Integer gehe, würde das eine Verbesserung bedeuten, aber das stimmt nicht. – shodanex

+0

Es dauert wahrscheinlich die ganze Zeit, auf alle Speicherplätze zuzugreifen. Klingt schwer zu reparieren. –

Antwort

24

speichern Wenn Sie imgarray = imgarray.astype('B') verwenden, können Sie eine Kopie des Arrays zu erhalten, gegossen in den angegebenen Typ. Dies erfordert zusätzliche Speicherzuweisung, auch wenn Sie sofort imgarray auf das neu zugewiesene Array zeigen.

Wenn Sie imgarray.view('uint8') verwenden, erhalten Sie eine Ansicht des Arrays. Dies verwendet die gleichen Daten, außer dass es als uint8 anstelle von imgarray.dtype interpretiert wird. (np.dot gibt eine uint32 Array, so dass nach den np.dot, imgarray ist vom Typ uint32.)

Das Problem bei view verwendet, ist jedoch, dass eine 32-Bit-Ganzzahl als 4 8-Bit-Integer betrachtet wird, und wir kümmere dich nur um den Wert in den letzten 8 Bits. Also müssen wir zu jeder 4. 8-Bit-Ganzzahl springen. Wir können tun, dass mit Slicing:

imgarray.view('uint8')[:,::4]

IPython des% timeit Befehl zeigt eine signifikante Geschwindigkeit, Dinge zu tun up ist auf diese Weise:

In [37]: %timeit imgarray2 = imgarray.astype('B') 
10000 loops, best of 3: 107 us per loop 

In [39]: %timeit imgarray3 = imgarray.view('B')[:,::4] 
100000 loops, best of 3: 3.64 us per loop 
+1

Kann ich diese Ansicht in eine Datei speichern – shodanex

+0

@shodanex: Ja, Sie könnten np.save() verwenden. Siehe http://docs.scipy.org/doc/numpy-1.3.x/reference/generated/numpy.save.html – unutbu

+0

@shodanex: Für andere Formatoptionen, siehe auch http://docs.scipy.org/doc /numpy-1.3.x/reference/routines.io.html – unutbu