Skip to content

Instantly share code, notes, and snippets.

@greentreeys
Forked from jeanpat/SkeletonToGraph.ipynb
Created January 29, 2016 06:27
Show Gist options
  • Save greentreeys/36217ee0e55e4cdf73d2 to your computer and use it in GitHub Desktop.
Save greentreeys/36217ee0e55e4cdf73d2 to your computer and use it in GitHub Desktop.
A ipython notebook. Takes an image, converts its skeleton to a networkx graph
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
# -*- coding: utf-8 -*-
# <nbformat>3.0</nbformat>
# <codecell>
import Image, ImageDraw, ImageFont
import mahotas as mh
from mahotas import polygon
import pymorph as pm
import networkx as nx
from scipy import ndimage as nd
import skimage.transform as transform
import skimage.io as sio
import scipy.misc as sm
import os
import math
# <codecell>
def branchedPoints(skel):
branch1=np.array([[2, 1, 2], [1, 1, 1], [2, 2, 2]])
branch2=np.array([[1, 2, 1], [2, 1, 2], [1, 2, 1]])
branch3=np.array([[1, 2, 1], [2, 1, 2], [1, 2, 2]])
branch4=np.array([[2, 1, 2], [1, 1, 2], [2, 1, 2]])
branch5=np.array([[1, 2, 2], [2, 1, 2], [1, 2, 1]])
branch6=np.array([[2, 2, 2], [1, 1, 1], [2, 1, 2]])
branch7=np.array([[2, 2, 1], [2, 1, 2], [1, 2, 1]])
branch8=np.array([[2, 1, 2], [2, 1, 1], [2, 1, 2]])
branch9=np.array([[1, 2, 1], [2, 1, 2], [2, 2, 1]])
br1=mh.morph.hitmiss(skel,branch1)
br2=mh.morph.hitmiss(skel,branch2)
br3=mh.morph.hitmiss(skel,branch3)
br4=mh.morph.hitmiss(skel,branch4)
br5=mh.morph.hitmiss(skel,branch5)
br6=mh.morph.hitmiss(skel,branch6)
br7=mh.morph.hitmiss(skel,branch7)
br8=mh.morph.hitmiss(skel,branch8)
br9=mh.morph.hitmiss(skel,branch9)
return br1+br2+br3+br4+br5+br6+br7+br8+br9
def endPoints(skel):
endpoint1=np.array([[0, 0, 0],
[0, 1, 0],
[2, 1, 2]])
endpoint2=np.array([[0, 0, 0],
[0, 1, 2],
[0, 2, 1]])
endpoint3=np.array([[0, 0, 2],
[0, 1, 1],
[0, 0, 2]])
endpoint4=np.array([[0, 2, 1],
[0, 1, 2],
[0, 0, 0]])
endpoint5=np.array([[2, 1, 2],
[0, 1, 0],
[0, 0, 0]])
endpoint6=np.array([[1, 2, 0],
[2, 1, 0],
[0, 0, 0]])
endpoint7=np.array([[2, 0, 0],
[1, 1, 0],
[2, 0, 0]])
endpoint8=np.array([[0, 0, 0],
[2, 1, 0],
[1, 2, 0]])
ep1=mh.morph.hitmiss(skel,endpoint1)
ep2=mh.morph.hitmiss(skel,endpoint2)
ep3=mh.morph.hitmiss(skel,endpoint3)
ep4=mh.morph.hitmiss(skel,endpoint4)
ep5=mh.morph.hitmiss(skel,endpoint5)
ep6=mh.morph.hitmiss(skel,endpoint6)
ep7=mh.morph.hitmiss(skel,endpoint7)
ep8=mh.morph.hitmiss(skel,endpoint8)
ep = ep1+ep2+ep3+ep4+ep5+ep6+ep7+ep8
return ep
def pruning(skeleton, size):
'''remove iteratively end points "size"
times from the skeleton
'''
for i in range(0, size):
endpoints = endPoints(skeleton)
endpoints = np.logical_not(endpoints)
skeleton = np.logical_and(skeleton,endpoints)
return skeleton
# <codecell>
image = Image.new("RGBA", (600,150), (255,255,255))
draw = ImageDraw.Draw(image)
fontsize = 150
font = ImageFont.truetype("/usr/share/fonts/truetype/liberation/LiberationMono-Regular.ttf", fontsize)
txt = 'A'
draw.text((30, 5), txt, (0,0,0), font=font)
img = image.resize((188,45), Image.ANTIALIAS)
plt.imshow(img)
# <codecell>
img = np.array(img)
im = img[:,0:50,0]
im = im < 128
skel = mh.thin(im)
# To fix the algorithm, prune the skeleton 1,2,3...
skel = pruning(skel,3)
bp = branchedPoints(skel)
ep = endPoints(skel)
edge = skel-bp
edge_lab,n = mh.label(edge)
bp_lab,_ = mh.label(bp)
ep_lab,_ = mh.label(ep)
# <codecell>
figsize(10,20)
subplot(141,frameon = False, xticks = [], yticks = [])
title('pruning 0')
imshow(mh.thin(im),interpolation = 'nearest')
subplot(142,frameon = False, xticks = [], yticks = [])
title('pruning 1')
imshow(pruning(mh.thin(im),1),interpolation = 'nearest')
subplot(143,frameon = False, xticks = [], yticks = [])
title('pruning 2')
imshow(pruning(mh.thin(im),2),interpolation = 'nearest')
subplot(144,frameon = False, xticks = [], yticks = [])
title('pruning 3')
imshow(pruning(mh.thin(im),3),interpolation = 'nearest')
# <codecell>
subplot(221,frameon = False, xticks = [], yticks = [])
title('skeleton')
imshow(skel,interpolation = 'nearest')
subplot(223,frameon = False, xticks = [], yticks = [])
title('skel-bp -> label')
imshow(edge_lab,interpolation = 'nearest')
subplot(224,frameon = False, xticks = [], yticks = [])
title('skel -> end points')
imshow(ep_lab,interpolation = 'nearest')
subplot(222,frameon = False, xticks = [], yticks = [])
title('branched points (bp)')
imshow(bp_lab,interpolation = 'nearest')
# <codecell>
endpoints = np.zeros(skel.shape)
edges = np.zeros(skel.shape)
for l in range(1,n+1):
cur_edge = edge_lab == l
cur_end_points = endPoints(cur_edge)
pruned_edge = pruning(cur_edge,1)
edges = np.logical_or(pruned_edge, edges)
endpoints = np.logical_or(endpoints,cur_end_points)
lab_bp, nbp = mh.label(bp)
lab_ep, nep = mh.label(endpoints+ep)
pruned_edges, ned = mh.label(edges)
# <codecell>
plt.figsize(13,8)
subplot(321,frameon = False, xticks = [], yticks = [])
title(str(np.unique(skel)))
imshow(skel, interpolation='nearest')
subplot(322,frameon = False, xticks = [], yticks = [])
title(str(np.unique(lab_bp)))
imshow(lab_bp, interpolation='nearest')
subplot(323,frameon = False, xticks = [], yticks = [])
title(str(np.unique(edge_lab)))
imshow(edge_lab, interpolation='nearest')
subplot(326,frameon = False, xticks = [], yticks = [])
edge_mask = lab_ep>0
ep_edgelab = edge_lab*edge_mask
title(str(np.unique(ep_edgelab)))
imshow(ep_edgelab,interpolation='nearest')#lab_ep
subplot(324,frameon = False, xticks = [], yticks = [])
title(str(np.unique(pruned_edges)))
imshow(pruned_edges, interpolation='nearest')
subplot(325,frameon = False, xticks = [], yticks = [])
title(str(np.unique(lab_ep)))
imshow(lab_ep, interpolation='nearest')
# <headingcell level=3>
# First make vertex from branched points and then link to the neighbouring endpoints
# <codecell>
BPlabel=np.unique(lab_bp)[1:]
EPlabel=np.unique(lab_ep)[1:]
EDlabel=np.unique(pruned_edges)[1:]
G=nx.Graph()
node_index=BPlabel.max()
selected_ep_labels = []
for bpl in BPlabel:
#branched point location
bp_row,bp_col= np.where(lab_bp==bpl)[0][0], np.where(lab_bp==bpl)[1][0]
bp_neighbor= lab_ep[bp_row-1:bp_row+2,bp_col-1:bp_col+2]
G.add_node(bpl,kind='BP',row=bp_row,col=bp_col,label=bpl)
#branched point neighborhood
neig_in_EP=lab_ep[bp_row-1:bp_row+2,bp_col-1:bp_col+2]
neig_inEplabel=np.unique(neig_in_EP)[1:]
print 'bp label',bpl,' pos',(bp_row,bp_col), 'ep neighbor label:',neig_inEplabel
for epl in neig_inEplabel:
selected_ep_labels.append(epl)
node_index = node_index+1
#print 'bp label',bpl,' pos',(bp_row,bp_col),neig_inEplabel, 'current ep',epl
ep_row,ep_col= np.where(lab_ep==epl)[0][0], np.where(lab_ep==epl)[1][0]
G.add_node(node_index,kind='EP',row=ep_row,col=ep_col,label=epl)
G.add_edge(bpl,node_index, weight=1)
print 'bp label',bpl,':',(bp_row,bp_col),neig_inEplabel,' -ep',epl,'(',node_index,')',':',(ep_row,ep_col),
#print 'edge',(bpl, node_index)
# <codecell>
figsize(5,7)
nx.draw(G)
# <codecell>
#Add isolated endpoints in the Graph
#label of isolated end points
lonely_ep = list(set(EPlabel) - set(selected_ep_labels))
#lep:lonely ep
for lep in lonely_ep:
lep_row,lep_col= np.where(lab_ep==lep)[0][0], np.where(lab_ep==lep)[1][0]
node_index = node_index+1
G.add_node(node_index,kind='EP',row=lep_row,col=lep_col,label=lep)
#print G.node[1]
#edges dict
edges={}
for ed in EDlabel:
edges[ed] = np.where(pruned_edges==ed),np.sum(pruned_edges==ed)
#print edges[ed]
#get nodes of kind EP
ep_nodes=[node for node,data in G.nodes(data=True) if data['kind'] == 'EP']
print ep_nodes
#print edges.keys()
ep_edges_lab = (lab_ep>0)*edge_lab
#print G.nodes()
#
# <codecell>
figsize(5,8)
title('Isolated endpoints are added')
nx.draw(G)
# <headingcell level=3>
# each endpoints pairs are linked
# <codecell>
# get all nodes of kind EP
#get their label
node_to_label={}
label_to_node={}
for node,data in G.nodes(data=True):
if data['kind']=='EP':
#print node,data['label']
label_to_node[data['label']]=node
print label_to_node
# <codecell>
#ep_labels from edge lab -> ep labels directly!
#
# node_index is not endpoint label!
#
map_epEdlab_epPair={}
print EDlabel
##plt.figsize(14,8)
for elab in EDlabel:
#subplot(3,3,elab)
mask = (ep_edges_lab==elab)# ep lab=edges lab
nodes_pair = np.unique(mask*lab_ep)[1:]
pair_weight = np.sum(pruned_edges==elab)
edge_image = (pruned_edges==elab)*elab
print 'edge lab',elab, 'ep2 lab',nodes_pair,'weight',pair_weight,'node1:',nodes_pair[0]
##title(str(elab)+str(np.where(ep_edgelab==elab))+str(nodes_pair))
##imshow(mask, interpolation='nearest')
node1 = label_to_node[nodes_pair[0]]
node2 = label_to_node[nodes_pair[1]]
G.add_edge(node1, node2, weight = pair_weight, image=edge_image)
# <codecell>
plt.figsize(5,8)
pos=nx.spring_layout(G)
#nx.draw_circular(G)
#subplot(121)
#nx.draw(G, width=range(1,4))
#imshow(edge_lab,interpolation='nearest')
#subplot(122)
edge_labels=dict([((u,v,),d['weight']) for u,v,d in G.edges(data=True)])
nx.draw(G)
#nx.draw_networkx_edge_labels(G,pos,edge_labels=edge_labels)
# <codecell>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment