Как преобразовать границы прямоугольника в срез массива в векторизации? - PullRequest
0 голосов
/ 08 апреля 2019

Мне нужно заполнить N прямоугольными областями заполненного 0 двумерного массива единицами.Области для заполнения хранятся в массиве Nx4, где каждая строка содержит границы прямоугольника (x_low, x_high, y_low, y_high).Эта часть в настоящее время является самой медленной частью того, что я сейчас работаю, и мне интересно, можно ли это сделать быстрее.

В настоящее время это делается путем простой итерации по массиву региона, и целевой массив заполняетсяс теми, которые используют ломтики:

import numpy as np
def fill_array_with_ones(coordinates_array, target_array):
    for row in coordinates_array:
        target_array[row[0]:row[1], row[2]:row[3]] = 1

coords = np.array([[1,3,1,3], [3,5,3,5]])
target = np.zeros((5,5))
fill_array_with_ones(coords, target)
print(target)

Вывод:

array([[0., 0., 0., 0., 0.],
       [0., 1., 1., 0., 0.],
       [0., 1., 1., 0., 0.],
       [0., 0., 0., 1., 1.],
       [0., 0., 0., 1., 1.]])

Я ожидал, что есть какая-то непонятная магия, которая позволила бы мне сделать это векторизованным способом, который бы избавилсяитерации по строкам и, мы надеемся, приведут к более быстрому выполнению:

target[bounds_to_slices(coords)] = 1

1 Ответ

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

Я провел некоторый тест по поводу метода, упомянутого в комментарии, и метода цикла for.Мне интересно, действительно ли это ваша горлышко бутылки?

# prepare data
import numpy as np
a = np.zeros((1024, 1024), '?')
bound = np.random.randint(0, 1024, (9999,4), 'H')

# build indices, as indices can be pre-computed, don't time it
x = np.arange(1024, dtype='H')[:,None]
y = x[:,None]

# the force vectorized method
%%timeit
ymask = y >= bound[:,0]
ymask &= y < bound[:,1]
xmask = x >= bound[:,2]
xmask &= x < bound[:,3]
a[(ymask & xmask).any(2)] = True
# outputs 3.06 s ± 1.35 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

# the normal method
%%timeit
for i,j,k,l in bound:
    a[i:k,j:l] = True
# outputs 22.8 ms ± 28.5 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

Мало того, что «векторизованный» метод всегда медленнее, независимо от количества ограничивающих рамок, он также генерирует временный массив размером 10 ГБ.С другой стороны, обычный метод достаточно быстр.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...