Reemplace todos los elementos de la matriz NumPy que sean mayores que algún valor
Tengo una matriz NumPy 2D. ¿Cómo reemplazo todos los valores mayores que un umbral T = 255
con un valor x = 255
? Un método lento basado en bucle for sería:
# arr = arr.copy() # Optionally, do not modify original arr.
for i in range(arr.shape[0]):
for j in range(arr.shape[1]):
if arr[i, j] > 255:
arr[i, j] = x
Creo que la forma más rápida y concisa de hacer esto es utilizar la indexación Fancy incorporada de NumPy. Si tiene un ndarray
nombre arr
, puede reemplazar todos los elementos >255
con un valor x
de la siguiente manera:
arr[arr > 255] = x
Ejecuté esto en mi máquina con una matriz aleatoria de 500 x 500, reemplazando todos los valores >0,5 por 5, y tardó un promedio de 7,59 ms.
In [1]: import numpy as np
In [2]: A = np.random.rand(500, 500)
In [3]: timeit A[A > 0.5] = 5
100 loops, best of 3: 7.59 ms per loop
Si desea una nueva matriz result
que contenga una copia de arr
siempre arr < 255
y 255
en caso contrario:
result = np.minimum(arr, 255)
De manera más general, para un límite inferior y/o superior:
result = np.clip(arr, 0, 255)
Si solo desea acceder a los valores superiores a 255, o algo más complicado, la respuesta de @mtitan8 es más general, pero np.clip
y np.minimum
(o np.maximum
) son mejores y mucho más rápidos para su caso:
In [292]: timeit np.minimum(a, 255)
100000 loops, best of 3: 19.6 µs per loop
In [293]: %%timeit
.....: c = np.copy(a)
.....: c[a>255] = 255
.....:
10000 loops, best of 3: 86.6 µs per loop
Si desea hacerlo in situ (es decir, modificar arr
en lugar de crear result
), puede utilizar el out
parámetro de np.minimum
:
np.minimum(arr, 255, out=arr)
o
np.clip(arr, 0, 255, arr)
(el out=
nombre es opcional ya que los argumentos están en el mismo orden que la definición de la función).
Para la modificación in situ, la indexación booleana se acelera mucho (sin tener que hacer y luego modificar la copia por separado), pero aún no es tan rápida como minimum
:
In [328]: %%timeit
.....: a = np.random.randint(0, 300, (100,100))
.....: np.minimum(a, 255, a)
.....:
100000 loops, best of 3: 303 µs per loop
In [329]: %%timeit
.....: a = np.random.randint(0, 300, (100,100))
.....: a[a>255] = 255
.....:
100000 loops, best of 3: 356 µs per loop
A modo de comparación, si quisiera restringir sus valores tanto con un mínimo como con un máximo, clip
tendría que hacerlo dos veces, con algo como
np.minimum(a, 255, a)
np.maximum(a, 0, a)
o,
a[a>255] = 255
a[a<0] = 0
Creo que puedes lograr esto más rápido usando la where
función:
Por ejemplo, buscar elementos mayores que 0,2 en una matriz numerosa y reemplazarlos con 0:
import numpy as np
nums = np.random.rand(4,3)
print np.where(nums > 0.2, 0, nums)