2009-12-11 12 views
14

Uważam, że metoda astype() z numpy tablic nie jest zbyt wydajna. Mam tablicę zawierającą 1 milion punktów Uint8. Mnożenie go przez matrycę 3x3 zajmuje 2 sekundy, ale konwersja wyniku z uint16 na uint8 trwa jeszcze jedną sekundę.numpy: Jak szybko przekonwertować typ tablicy

Dokładniej:

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() 

kropka produkt i skalowanie trwa 2 sek
strzyżenie trwa 200 ms typ konwersji trwa 1 sek

Biorąc pod uwagę czas potrzebny przez innych operacji, ja spodziewałbym astype być szybszym. Czy istnieje szybszy sposób na konwersję typu, czy też się mylę, gdy przeliczanie wartości tego typu nie powinno być tak trudne?

Edit: celem jest, aby zapisać ostateczną 8 bitową tablicę do pliku

+0

Dlaczego trzeba iść do uint16 iz powrotem? Czy możliwe jest posiadanie 'M' jako matrycy uint8, wtedy nie potrzebujesz konwersji. – u0b34a0f6ae

+0

wynik produktu kropki przekroczy zakres uint8. Pierwotnie używałem macierzy float M, a myślenie o liczbie całkowitej dałoby mi trochę poprawy, ale to nie jest prawda. – shodanex

+0

Prawdopodobnie trwa cały ten czas, ma dostęp do wszystkich lokalizacji pamięci. Trudno to naprawić. –

Odpowiedz

24

Podczas korzystania imgarray = imgarray.astype('B'), można uzyskać kopię tablicy, oddanych do określonego typu. Wymaga to dodatkowej alokacji pamięci, nawet jeśli natychmiast odwrócisz imgarray, wskazując na nowo przydzieloną tablicę.

Jeśli użyjesz imgarray.view('uint8'), otrzymasz widok tablicy. Używa tych samych danych, z wyjątkiem tego, że jest interpretowany jako uint8 zamiast imgarray.dtype. (np.dot zwraca uint32 tablicę, więc po np.dot, imgarray jest typu uint32).

Problem z wykorzystaniem view jest jednak to, że 32-bitowy zostaje postrzegany jako 4 8-bitowych liczb całkowitych, i dba tylko o wartość w ostatnich 8 bitach. Musimy więc przejść do każdej czwartej 8-bitowej liczby całkowitej. Możemy to zrobić z krojenia:

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

komenda% timeit ipython pokazuje istnieje znaczne przyspieszenie robienia rzeczy w ten sposób:

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

Czy mogę zapisać ten widok do pliku – shodanex

+0

@shodanex: Tak, możesz użyć np.save(). Zobacz http://docs.scipy.org/doc/numpy-1.3.x/reference/generated/numpy.save.html – unutbu

+0

@shodanex: Aby zapoznać się z innymi opcjami formatu, zobacz również http://docs.scipy.org/doc /numpy-1.3.x/reference/routines.io.html – unutbu