Reemplazo de elementos Numpy si se cumple la condición

Tengo una gran variedad de números que necesito manipular para que cada elemento se cambie a 1 o 0 si se cumple una condición (se usará como una máscara de píxeles más adelante). Hay alrededor de 8 millones de elementos en la matriz y mi método actual lleva demasiado tiempo para la reducción:

for (y,x), value in numpy.ndenumerate(mask_data): if mask_data[y,x]3: #Bad Pixel mask_data[y,x]=0 

¿Hay una función numpy que aceleraría esto?

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

Puedes acortar esto con:

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

Véase, por ejemplo, la indexación con matrices booleanas .

La forma más rápida (y más flexible) es usar np.where , que elige entre dos matrices según una máscara (matriz de valores verdaderos y falsos):

 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) 

que producirá:

 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]] 

Puede crear su matriz de máscara en un paso como este

 mask_data = input_mask_data < 3 

Esto crea una matriz booleana que luego se puede utilizar como una máscara de píxeles. Tenga en cuenta que no hemos cambiado la matriz de entrada (como en su código), pero hemos creado una nueva matriz para contener los datos de la máscara. Recomendaría hacerlo de esta manera.

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

No estoy seguro de haber entendido tu pregunta, pero si escribes:

 mask_data[:3, :3] = 1 mask_data[3:, 3:] = 0 

Esto hará que todos los valores de los datos de máscara cuyos índices x e y sean menores que 3 sean iguales a 1 y todos los demás sean iguales a 0