Flood fill NumPy Array `numpy.ndarray`, т.е. присваивать элементу новое значение и изменять соседние элементы с тем же значением. - PullRequest
1 голос
/ 26 мая 2019

Другой, похожий пост под названием Flood Fill в Python - это очень общий вопрос о заливке, и ответ содержит только пример с широким псевдокодом. Я ищу явное решение с numpy или scipy.


Давайте возьмем этот массив для примера:

a = np.array([
    [0, 1, 1, 1, 1, 0],
    [0, 0, 1, 2, 1, 1],
    [0, 1, 1, 1, 1, 0]
])

Для выбора элемента 0, 0 и заливки со значением 3, я бы ожидал:

[
    [3, 1, 1, 1, 1, 0],
    [3, 3, 1, 2, 1, 1],
    [3, 1, 1, 1, 1, 0]
]

Для выбора элемента 0, 1 и заливки со значением 3 я бы ожидал:

[
    [0, 3, 3, 3, 3, 0],
    [0, 0, 3, 2, 3, 3],
    [0, 3, 3, 3, 3, 0]
]

Для выбора элемента 0, 5 и заливки со значением 3 я бы ожидал:

[
    [0, 1, 1, 1, 1, 3],
    [0, 0, 1, 2, 1, 1],
    [0, 1, 1, 1, 1, 0]
]

Это должна быть довольно простая операция, нет? Какой метод numpy или scipy я пропускаю?

1 Ответ

2 голосов
/ 26 мая 2019

Подход № 1

Модуль scikit-image предлагает встроенный для того же сделать с skimage.segmentation.flood_fill -

from skimage.morphology import flood_fill

flood_fill(image, (x, y), newval)

Примеры прогонов -

In [17]: a
Out[17]: 
array([[0, 1, 1, 1, 1, 0],
       [0, 0, 1, 2, 1, 1],
       [0, 1, 1, 1, 1, 0]])

In [18]: flood_fill(a, (0, 0), 3)
Out[18]: 
array([[3, 1, 1, 1, 1, 0],
       [3, 3, 1, 2, 1, 1],
       [3, 1, 1, 1, 1, 0]])

In [19]: flood_fill(a, (0, 1), 3)
Out[19]: 
array([[0, 3, 3, 3, 3, 0],
       [0, 0, 3, 2, 3, 3],
       [0, 3, 3, 3, 3, 0]])

In [20]: flood_fill(a, (0, 5), 3)
Out[20]: 
array([[0, 1, 1, 1, 1, 3],
       [0, 0, 1, 2, 1, 1],
       [0, 1, 1, 1, 1, 0]])

Подход № 2

Мы можем использовать skimage.measure.label с некоторыми array-masking -

from skimage.measure import label

def floodfill_by_xy(a,xy,newval):
    x,y = xy
    l = label(a==a[x,y])
    a[l==l[x,y]] = newval
    return a

Чтобы использовать функцию label на основе SciPy - scipy.ndimage.measurements.label, она в основном будет такой же -

from scipy.ndimage.measurements import label

def floodfill_by_xy_scipy(a,xy,newval):
    x,y = xy
    l = label(a==a[x,y])[0]
    a[l==l[x,y]] = newval
    return a

Примечание: они будут работать какРедактирование на месте.

...