找到立即完全包围 0s 区域的 1s 像素

Find the 1s pixels that immediately and completely enclose an area of 0s

从一个由 0 和 1 组成的二维数组开始,我需要确定哪些 1 形成了一个完全包围一个或多个相邻 0 的联合栅栏。如果这些 0 在它们的侧面或对角线上接触,则它们被认为是相邻的。栅栏也必须存在于相邻的对角线上。

这是二维数组,我要的是表示栅栏的1,然后其他都为零。这是一个简单的例子,实际上数组是一个png图片,我想要里面可能存在的所有栅栏。

ndimage 是需要的模块吗?有什么建议吗

array=
[[1,1,1,1,1,1],  
 [1,1,0,0,1,1],  
 [1,1,0,1,1,1],  
 [1,1,1,1,1,1],  
 [0,0,1,1,0,0]] 

answer=
[[0,1,1,1,1,0],  
 [0,1,0,0,1,0],  
 [0,1,0,1,1,0],  
 [0,1,1,1,0,0],  
 [0,0,0,0,0,0]] 

遵循Jerome and Mark建议的方法:

  1. 用 1px 的零边框填充矩阵
  2. 填充矩阵并只保留中心 0 的孤岛
  3. 用 dilate 扩展那些岛(在反转它们之后)以扩展轮廓 -> B
  4. 按位与 A 取回轮廓并删除初始填充
from collections import deque as queue
from scipy import ndimage
import numpy as np
from skimage.segmentation import flood_fill

A = np.array([[1,1,1,1,1,1],  
              [1,1,0,0,1,1],  
              [1,1,0,1,1,1],  
              [1,1,1,1,1,1],  
              [0,0,1,1,0,0]])
A = np.pad(A, pad_width=1, mode='constant', constant_values=0)
print("A after padding")
print(A)

A = flood_fill(A, (0, 0), 1)
print("A after flooding")
print(A)

# you can also use cv2.dilate if you want to avoid ndimage
struct2 = ndimage.generate_binary_structure(2, 2)
B = ndimage.binary_dilation(1-A, structure=struct2).astype(A.dtype)
print("B")
print(B)

print("result")
res = B & A
print(res[1:-1, 1:-1]) # remove padding

输出:

A after padding
[[0 0 0 0 0 0 0 0]
 [0 1 1 1 1 1 1 0]
 [0 1 1 0 0 1 1 0]
 [0 1 1 0 1 1 1 0]
 [0 1 1 1 1 1 1 0]
 [0 0 0 1 1 0 0 0]
 [0 0 0 0 0 0 0 0]]
A after BFS
[[1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1]
 [1 1 1 0 0 1 1 1]
 [1 1 1 0 1 1 1 1]
 [1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1]
 [1 1 1 1 1 1 1 1]]
B
[[0 0 0 0 0 0 0 0]
 [0 0 1 1 1 1 0 0]
 [0 0 1 1 1 1 0 0]
 [0 0 1 1 1 1 0 0]
 [0 0 1 1 1 0 0 0]
 [0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0]]
result
[[0 1 1 1 1 0]
 [0 1 0 0 1 0]
 [0 1 0 1 1 0]
 [0 1 1 1 0 0]
 [0 0 0 0 0 0]]