Для этого можно использовать scipy.ndimage.binary_fill_holes
:
import scipy
a = np.array([
[0, 0, 1, 1, 1],
[0, 0, 1, 0, 1],
[0, 0, 1, 1, 1],
[0, 0, 0, 0, 0],
[2, 2, 2, 0, 0],
[2, 0, 2, 0, 0],
[2, 2, 2, 0, 0],
])
b = scipy.ndimage.binary_fill_holes(a)
print(b.astype(int))
# [[0 0 1 1 1]
# [0 0 1 1 1]
# [0 0 1 1 1]
# [0 0 0 0 0]
# [1 1 1 0 0]
# [1 1 1 0 0]
# [1 1 1 0 0]]
Одна из проблем заключается в том, что он не поддерживает идентификатор формы. Если вы хотите, это может быть немного сложнее ... Если у вас нет случаев, когда одна фигура находится внутри другой, возможно, это может сработать:
import scipy
a = np.array([
[0, 0, 1, 1, 1],
[0, 0, 1, 0, 1],
[0, 0, 1, 1, 1],
[0, 0, 0, 0, 0],
[2, 2, 2, 0, 0],
[2, 0, 2, 0, 0],
[2, 2, 2, 0, 0],
])
b = np.zeros_like(a)
for i in range(a.max()):
shape = i + 1
b += shape * scipy.ndimage.binary_fill_holes(a == shape)
print(b)
# [[0 0 1 1 1]
# [0 0 1 1 1]
# [0 0 1 1 1]
# [0 0 0 0 0]
# [2 2 2 0 0]
# [2 2 2 0 0]
# [2 2 2 0 0]]
Есть еще сложные случаи. Например, ввод:
1 1 1
1 0 2
2 2 2
будет производить все единицы в первом фрагменте и без изменений во втором. В зависимости от того, что именно вам нужно, вы можете настроить код по мере необходимости.