it-swarm.com.de

Ersetzen Sie alle Elemente von Python NumPy Array, die größer als ein bestimmter Wert sind

Ich habe ein 2D-NumPy-Array und möchte alle Werte darin, die größer oder gleich einem Schwellenwert T sind, durch 255.0 ersetzen. Meines Wissens wäre der grundlegendste Weg:

shape = arr.shape
result = np.zeros(shape)
for x in range(0, shape[0]):
    for y in range(0, shape[1]):
        if arr[x, y] >= T:
            result[x, y] = 255
  1. Was ist der prägnanteste und pythonischste Weg, dies zu tun?

  2. Gibt es eine schnellere (möglicherweise weniger präzise und/oder weniger pythonische) Möglichkeit, dies zu tun?

Dies ist Teil einer Subroutine zur Fenster-/Pegeleinstellung für MRT-Untersuchungen des menschlichen Kopfes. Das 2D-Numpy-Array enthält die Bildpixeldaten.

153
NLi10Me

Ich denke, der schnellste und prägnanteste Weg, dies zu tun, ist die Verwendung der in NumPy integrierten Fancy-Indexierung. Wenn Sie ein ndarray mit dem Namen arr haben, können Sie alle Elemente >255 wie folgt durch einen Wert x ersetzen:

arr[arr > 255] = x

Ich habe dies auf meinem Computer mit einer 500 x 500-Zufallsmatrix ausgeführt, wobei alle Werte> 0,5 durch 5 ersetzt wurden, und es dauerte durchschnittlich 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
266
mdml

Da Sie tatsächlich ein anderes Array wünschen, das arr where arr < 255 und 255 ist, kann dies einfach durchgeführt werden:

result = np.minimum(arr, 255)

Allgemeiner für eine untere und/oder obere Schranke:

result = np.clip(arr, 0, 255)

Wenn Sie nur auf Werte über 255 oder etwas Komplizierteres zugreifen möchten, ist die Antwort von @ mtitan8 allgemeiner, aber np.clip und np.minimum (oder np.maximum) sind schöner und viel schneller für Sie Fall:

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

Wenn Sie dies direkt ausführen möchten (d. H. arr ändern, anstatt result zu erstellen), können Sie den out -Parameter von np.minimum verwenden:

np.minimum(arr, 255, out=arr)

oder

np.clip(arr, 0, 255, arr)

(Der Name out= ist optional, da die Argumente in derselben Reihenfolge wie die Definition der Funktion angegeben sind.)

Bei direkten Änderungen beschleunigt sich die boolesche Indizierung erheblich (ohne dass die Kopie separat erstellt und anschließend geändert werden muss), ist jedoch immer noch nicht so schnell wie 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

Zum Vergleich: Wenn Sie Ihre Werte sowohl mit einem Minimum als auch mit einem Maximum einschränken möchten, ohne clip, müssen Sie dies zweimal mit so etwas tun

np.minimum(a, 255, a)
np.maximum(a, 0, a)

oder,

a[a>255] = 255
a[a<0] = 0
43
askewchan

Ich denke, Sie können dies am schnellsten erreichen, indem Sie die Funktion where verwenden:

Suchen Sie beispielsweise nach Elementen, die größer als 0,2 sind, und ersetzen Sie diese durch 0:

import numpy as np

nums = np.random.Rand(4,3)

print np.where(nums > 0.2, 0, nums)
11
Amir F

Sie können erwägen, numpy.putmask zu verwenden:

np.putmask(arr, arr>=T, 255.0)

Hier ist ein Leistungsvergleich mit der integrierten Indexierung des Numpy:

In [1]: import numpy as np
In [2]: A = np.random.Rand(500, 500)

In [3]: timeit np.putmask(A, A>0.5, 5)
1000 loops, best of 3: 1.34 ms per loop

In [4]: timeit A[A > 0.5] = 5
1000 loops, best of 3: 1.82 ms per loop
8
lev

Eine andere Möglichkeit ist die Verwendung von np.place, das das Ersetzen vor Ort durchführt und mit multidimentionalen Arrays funktioniert:

import numpy as np

arr = np.arange(6).reshape(2, 3)
np.place(arr, arr == 0, -10)
8
Shital Shah

Sie können auch &, | (und/oder) für mehr Flexibilität verwenden:

werte zwischen 5 und 10: A[(A>5)&(A<10)]

werte größer als 10 oder kleiner als 5: A[(A<5)|(A>10)]

2
Mahdi Shahbaba