3

Currently, I use skimage in python to extract the skeleton of open space from some a binarized map as following pictures,

Original BW map imageSkeleton-ized open area

With following python codes:

from skimage.morphology import skeletonize
from skimage import draw
from skimage.io import imread, imshow
from skimage.color import rgb2gray

# load image from file
img_fname=os.path.join('images','mall1_2F_schema.png') 
image=imread(img_fname)

# Change RGB color to gray 
image=rgb2gray(image)

# Change gray image to binary
image=np.where(image>np.mean(image),1.0,0.0)

# perform skeletonization
skeleton = skeletonize(image)

Now I would like to extract the end points and cross points from the skeleton as nodes for Networkx graph object while calculating the distance between the neighboring nodes as edges for Networkx Graph object. Currently, I have to manually get the point coordinates and input to NetworkX object initialization process, do we have any smarter way to do everything automatically?

By the way, I found yaron kahanovitch's answer to the question on stackoverflow proposes similar approaches. However, no more realization suggestions was given, and I think NetworkX could be one approach.

Any suggestions from you are greatly appreciated.

gongming wei
  • 83
  • 1
  • 9
  • Found [another interesting link to find end or cross point](https://stackoverflow.com/questions/26537313/how-can-i-find-endpoints-of-binary-skeleton-image-in-opencv) which could be helpful for approaching a solution in python. – gongming wei Dec 07 '16 at 05:53

1 Answers1

3

Here you go.

This piece of code is for 2D skeleton image and you can easily extend it to 3D.

import networkx as nx
import numpy as np

def skeleton_image_to_graph(skeIm, connectivity=2):
    assert(len(skeIm.shape) == 2)
    skeImPos = np.stack(np.where(skeIm))
    skeImPosIm = np.zeros_like(skeIm, dtype=np.int)
    skeImPosIm[skeImPos[0], skeImPos[1]] = np.arange(0, skeImPos.shape[1])
    g = nx.Graph()
    if connectivity == 1:
        neigh = np.array([[0, 1], [0, -1], [1, 0], [-1, 0]])
    elif connectivity == 2:
        neigh = np.array([[0, 1], [0, -1], [1, 0], [-1, 0], [1, 1], [1, -1], [-1, 1], [-1, -1]])
    else:
        raise ValueError(f'unsupported connectivity {connectivity}')
    for idx in range(skeImPos[0].shape[0]):
        for neighIdx in range(neigh.shape[0]):
            curNeighPos = skeImPos[:, idx] + neigh[neighIdx]
            if np.any(curNeighPos<0) or np.any(curNeighPos>=skeIm.shape):
                continue
            if skeIm[curNeighPos[0], curNeighPos[1]] > 0:
                g.add_edge(skeImPosIm[skeImPos[0, idx], skeImPos[1, idx]], skeImPosIm[curNeighPos[0], curNeighPos[1]], weight=np.linalg.norm(neigh[neighIdx]))
    g.graph['physicalPos'] = skeImPos.T
    return g
TurtleIzzy
  • 997
  • 7
  • 14