Bir 2D NumPy dizim var ve içindeki T eşiğinden büyük veya eşit olan tüm değerleri 255.0 ile değiştirmek istiyorum. Bildiğim kadarıyla en temel yol şudur:
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
Bunu yapmanın en özlü ve pironik yolu nedir?
Bunu yapmanın daha hızlı (muhtemelen daha az özlü ve/veya daha az pitonik) bir yolu var mı?
Bu, insan kafasının MRI taramaları için bir pencere/seviye ayarlama alt rutininin parçası olacaktır. 2D numpy dizisi görüntü piksel verileridir.
Bence bunu yapmanın hem en hızlı hem de en özlü yolu NumPy'nin yerleşik Fancy indekslemesini kullanmaktır. Eğer arr
adında bir ndarray
iniz varsa, tüm >255
elemanlarını aşağıdaki gibi bir x
değeri ile değiştirebilirsiniz:
arr[arr > 255] = x
Bunu makinemde 500 x 500 rastgele matrisle çalıştırdım, tüm >0.5 değerlerini 5 ile değiştirdim ve ortalama 7.59 ms sürdü.
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
Aslında arr < 255
olduğunda arr
ve aksi takdirde 255
olan farklı bir dizi istediğinizden, bu basitçe yapılabilir:
result = np.minimum(arr, 255)
Daha genel olarak, bir alt ve/veya üst sınır için:
result = np.clip(arr, 0, 255)
Sadece 255'in üzerindeki değerlere veya daha karmaşık bir şeye erişmek istiyorsanız, @mtitan8'in cevabı daha geneldir, ancak np.clip
ve np.minimum
(veya np.maximum
) sizin durumunuz için daha güzel ve çok daha hızlıdır:
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
Bunu yerinde yapmak istiyorsanız (yani, result
oluşturmak yerine arr
ı değiştirmek istiyorsanız) np.minimum
parametresinin out
parametresini kullanabilirsiniz:
np.minimum(arr, 255, out=arr)
veya
np.clip(arr, 0, 255, arr)
(out=
adı isteğe bağlıdır, çünkü argümanlar fonksiyonun tanımıyla aynı sıradadır).
Yerinde değişiklik için, boolean indeksleme çok hızlanır (kopyayı ayrı ayrı yapmak ve sonra değiştirmek zorunda kalmadan), ancak yine de minimum
kadar hızlı değildir:
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
Karşılaştırma için, değerlerinizi minimum ve maksimum ile sınırlamak isterseniz, clip
olmadan bunu iki kez yapmanız gerekir, şöyle bir şeyle
np.minimum(a, 255, a)
np.maximum(a, 0, a)
ya da,
a[a>255] = 255
a[a<0] = 0
numpy.putmask]1** kullanmayı düşünebilirsiniz:
np.putmask(arr, arr>=T, 255.0)
İşte Numpy'nin yerleşik indekslemesi ile bir performans karşılaştırması:
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