Skip to content

Instantly share code, notes, and snippets.

@alexbw
Created February 24, 2012 17:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save alexbw/1902342 to your computer and use it in GitHub Desktop.
Save alexbw/1902342 to your computer and use it in GitHub Desktop.
Skeletonizing an image
import SimpleCV as scv
import scipy.ndimage as ndimage
radius = 5
# Grab a little blobby image from the interwebs (it's a picture of a mouse, taken with the Microsoft Kinect)
scv_img = scv.Image("http://i.imgur.com/mGg0V.png")
# Grab a grayscale layer of the image
img = scv_img.getNumpy()[:,:,0]
# Calculate the Euclidean distance transform of the image
# ( This will make a ridge in the center of the blob that will be the bones of our skeleton )
distance_img = ndimage.distance_transform_edt(img)
# Calculate the morphological laplacian
# ( this makes the ridge from the distance transform really pop out, it's a kind of an edge detection )
morph_laplace_img = ndimage.morphological_laplace(distance_img, (radius, radius))
# Threshold the Laplacian, and voila, we've got a nice ridge
skeleton = morph_laplace_img < morph_laplace_img.min()/2
# NOTE:
# To be really robust and hardcore, you'd probably want to parameterize the "skeleton" array somehow.
# What we get back is actually a mask, not a definition of a line or curve, but it wouldn't be too hard
# to take the (x,y) positions of non-zero points in the skeleton mask and fit a function through them.
# What the function is you'd like to fit depends on what you expect your skeleton to look like
# For a mouse, it's probably a cubic, which is pretty easy.
# See http://www.scipy.org/Cookbook/FittingData for ideas on how to fit functions to data.
# Show the middle-ridge as a knock-out of the original image
img[skeleton] = 0
scv_img = scv.Image(img)
scv_img.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment