Установка окружающего блока на основе индекса центра в массиве numpy - PullRequest
2 голосов
/ 19 февраля 2020

У меня есть 2D numpy массив нулей, представляющих некоторую плоскую поверхность:

field = np.zeros((10,10))

field
Out[165]: 
array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])

Затем у меня есть массив координат в виде [row,column], например:

In [166]:c = np.array([[1,2],[4,5],[7,3],[2,6]])

In [167]:c
Out[167]: 
array([[1, 2],
       [4, 5],
       [7, 3],
       [2, 6]])

Что я хотел бы сделать, так это заполнить блок массива поля вокруг координат в c.

Out[192]: 
array([[0., 1., 1., 1., 0., 0., 0., 0., 0., 0.],
       [0., 1., 1., 1., 0., 1., 1., 1., 0., 0.],
       [0., 1., 1., 1., 0., 1., 1., 1., 0., 0.],
       [0., 0., 0., 0., 1., 1., 1., 1., 0., 0.],
       [0., 0., 0., 0., 1., 1., 1., 0., 0., 0.],
       [0., 0., 0., 0., 1., 1., 1., 0., 0., 0.],
       [0., 0., 1., 1., 1., 0., 0., 0., 0., 0.],
       [0., 0., 1., 1., 1., 0., 0., 0., 0., 0.],
       [0., 0., 1., 1., 1., 0., 0., 0., 0., 0.],
       [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])

Моя первоначальная попытка с использованием numpy векторизация:

In [168]:field[c[:,0]-1:c[:,0]+1,c[:,1]-1:c[:,1]+1] = 10
Traceback (most recent call last):

  File "<ipython-input-168-5433a2f4a5cf>", line 1, in <module>
    field[c[:,0]-1:c[:,0]+1,c[:,1]-1:c[:,1]+1] = 10

TypeError: only integer scalar arrays can be converted to a scalar index

Затем я сначала попытался создать массивы c[:,0]-1 и c[:,1]+1, но получил ту же ошибку, которая привела меня к выводу, что этот тип ранжированной индексации не может быть сделано в numpy.

Я также взглянул на np.ix _ () , но не могу установить окружающие блоки нескольких координат без a для l oop, используя этот метод.

Я могу добиться желаемого результата, однако, используя для l oop:

for row,column in c:
        field[row-1:row+2,column-1:column+2] = 1

Но не хотел бы использовать для l oop, потому что оба c и f будет большим и многомерным в моем последнем приложении, и я чувствую, что могу извлечь выгоду из скорости улучшения, сделанные numpy векторизацией.

Кроме того, я знаю, что при обработке изображений это можно рассматривать как проблему расширения или эрозии, но у меня уже есть координаты для ядра эрозии / расширения, которое будет размещаться снова и снова, несколько измерений и очень большие массивы.

1 Ответ

2 голосов
/ 19 февраля 2020

Вот простой способ, который имеет небольшое количество циклов Python и много векторизованной работы:

x, y = c[:,0], c[:,1]
for i in -1,0,1:
    for j in -1,0,1:
        field[x+i,y+j] = 1

Более сложный способ, который может быть быстрее:

offsets = np.array([[-1,-1],[-1,0],[-1,1], [0,-1],[0,0],[0,1], [1,-1],[1,0],[1,1]])
fill = (offsets + c[:,None]).reshape(-1,2)
field[fill[:,0], fill[:,1]] = 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...