Reputation: 435
I have binary skeletonized images and I use python library mahotas for extracting end-points and branched points.
I do not like mahotas thin function (there are too many little branches) and so I chose scikit-image skeletonize function.
Now troubles begin: in some images it doesn't more extract branched point. Why?
Scikit image function accepts both boolean and integer values (mahotas uses boolean).
from skimage import morphology
import mahotas as mh
import pymorph as pm
import numpy as np
import cv2
from matplotlib import pyplot as plt
import scipy
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):
for i in range(1, size):
endpoints = endPoints(skeleton)
endpoints = np.logical_not(endpoints)
skeleton = np.logical_and(skeleton,endpoints)
return skeleton
path = 'signs/a (0).jpg'
fork = mh.imread(path)
imgbnbin = fork[:,:,0]
shape = list(fork.shape)
w = (shape[0]/100 )*3.5
#structuring elements
disk7 = pm.sedisk(w)
disk5 = pm.sedisk(3)
disk3 = pm.sedisk(0.5)
bfork = imgbnbin < 150
plt.gray()
plt.subplot(121)
plt.title("after binarization")
plt.imshow(bfork)
plt.show()
bfork = mh.morph.dilate(bfork, disk7)
bfork = np.array(bfork, dtype=np.bool)
#Pota cose inutili
bfork = mh.morph.close(bfork, disk3)
# Skeleton+Pruning
#skelFk = mh.thin(bfork)
bfork = np.array(bfork, dtype=np.uint8)
skelFk = morphology.skeletonize(bfork)
skelFk = np.array(skelFk, dtype=np.bool)
skelF_pruned = pruning(skelFk, 15)
#end points (Ep) from skeletons
## fork (Fk) sign
print("skelfpruned before of endpoint")
print(skelF_pruned[70])
EpFk = endPoints(skelF_pruned)
EpFk_p = endPoints(skelF_pruned)
EpFk_p = mh.dilate(EpFk_p,disk5)
# counting end-points
lab_Ek, n1 = mh.label(EpFk)
lab_Ekp, n1p = mh.label(EpFk_p)
print n1, ' end points on fork like image'
print n1p, ' end points on fork like image, after pruning'
#branched points
## Merge too close points by morphological dilation
### Fork
BpFk = branchedPoints(skelF_pruned)# br points on Fork
print("branched point")
bcols,brows = np.where(BpFk)
print(brows)
print(bcols)
print("end point")
ecols,erows = np.where(EpFk)
print(erows)
img = skelF_pruned
# viene dilatato per mostrare meglio il punto di giunzione
BpFk = mh.morph.dilate(BpFk, disk5)
## count branched points
lab_Ek, n3 = mh.label(BpFk)
print n3, ' branched points on fork like image'
#Overlay:
#Display end-points in blue
# branched-points in yellow
# skeleton in red
display_Fk = pm.overlay(imgbnbin, red = img>0, blue = EpFk_p>0, yellow = BpFk>0)
plt.gray()
plt.subplot(121)
plt.imshow(imgbnbin)
plt.imshow(display_Fk)
plt.show()
Upvotes: 1
Views: 3039
Reputation: 83
I think the problem might be that there are actually 18 branch types and your code only searches for 9.
Try replacing your branch structures with:
xbranch0 = np.array([[1,0,1],[0,1,0],[1,0,1]])
xbranch1 = np.array([[0,1,0],[1,1,1],[0,1,0]])
tbranch0 = np.array([[0,0,0],[1,1,1],[0,1,0]])
tbranch1 = np.flipud(tbranch0)
tbranch2 = tbranch0.T
tbranch3 = np.fliplr(tbranch2)
tbranch4 = np.array([[1,0,1],[0,1,0],[1,0,0]])
tbranch5 = np.flipud(tbranch4)
tbranch6 = np.fliplr(tbranch4)
tbranch7 = np.fliplr(tbranch5)
ybranch0 = np.array([[1,0,1],[0,1,0],[2,1,2]])
ybranch1 = np.flipud(ybranch0)
ybranch2 = ybranch0.T
ybranch3 = np.fliplr(ybranch2)
ybranch4 = np.array([[0,1,2],[1,1,2],[2,2,1]])
ybranch5 = np.flipud(ybranch4)
ybranch6 = np.fliplr(ybranch4)
ybranch7 = np.fliplr(ybranch5)
Those branch structures are configured to prevent multiple hits for any single branch point. If that is not an issue, you can always replace '0's with '2's in the array structures.
Upvotes: 2