Подтвердить что ты не робот

Как распустить шаблон в массиве numpy?

Извините странное название, я не мог думать о подходящей формулировке.

Скажем, у меня есть массив вроде:

arr = [[0 1 1 1 1 1 1 1 0],
       [0 0 1 1 1 1 1 0 0],
       [0 0 0 1 1 1 0 0 0],
       [0 0 0 0 1 0 0 0 0],
       [0 0 0 0 0 0 0 0 0]]

Я ищу "травить" прочь 1, которые касаются 0 s, что приведет к:

arr = [[0 0 1 1 1 1 1 0 0],
       [0 0 0 1 1 1 0 0 0],
       [0 0 0 0 1 0 0 0 0],
       [0 0 0 0 0 0 0 0 0],
       [0 0 0 0 0 0 0 0 0]] .

Я пробовал несколько вещей с подобными np.roll, но кажется неэффективным (и имеет краевые эффекты). Есть ли хороший короткий способ сделать это?

4b9b3361

Ответ 1

Морфолокальная эрозия может быть использована здесь.

Морфологическая эрозия задает пиксель в точке (i, j) до минимума по всем пикселям в окрестности, расположенной по центру (i, j). источник

data
Out[39]: 
array([[0, 1, 1, 1, 1, 1, 1, 1, 0],
       [0, 0, 1, 1, 1, 1, 1, 0, 0],
       [0, 0, 0, 1, 1, 1, 0, 0, 0],
       [0, 0, 0, 0, 1, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0]])

structure
Out[40]: 
array([[0, 1, 0],
       [1, 1, 1],
       [0, 1, 0]])

eroded = binary_erosion(data, structure, border_value=1).astype(int)

eroded
Out[42]: 
array([[0, 0, 1, 1, 1, 1, 1, 0, 0],
       [0, 0, 0, 1, 1, 1, 0, 0, 0],
       [0, 0, 0, 0, 1, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0]])

Ответ 2

Рассмотрим свертку с крестообразным ядром.

import numpy as np
from scipy.signal import convolve2d
kernel = np.array([[0,1,0], [1,1,1], [0,1,0]])
mask = convolve2d(arr, kernel, boundary='symm', mode='same')
arr[mask!=5] = 0

Этот метод работает правильно для всех входов:

In [143]: D = np.random.random_integers(0,1, (5,5))

In [144]: D2 = D.copy()

In [145]: mask = convolve2d(D, kernel, boundary='symm', mode='same')

In [146]: D2[mask!=5] = 0

In [147]: binary_erosion(D, kernel2, border_value=1).astype(int)
Out[147]: 
array([[0, 1, 0, 1, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0]])

In [148]: D2
Out[148]: 
array([[0, 0, 0, 1, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0]])

In [149]: D
Out[149]: 
array([[1, 0, 1, 1, 1],
       [0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0],
       [0, 0, 1, 1, 0],
       [1, 0, 1, 0, 0]])
In [150]: kernel
Out[150]: 
array([[0, 1, 0],
       [1, 1, 1],
       [0, 1, 0]])

In [151]: kernel2
Out[151]: 
array([[0, 1, 0],
       [1, 0, 1],
       [0, 1, 0]])

Посмотрите на углы, чтобы увидеть различия.