2009-12-11 8 views
14

Je trouve la méthode astype() de tableaux chiffrés pas très efficace. J'ai un tableau contenant 3 millions de points Uint8. La multiplier par une matrice 3x3 prend 2 secondes, mais convertir le résultat de uint16 en uint8 prend une seconde.numpy: Comment convertir un type de tableau rapidement

Plus précisément:

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

produit scalaire et mise à l'échelle prend 2 sec
découpage est conversion de type 200 msec prend 1 sec

Compte tenu du temps pris par les autres opérations, je me attends astype être plus rapide. Existe-t-il un moyen plus rapide de faire une conversion de type, ou ai-je tort quand j'imagine que la conversion de type ne devrait pas être si difficile?

Edit: le but est de sauver le tableau final 8 bits dans un fichier

+0

Pourquoi avez-vous besoin d'aller à uint16 et à nouveau? Est-il possible d'avoir M comme une matrice uint8, alors vous n'avez pas besoin de la conversion. – u0b34a0f6ae

+0

le résultat du produit scalaire dépassera la gamme uint8. À l'origine, j'utilisais une matrice float M, et je pensais que aller à l'entier me donnerait une certaine amélioration, mais ce n'est pas vrai. – shodanex

+0

Ce qui prend tout ce temps, probablement, est d'accéder à tous les emplacements de mémoire. Ça a l'air dur à réparer. –

Répondre

24

Lorsque vous utilisez imgarray = imgarray.astype('B'), vous obtenez une copie du tableau, jeté dans le type spécifié. Cela nécessite une allocation de mémoire supplémentaire, même si vous inversez immédiatement imgarray pour pointer vers le tableau nouvellement alloué. Si vous utilisez imgarray.view('uint8'), vous obtenez une vue du tableau. Ceci utilise les mêmes données sauf qu'il est interprété comme uint8 au lieu de imgarray.dtype. (np.dot renvoie un tableau uint32, donc après la np.dot, imgarray est de type uint32.)

Le problème avec l'utilisation view, cependant, est que le nombre entier de 32 bits devient considéré comme 4 entiers de 8 bits, et nous seulement se soucier de la valeur dans les derniers 8 bits. Nous devons donc passer à tous les 4 entiers de 8 bits. Nous pouvons le faire avec le découpage:

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

% commande timeit de IPython montre qu'il ya une vitesse importante en faisant les choses de cette façon:

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

Puis-je enregistrer cette vue dans un fichier – shodanex

+0

@shodanex: Oui, vous pouvez utiliser np.save(). Voir http://docs.scipy.org/doc/numpy-1.3.x/reference/generated/numpy.save.html – unutbu

+0

@shodanex: Pour les autres options de format, voir aussi http://docs.scipy.org/doc /numpy-1.3.x/reference/routines.io.html – unutbu

Questions connexes