这确实是一个棘手的问题,从二值图像到图形(即拓扑)。从根本上涉及从像素和 2D 图像数据的离散世界跨越到节点和连接的抽象数据结构......
但是什么可以提供两者之间的“粘合剂”呢?恐怕这是一个相当开放的问题,需要对视觉数据进行复杂的解释。
还好有人在python这里分享了一个不错的尝试:http://planet.lengrand.fr/?post_id=267
(这显然假设一个完整的 python 安装 NetworkX 和任何其他依赖项。我在 Mac 上通过一些调用(例如 > brew install opencv; pip install networkx; brew install graph-tool; brew install graphviz)使用自制软件完成了此操作。下面的 ipython 笔记本也使用了 http://scikit-image.org 和 http://mahotas.readthedocs.org/en/latest/ -如此令人兴奋的计算机视觉和图像处理代码鸡尾酒!最后:你当然需要安装 ipython...)
这是一个示例(首先从上面加载到下载的笔记本中 - 全部从:> ipython —pylab 运行):
%run C8Skeleton_to_graph-01.ipynb
import scipy.io as sio # Need this to load matlab files...
mat = sio.loadmat('bw.mat')
img = np.zeros((30,70),np.uint8) # Buffered image border
img[5:25,5:65] = mat['BW'] # Insert matrix data into middle
skeleton = mh.thin(img) # Do skeletonization...
graph = nx.MultiGraph() # Graph we’ll create
C8_Skeleton_To_Graph_01(graph, skeleton) # Do it!
figure(1)
subplot(211)
plt.imshow(img,plt.get_cmap('gray'), vmin=0, vmax=1, origin='upper');
subplot(212)
plt.imshow(skeleton,plt.get_cmap('gray'), vmin=0, vmax=1, origin='upper');
figure(2)
nx.draw(graph)
显示您最初提供的 Matlab 数据的骨架化(边缘周围有缓冲区):
结果如下图:
请注意图形拓扑和布局与细化图像的结构相对应 - 包括最后创建的“马刺”。这是一个持续存在的问题/研究领域,采用这种方法......
编辑: 但可以通过移除图中的杂散弧(导致度数==1 的叶节点)来解决。例如
remove = [node for node,degree in graph.degree().items() if degree == 1]
graph.remove_nodes_from(remove)
nx.draw(graph)