J'ai un grand tableau numpy que je dois manipuler afin que chaque élément soit changé en 1 ou 0 si une condition est remplie (sera utilisé comme masque de pixel plus tard). Il y a environ 8 millions d'éléments dans le tableau et ma méthode actuelle prend trop de temps pour le pipeline de réduction:
for (y,x), value in numpy.ndenumerate(mask_data):
if mask_data[y,x]<3: #Good Pixel
mask_data[y,x]=1
Elif mask_data[y,x]>3: #Bad Pixel
mask_data[y,x]=0
Existe-t-il une fonction numpy qui accélérerait cela?
>>> import numpy as np
>>> a = np.random.randint(0, 5, size=(5, 4))
>>> a
array([[4, 2, 1, 1],
[3, 0, 1, 2],
[2, 0, 1, 1],
[4, 0, 2, 3],
[0, 0, 0, 2]])
>>> b = a < 3
>>> b
array([[False, True, True, True],
[False, True, True, True],
[ True, True, True, True],
[False, True, True, False],
[ True, True, True, True]], dtype=bool)
>>>
>>> c = b.astype(int)
>>> c
array([[0, 1, 1, 1],
[0, 1, 1, 1],
[1, 1, 1, 1],
[0, 1, 1, 0],
[1, 1, 1, 1]])
Vous pouvez raccourcir ceci avec:
>>> c = (a < 3).astype(int)
>>> a = np.random.randint(0, 5, size=(5, 4))
>>> a
array([[0, 3, 3, 2],
[4, 1, 1, 2],
[3, 4, 2, 4],
[2, 4, 3, 0],
[1, 2, 3, 4]])
>>>
>>> a[a > 3] = -101
>>> a
array([[ 0, 3, 3, 2],
[-101, 1, 1, 2],
[ 3, -101, 2, -101],
[ 2, -101, 3, 0],
[ 1, 2, 3, -101]])
>>>
Voir, par exemple, Indexation avec des tableaux booléens .
Le moyen le plus rapide (et le plus flexible) consiste à utiliser np.where , qui choisit entre deux tableaux en fonction d'un masque (tableau de valeurs true et false):
import numpy as np
a = np.random.randint(0, 5, size=(5, 4))
b = np.where(a<3,0,1)
print('a:',a)
print()
print('b:',b)
qui produira:
a: [[1 4 0 1]
[1 3 2 4]
[1 0 2 1]
[3 1 0 0]
[1 4 0 1]]
b: [[0 1 0 0]
[0 1 0 1]
[0 0 0 0]
[1 0 0 0]
[0 1 0 0]]
Vous pouvez créer votre tableau de masques en une étape comme celle-ci.
mask_data = input_mask_data < 3
Cela crée un tableau booléen qui peut ensuite être utilisé comme masque de pixels. Notez que nous n’avons pas changé le tableau en entrée (comme dans votre code) mais que nous avons créé un nouveau tableau pour contenir les données de masque. Je vous recommande de le faire de cette façon.
>>> input_mask_data = np.random.randint(0, 5, (3, 4))
>>> input_mask_data
array([[1, 3, 4, 0],
[4, 1, 2, 2],
[1, 2, 3, 0]])
>>> mask_data = input_mask_data < 3
>>> mask_data
array([[ True, False, False, True],
[False, True, True, True],
[ True, True, False, True]], dtype=bool)
>>>
Je ne suis pas sûr d'avoir compris votre question, mais si vous écrivez:
mask_data[:3, :3] = 1
mask_data[3:, 3:] = 0
Ainsi, toutes les valeurs de données de masque dont les index x et y sont inférieurs à 3 seront égales à 1 et toutes les valeurs restantes seront égales à 0.