Tengo una gran matriz numpy que necesito manipular para que cada elemento 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 toma demasiado tiempo para la tubería de reducción:
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
¿Hay alguna función que acelere esto?
python
arrays
numpy
conditional
ChrisFro
fuente
fuente
mask_data[y,x]==3
?if mask_data[y,x]>=3:
Respuestas:
>>> 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]])
Puede acortar esto con:
>>> c = (a < 3).astype(int)
fuente
>>> 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]]) >>>
Ver, por ejemplo, Indexación con matrices booleanas .
fuente
a[a > 3] = -101+a[a > 3]
.a[a > 3] = -101+a[a > 3]
lugar dea[a > 3] += -101
lo más probable es que se enfrente a una pérdida de memoria.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]]
fuente
a[a<3] = 0
Puede crear su matriz de máscaras en un paso como este
mask_data = input_mask_data < 3
Esto crea una matriz booleana que luego se puede usar como 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) >>>
fuente
.astype(int)
o*1
, pero una matriz deTrue
yFalse
es tan buena como es.No estoy seguro de haber entendido su pregunta, pero si escribe:
mask_data[:3, :3] = 1 mask_data[3:, 3:] = 0
Esto hará que todos los valores de los datos de máscara cuyos índices xey sean menores que 3 sean iguales a 1 y todos los demás sean iguales a 0
fuente