Eu tenho uma grande matriz numpy que preciso manipular para que cada elemento seja alterado para 1 ou 0 se uma condição for atendida (será usada como uma máscara de pixel posteriormente). Existem cerca de 8 milhões de elementos na matriz e meu método atual leva muito tempo para o pipeline de redução:
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 uma função numpy que aceleraria isso?
python
arrays
numpy
conditional
ChrisFro
fonte
fonte
mask_data[y,x]==3
?if mask_data[y,x]>=3:
Respostas:
>>> 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]])
Você pode encurtar isso com:
>>> c = (a < 3).astype(int)
fonte
>>> 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]]) >>>
Veja, por exemplo, Indexação com matrizes booleanas .
fonte
a[a > 3] = -101+a[a > 3]
.a[a > 3] = -101+a[a > 3]
em vez dea[a > 3] += -101
você provavelmente irá vazamento de memória face.A maneira mais rápida (e mais flexível) é usar np.where , que escolhe entre duas matrizes de acordo com uma máscara (matriz de valores verdadeiros e 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 irá produzir:
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]]
fonte
a[a<3] = 0
Você pode criar sua matriz de máscara em uma etapa como esta
mask_data = input_mask_data < 3
Isso cria uma matriz booleana que pode ser usada como uma máscara de pixel. Observe que não alteramos a matriz de entrada (como em seu código), mas criamos uma nova matriz para armazenar os dados da máscara - eu recomendaria fazer dessa forma.
>>> 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) >>>
fonte
.astype(int)
ou*1
, mas um array deTrue
eFalse
é tão bom quanto é.Não tenho certeza se entendi sua pergunta, mas se você escrever:
mask_data[:3, :3] = 1 mask_data[3:, 3:] = 0
Isso fará com que todos os valores dos dados de máscara cujos índices x e y sejam menores que 3 sejam iguais a 1 e todos os restantes sejam iguais a 0
fonte