web-dev-qa-db-fra.com

Remplacer des éléments Numpy si la condition est remplie

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?

48
ChrisFro
>>> 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)
76
Steve Barnes
>>> 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

52
ev-br

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]]
22
Markus Dutschke

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)
>>> 
3
YXD

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.

0
mamalos