从 label_image 获取图像中对象的边缘

getting the edges of objects in an image from a label_image

我有一个 label_image 它实际上是一个数组,它将图像的每个像素分配给现实生活中的对象。因此,例如,如果 label_image 看起来像

0,0,0,0,0,0,0,0
0,1,1,1,0,0,0,0
0,1,1,1,0,0,0,0
0,1,1,1,0,2,0,0
0,0,0,0,2,2,2,0
0,0,0,0,0,2,0,0
0,0,0,0,0,0,0,0

那么可以理解为我的图片显示了两个物体,一个是方形的(靠近左上角,标记为第一个物体),另一个是菱形的(靠近右下角,标记为作为第二个对象) 零表示背景。

请问如何从 label_image 中获取对象的 edges/boundaries/outlines?在这个过度简化的示例中,我想以:

0,0,0,0,0,0,0,0
0,1,1,1,0,0,0,0
0,1,0,1,0,0,0,0
0,1,1,1,0,2,0,0
0,0,0,0,2,0,2,0
0,0,0,0,0,2,0,0
0,0,0,0,0,0,0,0

我正在使用 Python 3

如果将您的图像视为字符串矩阵可能是个好主意(每个标签都是一个字符串,即使它看起来像一个整数),这样您就可以从 count 内置方法中获益字符串:

mat = """
0,0,0,0,0,0,0,0
0,1,1,1,0,0,0,0
0,1,1,1,0,0,0,0
0,1,1,1,0,2,0,0
0,0,0,0,2,2,2,0
0,0,0,0,0,2,0,0
0,0,0,0,0,0,0,0
"""

# convert multi-line string into a matrix of string labels ('0','1' or '2')
mat = [line.split(',') for line in mat.strip().split('\n')]
# get matrix dimensions
rows, cols = len(mat), len(mat[0])

indices = []
for row in range(1, rows-1):
  for col in range(1, cols-1):
    # concatenate the labels of the 4 neighbors (N,S,W,E) for the current cell
    nb = mat[row-1][col] + mat[row+1][col] + mat[row][col-1] + mat[row][col+1]
    # if all neighbors have same label as current cell --> store pixel index
    if nb.count(mat[row][col]) == 4:
      indices.append((row,col))

for row, col in indices: # loop over all previously found interior pixels
  mat[row][col] = '0' # force pixel label to '0'

print(mat)

输出:

[['0', '0', '0', '0', '0', '0', '0', '0'],
 ['0', '1', '1', '1', '0', '0', '0', '0'],
 ['0', '1', '0', '1', '0', '0', '0', '0'],
 ['0', '1', '1', '1', '0', '2', '0', '0'],
 ['0', '0', '0', '0', '2', '0', '2', '0'],
 ['0', '0', '0', '0', '0', '2', '0', '0'],
 ['0', '0', '0', '0', '0', '0', '0', '0']]

注意:如果你想要输入和输出相同的矩阵(如上面代码中所做的),你必须链接两个不同的循环:第一个检测所有内部像素(并将它们的索引存储到列表中),而第二个循环遍历存储的索引并将相应的像素设置为“0”。如果你能负担得起第二个矩阵来存储输出,整个过程可以在第一个循环中完成。

您可以使用 scipy 的 binary_erosion:


import numpy as np
from scipy import ndimage 

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

mask =  ndimage.binary_erosion(eee.tolist())
eee[mask]=0                                                                                                                                                                         

输出:

array([[0, 0, 0, 0, 0, 0, 0, 0],
       [0, 1, 1, 1, 0, 0, 0, 0],
       [0, 1, 0, 1, 0, 0, 0, 0],
       [0, 1, 1, 1, 0, 2, 0, 0],
       [0, 0, 0, 0, 2, 0, 2, 0],
       [0, 0, 0, 0, 0, 2, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0]])