如何从二值图像的轮廓连接点

问题描述

我有一个存储在二进制图像中的分割结果,我想从中提取轮廓。为此,我计算了掩膜和侵蚀掩膜之间的差异。因此,我能够提取位于我的分割结果边界上的像素。这是一个代码片段:

import numpy as np
from skimage.morphology import binary_erosion
from matplotlib import pyplot as plt

# mask is a 2D boolean np.array containing the segmentation result
contour_raw=np.logical_xor(mask,binary_erosion(mask)) 
contour_y,contour_x=np.where(contour_raw)

fig=plt.figure()
plt.imshow(mask)
plt.plot(contour_x,contour_y,'.r')

我最终在面具的轮廓上得到了一组点:

enter image description here

当我想连接点时,麻烦就开始了。对轮廓进行天真的绘图当然会导致令人失望的结果,因为 contour_xcontour_y 没有按照我想要的方式排序:

plt.plot(contour_x,'--r')

这是结果,重点放在图中的任意部分以突出显示点之间的连接:

enter image description here

如何对等高线坐标 contour_xcontour_y 进行排序,以便在连接点时正确排序?此外,如果我的掩码包含多个独立的连通分量,我希望获得与连通分量一样多的轮廓。

感谢您的帮助!

最好,

解决方法

我认为结合聚类和凸包适用于您的情况。在本例中,我使用 make_blobs 函数生成三个合成片段并用颜色演示每个片段:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs
from sklearn.cluster import DBSCAN
from scipy.spatial import ConvexHull,convex_hull_plot_2d

X,y = make_blobs(n_samples=1000,centers=3,n_features=2,random_state=0,cluster_std=0.3)
plt.scatter(X[:,0],X[:,1],c=y)

Synthetic segments

然后,由于段分布在二维图中,我们可以运行基于密度的聚类方法对它们进行聚类,然后通过在每个簇周围找到凸包,我们可以找到这些簇周围的点:

>

# Fitting Clustering
c_alg = DBSCAN()
c_alg.fit(X)
labels = c_alg.labels_

for i in range(0,max(labels)+1):
    ind = np.where(labels == i)

    segment = X[ind,:][0]
    hull = ConvexHull(segment)

    plt.plot(segment[:,segment[:,'o')
    for simplex in hull.simplices:
        plt.plot(segment[simplex,segment[simplex,'k-')

Convex hull

但是,在您的情况下,凹形船体不应该适用于凸形船体。 python中有一个包alphashape声称可以在二维图中找到凹壳。更多信息here。棘手的部分是找到最好的 alpha,但在本例中,我们可以使用以下方法拟合凹壳:

import alphashape
from descartes import PolygonPatch

fig,ax = plt.subplots()
for i in range(0,max(labels)+1):
  ind = np.where(labels == i)
  points = X[ind,:][0,:,:]

  alpha_shape = alphashape.alphashape(points,5.0)
  ax.scatter(*zip(*points))
  ax.add_patch(PolygonPatch(alpha_shape,alpha=0.5))

plt.show()

Concave Hull