import networkx as nx
from PIL import Image, ImageDraw, ImageFont
import mahotas as mh
def branchedPoints(skel, showSE=True):
X=[]
#cross X
X0 = np.array([[0, 1, 0],
[1, 1, 1],
[0, 1, 0]])
X1 = np.array([[1, 0, 1],
[0, 1, 0],
[1, 0, 1]])
X.append(X0)
X.append(X1)
#T like
T=[]
#T0 contains X0
T0=np.array([[2, 1, 2],
[1, 1, 1],
[2, 2, 2]])
T1=np.array([[1, 2, 1],
[2, 1, 2],
[1, 2, 2]]) # contains X1
T2=np.array([[2, 1, 2],
[1, 1, 2],
[2, 1, 2]])
T3=np.array([[1, 2, 2],
[2, 1, 2],
[1, 2, 1]])
T4=np.array([[2, 2, 2],
[1, 1, 1],
[2, 1, 2]])
T5=np.array([[2, 2, 1],
[2, 1, 2],
[1, 2, 1]])
T6=np.array([[2, 1, 2],
[2, 1, 1],
[2, 1, 2]])
T7=np.array([[1, 2, 1],
[2, 1, 2],
[2, 2, 1]])
T.append(T0)
T.append(T1)
T.append(T2)
T.append(T3)
T.append(T4)
T.append(T5)
T.append(T6)
T.append(T7)
#Y like
Y=[]
Y0=np.array([[1, 0, 1],
[0, 1, 0],
[2, 1, 2]])
Y1=np.array([[0, 1, 0],
[1, 1, 2],
[0, 2, 1]])
Y2=np.array([[1, 0, 2],
[0, 1, 1],
[1, 0, 2]])
Y2=np.array([[1, 0, 2],
[0, 1, 1],
[1, 0, 2]])
Y3=np.array([[0, 2, 1],
[1, 1, 2],
[0, 1, 0]])
Y4=np.array([[2, 1, 2],
[0, 1, 0],
[1, 0, 1]])
Y5=np.rot90(Y3)
Y6 = np.rot90(Y4)
Y7 = np.rot90(Y5)
Y.append(Y0)
Y.append(Y1)
Y.append(Y2)
Y.append(Y3)
Y.append(Y4)
Y.append(Y5)
Y.append(Y6)
Y.append(Y7)
bp = np.zeros(skel.shape, dtype=int)
for x in X:
bp = bp + mh.morph.hitmiss(skel,x)
for y in Y:
bp = bp + mh.morph.hitmiss(skel,y)
for t in T:
bp = bp + mh.morph.hitmiss(skel,t)
if showSE==True:
fig = plt.figure(figsize=(4,5))
tX =['X0','X1']
tY =['Y'+str(i) for i in range(0,8)]
tT =['T'+str(i) for i in range(0,8)]
ti= tX+tY+tT
SE=X+Y+T
print len(SE), len(ti)
n = 1
ti = iter(ti)
for se in SE:
#print next(ti)
#print se
mycmap = mpl.colors.ListedColormap(['black','blue','red'])
ax = fig.add_subplot(4,5,n,frameon=False, xticks=[], yticks=[])
title(str(next(ti)))
imshow(se, interpolation='nearest',vmin=0,vmax=2,cmap=mycmap)
n = n+1
fig.subplots_adjust(hspace=0.1,wspace=0.08)
#ax_cb = fig.add_axes([.9,.25,.1,.3])#
color_vals=[0,1,2]
#cb = mpl.colorbar.ColorbarBase(ax_cb,cmap=mycmap, ticks=color_vals)
#cb.set_ticklabels(['back', 'hit', 'don\'t care'])
plt.show()
return bp > 0
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 > 0
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
def edges_from_C8skel(c8skeleton):
'''given a skeleton defined on c8 neighborhood (use mahotas),
\ returns labeled edges
'''
branchedP = branchedPoints(c8skeleton, showSE = False) > 0
endP = endPoints(c8skeleton) > 0
edges = np.logical_not(branchedP)*c8skeleton
label_edges,ne = mh.label(edges)
return label_edges
def add_bp_to_graph(Graph, labels_branchpoints):
labels = np.arange(1, labels_branchpoints.max()+1)
label_bp = {}
for lab in labels:
pos = np.where(labels_branchpoints==lab)
row = int(pos[0])
col = int(pos[1])
label_bp[lab] = lab
Graph.add_node(lab, pos= (row,col), label=lab)
return label_bp
def add_ep_to_graph(Graph, im_labels_endpoints):
label_ep = {}
first_endpoint = Graph.number_of_nodes()+1
labels = np.where(mh.histogram.fullhistogram(np.uint16(im_labels_endpoints))[:]==1)[0]
n=0
for lab in labels:
pos = np.where(im_labels_endpoints==lab)
row = int(pos[0])
col = int(pos[1])
nodeIndex = first_endpoint + n
Graph.add_node( nodeIndex, pos= (row,col), label=lab)
label_ep[lab]= nodeIndex
n = n+1
return label_ep
def C8skeleton_to_graph(skeletonC8):
#images processing: extraction of branchedpoints, end-points, edges
ep = endPoints(skeletonC8)
bp = branchedPoints(skeletonC8, showSE = False)
## Label branched-points
l_bp,_ = mh.label(bp)
## Label the edges
l_edges = edges_from_C8skel(skeletonC8)
##Make end-points with the same label than their edge
l_ep = ep*l_edges
##edges between branched-points
endpoints_labels = np.where(mh.histogram.fullhistogram(np.uint16(l_ep))[:]==1)[0]
edges_bp = np.copy(l_edges)
for l in endpoints_labels:
edges_bp[np.where(edges_bp == l)]=0
#edges between end-points and branched points
edges_ep_to_bp = l_edges * np.logical_not(edges_bp > 0)
#Building graph
## Add branched points first
G=nx.Graph()
lab_bpTonode = add_bp_to_graph(G, l_bp)
## Add end-points
lab_epTonode = add_ep_to_graph(G, l_ep)
##Link end-points to branched-points
###labels of bp
branchedpoints_labels = np.where(mh.histogram.fullhistogram(np.uint16(l_bp))[:]==1)[0]
for lab in branchedpoints_labels:
pos = np.where(l_bp == lab)
row = int(pos[0])
col = int(pos[1])
#search label(s) of edges in image containing edges between ep and bp
## first get the neighborhood of the curent bp
neigh_epbp = edges_ep_to_bp[row-1:row+1+1,col-1:col+1+1]
labels_in_neigh = np.where(mh.histogram.fullhistogram(np.uint16(neigh_epbp))[:]<>0)[0]
#print neigh_epbp, labels_in_neigh[1:]
#get node(s) of attribute label= labels_in_neigh ! may be more than one, think to a list
for lab_ep in labels_in_neigh[1:]:
#search for nodes f attribute label= lab_ep
w = np.sum(l_edges==lab_ep)
#print 'linking ',lab, lab_ep, ' weight ',w
G.add_edge(lab_bpTonode[lab],lab_epTonode[lab_ep],weight=w)#
##
##Now try to link branched points between them
##
bps_neighborhood = {}
branchedpoints_labels = np.where(mh.histogram.fullhistogram(np.uint16(l_bp))[:]==1)[0]
for lab in branchedpoints_labels:
pos = np.where(l_bp == lab)
row = int(pos[0])
col = int(pos[1])
#search label(s) of edges in image containing edges between ep and bp
## first get the neighborhood of the curent bp
neigh_epbp = edges_bp[row-1:row+1+1,col-1:col+1+1]
labels_in_neigh = np.where(mh.histogram.fullhistogram(np.uint16(neigh_epbp))[:]<>0)[0]
bps_neighborhood[lab]=labels_in_neigh[1:].tolist()
#print bps_neighborhood
## Build the dictionnary of edges see (http://stackoverflow.com/questions/21375146/pythonic-inverse-dict-non-unique-mappings)
invert_is_edges = {item: [key for key in bps_neighborhood if item in bps_neighborhood[key]] for value in bps_neighborhood.values() for item in value}
## Addeges to graph
for ed in invert_is_edges.keys():
## first get edge size -> its weight
w = np.sum(edges_bp==ed)
vertex1 = invert_is_edges[ed][0]
vertex2 = invert_is_edges[ed][1]
#print ed,w
G.add_edge(vertex1,vertex2,weight=w)
## This is it !!
return G
def makeLetterImage(character, size):
image = Image.new("RGBA", (600,150), (255,255,255))
draw = ImageDraw.Draw(image)
font = ImageFont.truetype("verdana.ttf", size)
draw.text((5, 0), character, (0,0,0), font=font)
img_resized = np.array(image.resize((300,75), Image.ANTIALIAS))
letter = img_resized[0:40,0:30,0]<64
r1 = mh.bbox(letter)[0]
r2 = mh.bbox(letter)[1]
c1 = mh.bbox(letter)[2]
c2 = mh.bbox(letter)[3]
letter = letter[r1-1:r2+1,c1-1:c2+1]
return letter
imA = makeLetterImage("A", 70)
imB = makeLetterImage("B", 70)
imH = makeLetterImage("H", 70)
imO= makeLetterImage("O", 70)
skeletonB = mh.thin(imB)
Bgraph = C8skeleton_to_graph(skeletonB)
skeletonA = mh.thin(imA)
Agraph = C8skeleton_to_graph(skeletonA)
skeletonO = mh.thin(imO)
Og = C8skeleton_to_graph(skeletonO)
linking 1 1 weight 2 linking 4 7 weight 2 {1: [2, 3], 2: [3, 4, 5], 3: [2, 4, 6], 4: [5, 6]} linking 1 1 weight 2 linking 2 2 weight 3 linking 3 6 weight 12 linking 4 8 weight 12 {1: [3, 4], 2: [3, 5], 3: [4, 7], 4: [5, 7]} {}
figsize(6,6)
subplot(221,xticks=[],yticks=[])
imshow(imA, interpolation='nearest')
subplot(222,xticks=[],yticks=[])
nx.draw(Agraph)
subplot(223,xticks=[],yticks=[])
imshow(skeletonO, interpolation='nearest')
subplot(224,xticks=[],yticks=[])
nx.draw(Og)
import string
alphabet = list(string.ascii_uppercase)
ilphabet = []
for l in alphabet:
imLetter = makeLetterImage(l, 70)
skeletter = mh.thin(imLetter)
BP = branchedPoints(skeletter, showSE=False)
EP = endPoints(skeletter)
ilphabet.append(skeletter+10*BP+3*EP)#np.uint(skeletter) +
figsize(10,10)
for im,n in zip(ilphabet, range(1,27)):
subplot(6,5,n,xticks=[],yticks=[])
imshow(im,interpolation='nearest')
gralphabet = []
ilphabet = []
for l in alphabet:
imLetter = makeLetterImage(l, 70)
skeletter = mh.thin(imLetter)
print l
gralphabet.append(C8skeleton_to_graph(skeletter))
A B C D E F G H I J K
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-75-776d5253f624> in <module>() 5 skeletter = mh.thin(imLetter) 6 print l ----> 7 gralphabet.append(C8skeleton_to_graph(skeletter)) 8 <ipython-input-30-18929c12993f> in C8skeleton_to_graph(skeletonC8) 21 ## Add branched points first 22 G=nx.Graph() ---> 23 lab_bpTonode = add_bp_to_graph(G, l_bp) 24 ## Add end-points 25 lab_epTonode = add_ep_to_graph(G, l_ep) <ipython-input-4-091810c1f148> in add_bp_to_graph(Graph, labels_branchpoints) 4 for lab in labels: 5 pos = np.where(labels_branchpoints==lab) ----> 6 row = int(pos[0]) 7 col = int(pos[1]) 8 label_bp[lab] = lab TypeError: only length-1 arrays can be converted to Python scalars
print len(gralphabet)
figsize(10,15)
for g,n in zip(gralphabet, range(1,11)):
subplot(4,3,n)
nx.draw(g)
10