Ваш размер массива является типичным размером экрана, поэтому я предполагаю, что ячейки представляют собой значения пикселей в диапазоне [0, 1).Теперь значения пикселей никогда не умножаются друг на друга.Если бы они были, операции будут зависеть от диапазона (например, [0, 1) или [0, 255]), но они никогда не делают.Поэтому я бы предположил, что когда вы говорите «уменьшить на 10% ячейки», вы имеете в виду «вычесть 10% ячейки».Но даже в этом случае операция остается зависимой от порядка, в котором она применяется к ячейкам, поскольку обычный способ сначала вычислить общее изменение ячейки, а затем применить его (как в свертке) приведет к тому, что некоторые значения ячейки станут отрицательными (например, 0,251 - 8 * 0,1 * 0,999), что не имеет смысла, если они являются пикселями.
Позвольте мне сейчас предположить, что вы действительно хотите умножить ячейки друг на друга и нафактор, и что вы хотите сделать это, сначала на каждую ячейку влияет ее соседний номер 0 (ваша нумерация), затем ее соседний номер 1, и так далее для соседей номер 2, 3, 5, 7 и 8. КакКак правило, этот вид операций легче определить с «точки зрения» целевых ячеек, чем с исходных ячеек.Поскольку numpy быстро работает с полными массивами (или их представлениями), способ сделать это - сместить всех соседей в положение ячейки, которая должна быть изменена.У Numpy нет shift()
, но у него есть roll()
, что для наших целей столь же хорошо, потому что нас не волнуют граничные ячейки, которые, согласно вашему комментарию, могут быть восстановленык первоначальному значению в качестве последнего шага.Вот код:
import numpy as np
arr = np.random.rand(720, 1440)
threshold = 0.25
factor = 0.1
# 0 1 2
# neighbors: 3 5
# 6 7 8
# ∆y ∆x axes
arr0 = np.where(arr > threshold, arr * np.roll(arr, (1, 1), (0, 1)) * factor, arr)
arr1 = np.where(arr0 > threshold, arr0 * np.roll(arr0, 1, 0 ) * factor, arr0)
arr2 = np.where(arr1 > threshold, arr1 * np.roll(arr1, (1, -1), (0, 1)) * factor, arr1)
arr3 = np.where(arr2 > threshold, arr2 * np.roll(arr2, 1, 1 ) * factor, arr2)
arr5 = np.where(arr3 > threshold, arr3 * np.roll(arr3, -1, 1 ) * factor, arr3)
arr6 = np.where(arr5 > threshold, arr5 * np.roll(arr5, (-1, 1), (0, 1)) * factor, arr5)
arr7 = np.where(arr6 > threshold, arr6 * np.roll(arr6, -1, 0 ) * factor, arr6)
res = np.where(arr7 > threshold, arr7 * np.roll(arr7, (-1, -1), (0, 1)) * factor, arr7)
# fix the boundary:
res[:, 0] = arr[:, 0]
res[:, -1] = arr[:, -1]
res[ 0, :] = arr[ 0, :]
res[-1, :] = arr[-1, :]
Обратите внимание, что несмотря на это, основные шаги отличаются от того, что вы делаете в своем решении.Но они обязательно есть, потому что переписывание вашего решения в numpy приведет к тому, что массивы будут считываться и записываться в одной и той же операции, и это не то, что numpy может сделать предсказуемым образом.
Если вы должны изменить свойпомните, и решите вычесть вместо умножения, вам нужно только изменить столбец *
с до np.roll
на столбец -
с.Но это будет только первый шаг в направлении правильной свертки (обычная и важная операция на 2D-изображениях), для которой вам, однако, потребуется полностью переформулировать свой вопрос.
Два замечания: в вашемВ примере кода вы индексировали массив как arr[x][y]
, но по умолчанию в numy-массивах крайний левый индекс является наиболее медленно меняющимся, т. е. в 2D - вертикальным, так что правильная индексация равна arr[y][x]
.Это подтверждается порядком размеров вашего массива.Во-вторых, на изображениях, в матрицах и в куске вертикальный размер обычно представлен в виде увеличения вниз.Это заставляет вашу нумерацию соседей отличаться от моей.Просто умножьте вертикальные сдвиги на -1 при необходимости.
EDIT
Вот альтернативная реализация, которая дает точно такие же результаты.Это немного быстрее, но изменяет массив на месте:
arr[1:-1, 1:-1] = np.where(arr[1:-1, 1:-1] > threshold, arr[1:-1, 1:-1] * arr[ :-2, :-2] * factor, arr[1:-1, 1:-1])
arr[1:-1, 1:-1] = np.where(arr[1:-1, 1:-1] > threshold, arr[1:-1, 1:-1] * arr[ :-2, 1:-1] * factor, arr[1:-1, 1:-1])
arr[1:-1, 1:-1] = np.where(arr[1:-1, 1:-1] > threshold, arr[1:-1, 1:-1] * arr[ :-2, 2: ] * factor, arr[1:-1, 1:-1])
arr[1:-1, 1:-1] = np.where(arr[1:-1, 1:-1] > threshold, arr[1:-1, 1:-1] * arr[1:-1, :-2] * factor, arr[1:-1, 1:-1])
arr[1:-1, 1:-1] = np.where(arr[1:-1, 1:-1] > threshold, arr[1:-1, 1:-1] * arr[1:-1, 2: ] * factor, arr[1:-1, 1:-1])
arr[1:-1, 1:-1] = np.where(arr[1:-1, 1:-1] > threshold, arr[1:-1, 1:-1] * arr[2: , :-2] * factor, arr[1:-1, 1:-1])
arr[1:-1, 1:-1] = np.where(arr[1:-1, 1:-1] > threshold, arr[1:-1, 1:-1] * arr[2: , 1:-1] * factor, arr[1:-1, 1:-1])
arr[1:-1, 1:-1] = np.where(arr[1:-1, 1:-1] > threshold, arr[1:-1, 1:-1] * arr[2: , 2: ] * factor, arr[1:-1, 1:-1])