У меня есть большой массив numpy, которым мне нужно манипулировать, чтобы каждый элемент был изменен на 1 или 0, если условие выполнено (будет использоваться в качестве маски пикселей позже). В массиве около 8 миллионов элементов, и мой текущий метод занимает слишком много времени для конвейера сокращения:
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
Есть ли функция numpy, которая ускорит это?
python
arrays
numpy
conditional
ChrisFro
источник
источник
mask_data[y,x]==3
?if mask_data[y,x]>=3:
Ответы:
>>> 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]])
Вы можете сократить это с помощью:
>>> c = (a < 3).astype(int)
источник
>>> 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]]) >>>
См., Например, Индексирование с помощью логических массивов .
источник
a[a > 3] = -101+a[a > 3]
.a[a > 3] = -101+a[a > 3]
вместоa[a > 3] += -101
вас, скорее всего , утечка памяти лица.Самый быстрый (и самый гибкий) способ - использовать np.where , который выбирает между двумя массивами в соответствии с маской (массив истинных и ложных значений):
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)
который будет производить:
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]]
источник
a[a<3] = 0
Вы можете создать свой массив масок за один шаг следующим образом
mask_data = input_mask_data < 3
Это создает логический массив, который затем можно использовать в качестве маски пикселей. Обратите внимание, что мы не изменили входной массив (как в вашем коде), но создали новый массив для хранения данных маски - я бы рекомендовал сделать это таким образом.
>>> 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) >>>
источник
.astype(int)
или*1
, но массивTrue
иFalse
ничем не хуже.Не уверен, что понял ваш вопрос, но если вы напишете:
mask_data[:3, :3] = 1 mask_data[3:, 3:] = 0
Это сделает все значения данных маски, чьи индексы x и y меньше 3, равными 1, а все остальные будут равны 0
источник