Medial axis skeletonizationΒΆ

The medial axis of an object is the set of all points having more than one closest point on the object’s boundary. It is often called the topological skeleton, because it is a 1-pixel wide skeleton of the object, with the same connectivity as the original object.

Here, we use the medial axis transform to compute the width of the foreground objects. As the function medial_axis (skimage.morphology.medial_axis) returns the distance transform in addition to the medial axis (with the keyword argument return_distance=True), it is possible to compute the distance to the background for all points of the medial axis with this function. This gives an estimate of the local width of the objects.

For a skeleton with fewer branches, there exists another skeletonization algorithm in skimage: skimage.morphology.skeletonize, that computes a skeleton by iterative morphological thinnings.

../_images/plot_medial_transform_1.png

import numpy as np
from scipy import ndimage
from skimage.morphology import medial_axis
import matplotlib.pyplot as plt


def microstructure(l=256):
    """
    Synthetic binary data: binary microstructure with blobs.

    Parameters
    ----------

    l: int, optional
        linear size of the returned image

    """
    n = 5
    x, y = np.ogrid[0:l, 0:l]
    mask_outer = (x - l/2)**2 + (y - l/2)**2 < (l/2)**2
    mask = np.zeros((l, l))
    generator = np.random.RandomState(1)
    points = l * generator.rand(2, n**2)
    mask[(points[0]).astype(np.int), (points[1]).astype(np.int)] = 1
    mask = ndimage.gaussian_filter(mask, sigma=l/(4.*n))
    return mask > mask.mean()

data = microstructure(l=64)

# Compute the medial axis (skeleton) and the distance transform
skel, distance = medial_axis(data, return_distance=True)

# Distance to the background for pixels of the skeleton
dist_on_skel = distance * skel

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4))
ax1.imshow(data, cmap=plt.cm.gray, interpolation='nearest')
ax1.axis('off')
ax2.imshow(dist_on_skel, cmap=plt.cm.spectral, interpolation='nearest')
ax2.contour(data, [0.5], colors='w')
ax2.axis('off')

fig.subplots_adjust(hspace=0.01, wspace=0.01, top=1, bottom=0, left=0, right=1)
plt.show()

STDOUT


        

STDERR


        

Python source code: download (generated using skimage 0.11dev)

IPython Notebook: download (generated using skimage 0.11dev)

aW1wb3J0IG51bXB5IGFzIG5wCmZyb20gc2NpcHkgaW1wb3J0IG5kaW1hZ2UKZnJvbSBza2ltYWdlLm1vcnBob2xvZ3kgaW1wb3J0IG1lZGlhbF9heGlzCmltcG9ydCBtYXRwbG90bGliLnB5cGxvdCBhcyBwbHQKCgpkZWYgbWljcm9zdHJ1Y3R1cmUobD0yNTYpOgogICAgIiIiCiAgICBTeW50aGV0aWMgYmluYXJ5IGRhdGE6IGJpbmFyeSBtaWNyb3N0cnVjdHVyZSB3aXRoIGJsb2JzLgoKICAgIFBhcmFtZXRlcnMKICAgIC0tLS0tLS0tLS0KCiAgICBsOiBpbnQsIG9wdGlvbmFsCiAgICAgICAgbGluZWFyIHNpemUgb2YgdGhlIHJldHVybmVkIGltYWdlCgogICAgIiIiCiAgICBuID0gNQogICAgeCwgeSA9IG5wLm9ncmlkWzA6bCwgMDpsXQogICAgbWFza19vdXRlciA9ICh4IC0gbC8yKSoqMiArICh5IC0gbC8yKSoqMiA8IChsLzIpKioyCiAgICBtYXNrID0gbnAuemVyb3MoKGwsIGwpKQogICAgZ2VuZXJhdG9yID0gbnAucmFuZG9tLlJhbmRvbVN0YXRlKDEpCiAgICBwb2ludHMgPSBsICogZ2VuZXJhdG9yLnJhbmQoMiwgbioqMikKICAgIG1hc2tbKHBvaW50c1swXSkuYXN0eXBlKG5wLmludCksIChwb2ludHNbMV0pLmFzdHlwZShucC5pbnQpXSA9IDEKICAgIG1hc2sgPSBuZGltYWdlLmdhdXNzaWFuX2ZpbHRlcihtYXNrLCBzaWdtYT1sLyg0LipuKSkKICAgIHJldHVybiBtYXNrID4gbWFzay5tZWFuKCkKCmRhdGEgPSBtaWNyb3N0cnVjdHVyZShsPTY0KQoKIyBDb21wdXRlIHRoZSBtZWRpYWwgYXhpcyAoc2tlbGV0b24pIGFuZCB0aGUgZGlzdGFuY2UgdHJhbnNmb3JtCnNrZWwsIGRpc3RhbmNlID0gbWVkaWFsX2F4aXMoZGF0YSwgcmV0dXJuX2Rpc3RhbmNlPVRydWUpCgojIERpc3RhbmNlIHRvIHRoZSBiYWNrZ3JvdW5kIGZvciBwaXhlbHMgb2YgdGhlIHNrZWxldG9uCmRpc3Rfb25fc2tlbCA9IGRpc3RhbmNlICogc2tlbAoKZmlnLCAoYXgxLCBheDIpID0gcGx0LnN1YnBsb3RzKDEsIDIsIGZpZ3NpemU9KDgsIDQpKQpheDEuaW1zaG93KGRhdGEsIGNtYXA9cGx0LmNtLmdyYXksIGludGVycG9sYXRpb249J25lYXJlc3QnKQpheDEuYXhpcygnb2ZmJykKYXgyLmltc2hvdyhkaXN0X29uX3NrZWwsIGNtYXA9cGx0LmNtLnNwZWN0cmFsLCBpbnRlcnBvbGF0aW9uPSduZWFyZXN0JykKYXgyLmNvbnRvdXIoZGF0YSwgWzAuNV0sIGNvbG9ycz0ndycpCmF4Mi5heGlzKCdvZmYnKQoKZmlnLnN1YnBsb3RzX2FkanVzdChoc3BhY2U9MC4wMSwgd3NwYWNlPTAuMDEsIHRvcD0xLCBib3R0b209MCwgbGVmdD0wLCByaWdodD0xKQpwbHQuc2hvdygp