Эффективный способ вычислить расстояние ячейки матрицы от произвольной координаты в numpy - PullRequest
0 голосов
/ 26 апреля 2019

Я ищу эффективное решение этой проблемы:

У меня есть матрица N by N. Учитывая произвольную i, j координату (может быть десятичной) матрицы и произвольный диапазон, мне нужно вычислить значение каждой ячейки матрицы, деленное на ее евклидово расстояние до координаты в указанном диапазоне.

В случае, если это не было ясно. Учитывая координаты (5.2, 5.5) и диапазон 1. Мне нужно взять все 8 соседей ячейки (5,5) и саму ячейку и разделить значения этих ячеек по их расстоянию до (5.2, 5.5).

Ниже приведена простая и очень медленная версия кода.

PROXIMITY_RANGE = 1
x = 5.2
y = 5.5
min_x = int(max(int(x) - PROXIMITY_RANGE, 0))
max_x = int(min(int(x) + PROXIMITY_RANGE, IMAGE_SIZE - 1))
min_y = int(max(int(y) - PROXIMITY_RANGE, 0))
max_y = int(min(int(y) + PROXIMITY_RANGE, IMAGE_SIZE - 1))

total = 0
for c_x in np.arange(min_x, max_x+1):
    for c_y in np.arange(min_y, max_y+1):
        distance = math.sqrt((x - c_x)**2 + (y - c_y)**2)
        total += input[c_y][c_x] / (1 + distance)

1 Ответ

0 голосов
/ 26 апреля 2019

Мы можем векторизовать ваш код, чтобы сделать его более эффективным, удалив два цикла for и заменив их на пустые операции и нарезку.Кроме того, удаление стандартного python math.sqrt и его замена на np.sqrt должны повысить производительность, что особенно заметно при использовании больших матриц

import numpy as np

IMAGE_SIZE = 100
input = np.random.randint(0, 100, size=(IMAGE_SIZE,IMAGE_SIZE))

PROXIMITY_RANGE = 1
x = 5.2
y = 5.5
min_x = int(max(int(x) - PROXIMITY_RANGE, 0))
max_x = int(min(int(x) + PROXIMITY_RANGE, IMAGE_SIZE - 1))
min_y = int(max(int(y) - PROXIMITY_RANGE, 0))
max_y = int(min(int(y) + PROXIMITY_RANGE, IMAGE_SIZE - 1))

size_y = max_y+1-min_y
size_x = max_x+1-min_x

#shape x and y to be like what you had in your for loops
y_vals = np.repeat(np.reshape(np.arange(min_y, max_y+1), (-1, size_y)), size_y, axis=0).transpose()
x_vals = np.tile(np.arange(min_x, max_x+1), (size_x, 1))

#extract the bits of the input we watn 
sliced_input = input[min_y:max_y+1, min_x:max_x+1]

# compute euclidean distance
distance = np.sqrt((x_vals - x)**2 + (y_vals - y)**2) + 1

#sum the total of the cell values
total = np.sum(sliced_input / distance)

print(total)

Кроме того, у вас была ошибка, при которой расстояние всегда было равно нулю.Это произошло из-за переопределения x и y в итераторе цикла for.

...