Module: morphology

skimage.morphology.black_tophat(image, selem) Return black top hat of an image.
skimage.morphology.closing(image, selem[, out]) Return greyscale morphological closing of an image.
skimage.morphology.convex_hull_image(image) Compute the convex hull image of a binary image.
skimage.morphology.diamond(radius[, dtype]) Generates a flat, diamond-shaped structuring element of a given radius.
skimage.morphology.dilation(image, selem[, ...]) Return greyscale morphological dilation of an image.
skimage.morphology.disk(radius[, dtype]) Generates a flat, disk-shaped structuring element of a given radius.
skimage.morphology.erosion(image, selem[, ...]) Return greyscale morphological erosion of an image.
skimage.morphology.greyscale_black_top_hat(...)
skimage.morphology.greyscale_close(*args, ...)
skimage.morphology.greyscale_dilate(*args, ...)
skimage.morphology.greyscale_erode(*args, ...)
skimage.morphology.greyscale_open(*args, ...)
skimage.morphology.greyscale_white_top_hat(...)
skimage.morphology.is_local_maximum(image[, ...]) Return a boolean array of points that are local maxima
skimage.morphology.label Label connected regions of an integer array.
skimage.morphology.medial_axis(image[, ...]) Compute the medial axis transform of a binary image
skimage.morphology.opening(image, selem[, out]) Return greyscale morphological opening of an image.
skimage.morphology.rectangle(width, height) Generates a flat, rectangular-shaped structuring element of a given width and height.
skimage.morphology.skeletonize(image) Return the skeleton of a binary image.
skimage.morphology.square(width[, dtype]) Generates a flat, square-shaped structuring element.
skimage.morphology.watershed(image, markers) Return a matrix labeled using the watershed segmentation algorithm
skimage.morphology.white_tophat(image, selem) Return white top hat of an image.

black_tophat

skimage.morphology.black_tophat(image, selem, out=None)

Return black top hat of an image.

The black top hat of an image is defined as its morphological closing minus the original image. This operation returns the dark spots of the image that are smaller than the structuring element. Note that dark spots in the original image are bright spots after the black top hat.

Parameters :

image : ndarray

Image array.

selem : ndarray

The neighborhood expressed as a 2-D array of 1’s and 0’s.

out : ndarray

The array to store the result of the morphology. If None is passed, a new array will be allocated.

Returns :

opening : uint8 array

The result of the black top filter.

Examples

>>> # Change dark peak to bright peak and subtract background
>>> from skimage.morphology import square
>>> dark_on_grey = np.array([[7, 6, 6, 6, 7],
...                          [6, 5, 4, 5, 6],
...                          [6, 4, 0, 4, 6],
...                          [6, 5, 4, 5, 6],
...                          [7, 6, 6, 6, 7]], dtype=np.uint8)
>>> black_tophat(dark_on_grey, square(3))
array([[0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0],
       [0, 1, 5, 1, 0],
       [0, 0, 1, 0, 0],
       [0, 0, 0, 0, 0]], dtype='uint8')

closing

skimage.morphology.closing(image, selem, out=None)

Return greyscale morphological closing of an image.

The morphological closing on an image is defined as a dilation followed by an erosion. Closing can remove small dark spots (i.e. “pepper”) and connect small bright cracks. This tends to “close” up (dark) gaps between (bright) features.

Parameters :

image : ndarray

Image array.

selem : ndarray

The neighborhood expressed as a 2-D array of 1’s and 0’s.

out : ndarray

The array to store the result of the morphology. If None, is passed, a new array will be allocated.

Returns :

closing : uint8 array

The result of the morphological closing.

Examples

>>> # Close a gap between two bright lines
>>> from skimage.morphology import square
>>> broken_line = np.array([[0, 0, 0, 0, 0],
...                         [0, 0, 0, 0, 0],
...                         [1, 1, 0, 1, 1],
...                         [0, 0, 0, 0, 0],
...                         [0, 0, 0, 0, 0]], dtype=np.uint8)
>>> closing(broken_line, square(3))
array([[0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [1, 1, 1, 1, 1],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0]], dtype='uint8')

convex_hull_image

skimage.morphology.convex_hull_image(image)

Compute the convex hull image of a binary image.

The convex hull is the set of pixels included in the smallest convex polygon that surround all white pixels in the input image.

Parameters :

image : ndarray

Binary input image. This array is cast to bool before processing.

Returns :

hull : ndarray of uint8

Binary image with pixels in convex hull set to 255.

References

[R44]http://blogs.mathworks.com/steve/2011/10/04/binary-image-convex-hull-algorithm-notes/

diamond

skimage.morphology.diamond(radius, dtype=<type 'numpy.uint8'>)

Generates a flat, diamond-shaped structuring element of a given radius. A pixel is part of the neighborhood (i.e. labeled 1) if the city block/manhattan distance between it and the center of the neighborhood is no greater than radius.

Parameters :

radius : int

The radius of the diamond-shaped structuring element.

dtype : data-type

The data type of the structuring element.

Returns :

selem : ndarray

The structuring element where elements of the neighborhood are 1 and 0 otherwise.

dilation

skimage.morphology.dilation(image, selem, out=None, shift_x=False, shift_y=False)

Return greyscale morphological dilation of an image.

Morphological dilation sets a pixel at (i,j) to the maximum over all pixels in the neighborhood centered at (i,j). Dilation enlarges bright regions and shrinks dark regions.

Parameters :

image : ndarray

Image array.

selem : ndarray

The neighborhood expressed as a 2-D array of 1’s and 0’s.

out : ndarray

The array to store the result of the morphology. If None, is passed, a new array will be allocated.

shift_x, shift_y : bool

shift structuring element about center point. This only affects eccentric structuring elements (i.e. selem with even numbered sides).

Returns :

dilated : uint8 array

The result of the morphological dilation.

Examples

>>> # Dilation enlarges bright regions
>>> from skimage.morphology import square
>>> bright_pixel = np.array([[0, 0, 0, 0, 0],
...                          [0, 0, 0, 0, 0],
...                          [0, 0, 1, 0, 0],
...                          [0, 0, 0, 0, 0],
...                          [0, 0, 0, 0, 0]], dtype=np.uint8)
>>> dilation(bright_pixel, square(3))
array([[0, 0, 0, 0, 0],
       [0, 1, 1, 1, 0],
       [0, 1, 1, 1, 0],
       [0, 1, 1, 1, 0],
       [0, 0, 0, 0, 0]], dtype='uint8')

disk

skimage.morphology.disk(radius, dtype=<type 'numpy.uint8'>)

Generates a flat, disk-shaped structuring element of a given radius. A pixel is within the neighborhood if the euclidean distance between it and the origin is no greater than a radius.

Parameters :

radius : int

The radius of the disk-shaped structuring element.

dtype : data-type

The data type of the structuring element.

Returns :

selem : ndarray

The structuring element where elements of the neighborhood are 1 and 0 otherwise.

erosion

skimage.morphology.erosion(image, selem, out=None, shift_x=False, shift_y=False)

Return greyscale morphological erosion of an image.

Morphological erosion sets a pixel at (i,j) to the minimum over all pixels in the neighborhood centered at (i,j). Erosion shrinks bright regions and enlarges dark regions.

Parameters :

image : ndarray

Image array.

selem : ndarray

The neighborhood expressed as a 2-D array of 1’s and 0’s.

out : ndarray

The array to store the result of the morphology. If None is passed, a new array will be allocated.

shift_x, shift_y : bool

shift structuring element about center point. This only affects eccentric structuring elements (i.e. selem with even numbered sides).

Returns :

eroded : uint8 array

The result of the morphological erosion.

Examples

>>> # Erosion shrinks bright regions
>>> from skimage.morphology import square
>>> bright_square = np.array([[0, 0, 0, 0, 0],
...                           [0, 1, 1, 1, 0],
...                           [0, 1, 1, 1, 0],
...                           [0, 1, 1, 1, 0],
...                           [0, 0, 0, 0, 0]], dtype=np.uint8)
>>> erosion(bright_square, square(3))
array([[0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0],
       [0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0]], dtype='uint8')

greyscale_black_top_hat

skimage.morphology.greyscale_black_top_hat(*args, **kwargs)

greyscale_close

skimage.morphology.greyscale_close(*args, **kwargs)

greyscale_dilate

skimage.morphology.greyscale_dilate(*args, **kwargs)

greyscale_erode

skimage.morphology.greyscale_erode(*args, **kwargs)

greyscale_open

skimage.morphology.greyscale_open(*args, **kwargs)

greyscale_white_top_hat

skimage.morphology.greyscale_white_top_hat(*args, **kwargs)

is_local_maximum

skimage.morphology.is_local_maximum(image, labels=None, footprint=None)

Return a boolean array of points that are local maxima

Parameters :

image: ndarray (2-D, 3-D, ...) :

intensity image

labels: ndarray, optional :

find maxima only within labels. Zero is reserved for background.

footprint: ndarray of bools, optional :

binary mask indicating the neighborhood to be examined footprint must be a matrix with odd dimensions, the center is taken to be the point in question.

Returns :

result: ndarray of bools :

mask that is True for pixels that are local maxima of image

Examples

>>> image = np.zeros((4, 4))
>>> image[1, 2] = 2
>>> image[3, 3] = 1
>>> image
array([[ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  2.,  0.],
       [ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  1.]])
>>> is_local_maximum(image)
array([[ True, False, False, False],
       [ True, False,  True, False],
       [ True, False, False, False],
       [ True,  True, False,  True]], dtype='bool')
>>> image = np.arange(16).reshape((4, 4))
>>> labels = np.array([[1, 2], [3, 4]])
>>> labels = np.repeat(np.repeat(labels, 2, axis=0), 2, axis=1)
>>> labels
array([[1, 1, 2, 2],
       [1, 1, 2, 2],
       [3, 3, 4, 4],
       [3, 3, 4, 4]])
>>> image
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])
>>> is_local_maximum(image, labels=labels)
array([[False, False, False, False],
       [False,  True, False,  True],
       [False, False, False, False],
       [False,  True, False,  True]], dtype='bool')

label

skimage.morphology.label()

Label connected regions of an integer array.

Two pixels are connected when they are neighbors and have the same value. They can be neighbors either in a 4- or 8-connected sense:

4-connectivity      8-connectivity

     [ ]           [ ]  [ ]  [ ]
      |               \  |  /
[ ]--[ ]--[ ]      [ ]--[ ]--[ ]
      |               /  |  \ 
     [ ]           [ ]  [ ]  [ ]
Parameters :

input : ndarray of dtype int

Image to label.

neighbors : {4, 8}, int

Whether to use 4- or 8-connectivity.

background : int

Consider all pixels with this value as background pixels, and label them as -1.

Returns :

labels : ndarray of dtype int

Labeled array, where all connected regions are assigned the same integer value.

Examples

>>> x = np.eye(3).astype(int)
>>> print x
[[1 0 0]
 [0 1 0]
 [0 0 1]]
>>> print m.label(x, neighbors=4)
[[0 1 1]
 [2 3 1]
 [2 2 4]]
>>> print m.label(x, neighbors=8)
[[0 1 1]
 [1 0 1]
 [1 1 0]]
>>> x = np.array([[1, 0, 0],
...               [1, 1, 5],
...               [0, 0, 0]])
>>> print m.label(x, background=0)
[[ 0 -1 -1]
 [ 0  0  1]
 [-1 -1 -1]]

medial_axis

skimage.morphology.medial_axis(image, mask=None, return_distance=False)

Compute the medial axis transform of a binary image

Parameters :

image : binary ndarray

mask : binary ndarray, optional

If a mask is given, only those elements with a true value in mask are used for computing the medial axis.

return_distance : bool, optional

If true, the distance transform is returned as well as the skeleton.

Returns :

out : ndarray of bools

Medial axis transform of the image

dist : ndarray of ints

Distance transform of the image (only returned if return_distance is True)

See also

skeletonize

Notes

This algorithm computes the medial axis transform of an image as the ridges of its distance transform.

The different steps of the algorithm are as follows
  • A lookup table is used, that assigns 0 or 1 to each configuration of the 3x3 binary square, whether the central pixel should be removed or kept. We want a point to be removed if it has more than one neighbor and if removing it does not change the number of connected components.
  • The distance transform to the background is computed, as well as the cornerness of the pixel.
  • The foreground (value of 1) points are ordered by the distance transform, then the cornerness.
  • A cython function is called to reduce the image to its skeleton. It processes pixels in the order determined at the previous step, and removes or maintains a pixel according to the lookup table. Because of the ordering, it is possible to process all pixels in only one pass.

Examples

>>> square = np.zeros((7, 7), dtype=np.uint8)
>>> square[1:-1, 2:-2] = 1
>>> square
array([[0, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 1, 1, 0, 0],
       [0, 0, 1, 1, 1, 0, 0],
       [0, 0, 1, 1, 1, 0, 0],
       [0, 0, 1, 1, 1, 0, 0],
       [0, 0, 1, 1, 1, 0, 0],
       [0, 0, 0, 0, 0, 0, 0]], dtype=uint8)
>>> morphology.medial_axis(square).astype(np.uint8)
array([[0, 0, 0, 0, 0, 0, 0],
       [0, 0, 1, 0, 1, 0, 0],
       [0, 0, 0, 1, 0, 0, 0],
       [0, 0, 0, 1, 0, 0, 0],
       [0, 0, 0, 1, 0, 0, 0],
       [0, 0, 1, 0, 1, 0, 0],
       [0, 0, 0, 0, 0, 0, 0]], dtype=uint8)

opening

skimage.morphology.opening(image, selem, out=None)

Return greyscale morphological opening of an image.

The morphological opening on an image is defined as an erosion followed by a dilation. Opening can remove small bright spots (i.e. “salt”) and connect small dark cracks. This tends to “open” up (dark) gaps between (bright) features.

Parameters :

image : ndarray

Image array.

selem : ndarray

The neighborhood expressed as a 2-D array of 1’s and 0’s.

out : ndarray

The array to store the result of the morphology. If None is passed, a new array will be allocated.

Returns :

opening : uint8 array

The result of the morphological opening.

Examples

>>> # Open up gap between two bright regions (but also shrink regions)
>>> from skimage.morphology import square
>>> bad_connection = np.array([[1, 0, 0, 0, 1],
...                            [1, 1, 0, 1, 1],
...                            [1, 1, 1, 1, 1],
...                            [1, 1, 0, 1, 1],
...                            [1, 0, 0, 0, 1]], dtype=np.uint8)
>>> opening(bad_connection, square(3))
array([[0, 0, 0, 0, 0],
       [1, 1, 0, 1, 1],
       [1, 1, 0, 1, 1],
       [1, 1, 0, 1, 1],
       [0, 0, 0, 0, 0]], dtype='uint8')

rectangle

skimage.morphology.rectangle(width, height, dtype=<type 'numpy.uint8'>)

Generates a flat, rectangular-shaped structuring element of a given width and height. Every pixel in the rectangle belongs to the neighboorhood.

Parameters :

width : int

The width of the rectangle

height : int

The height of the rectangle

Returns :

selem : ndarray

A structuring element consisting only of ones, i.e. every pixel belongs to the neighborhood.

skeletonize

skimage.morphology.skeletonize(image)

Return the skeleton of a binary image.

Thinning is used to reduce each connected component in a binary image to a single-pixel wide skeleton.

Parameters :

image : numpy.ndarray

A binary image containing the objects to be skeletonized. ‘1’ represents foreground, and ‘0’ represents background. It also accepts arrays of boolean values where True is foreground.

Returns :

skeleton : ndarray

A matrix containing the thinned image.

See also

medial_axis

Notes

The algorithm [1] works by making successive passes of the image, removing pixels on object borders. This continues until no more pixels can be removed. The image is correlated with a mask that assigns each pixel a number in the range [0...255] corresponding to each possible pattern of its 8 neighbouring pixels. A look up table is then used to assign the pixels a value of 0, 1, 2 or 3, which are selectively removed during the iterations.

Note that this algorithm will give different results than a medial axis transform, which is also often referred to as “skeletonization”.

References

[R45]A fast parallel algorithm for thinning digital patterns, T. Y. ZHANG and C. Y. SUEN, Communications of the ACM, March 1984, Volume 27, Number 3

Examples

>>> X, Y = np.ogrid[0:9, 0:9]
>>> ellipse = (1./3 * (X - 4)**2 + (Y - 4)**2 < 3**2).astype(np.uint8)
>>> ellipse
array([[0, 0, 0, 1, 1, 1, 0, 0, 0],
       [0, 0, 1, 1, 1, 1, 1, 0, 0],
       [0, 0, 1, 1, 1, 1, 1, 0, 0],
       [0, 0, 1, 1, 1, 1, 1, 0, 0],
       [0, 0, 1, 1, 1, 1, 1, 0, 0],
       [0, 0, 1, 1, 1, 1, 1, 0, 0],
       [0, 0, 1, 1, 1, 1, 1, 0, 0],
       [0, 0, 1, 1, 1, 1, 1, 0, 0],
       [0, 0, 0, 1, 1, 1, 0, 0, 0]], dtype=uint8)
>>> skel = skeletonize(ellipse)
>>> skel
array([[0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 1, 0, 0, 0, 0],
       [0, 0, 0, 0, 1, 0, 0, 0, 0],
       [0, 0, 0, 0, 1, 0, 0, 0, 0],
       [0, 0, 0, 0, 1, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8)

square

skimage.morphology.square(width, dtype=<type 'numpy.uint8'>)

Generates a flat, square-shaped structuring element. Every pixel along the perimeter has a chessboard distance no greater than radius (radius=floor(width/2)) pixels.

Parameters :

width : int

The width and height of the square

Returns :

selem : ndarray

A structuring element consisting only of ones, i.e. every pixel belongs to the neighborhood.

watershed

skimage.morphology.watershed(image, markers, connectivity=None, offset=None, mask=None)

Return a matrix labeled using the watershed segmentation algorithm

Parameters :

image: ndarray (2-D, 3-D, ...) of integers :

Data array where the lowest value points are labeled first.

markers: ndarray of the same shape as `image` :

An array marking the basins with the values to be assigned in the label matrix. Zero means not a marker. This array should be of an integer type.

connectivity: ndarray, optional :

An array with the same number of dimensions as image whose non-zero elements indicate neighbors for connection. Following the scipy convention, default is a one-connected array of the dimension of the image.

offset: array_like of shape image.ndim, optional :

offset of the connectivity (one offset per dimension)

mask: ndarray of bools or 0s and 1s, optional :

Array of same shape as image. Only points at which mask == True will be labeled.

Returns :

out: ndarray :

A labeled matrix of the same type and shape as markers

See also

skimage.segmentation.random_walker
random walker segmentation A segmentation algorithm based on anisotropic diffusion, usually slower than the watershed but with good results on noisy data and boundaries with holes.

Notes

This function implements a watershed algorithm [R46]_that apportions pixels into marked basins. The algorithm uses a priority queue to hold the pixels with the metric for the priority queue being pixel value, then the time of entry into the queue - this settles ties in favor of the closest marker.

Some ideas taken from Soille, “Automated Basin Delineation from Digital Elevation Models Using Mathematical Morphology”, Signal Processing 20 (1990) 171-182

The most important insight in the paper is that entry time onto the queue solves two problems: a pixel should be assigned to the neighbor with the largest gradient or, if there is no gradient, pixels on a plateau should be split between markers on opposite sides.

This implementation converts all arguments to specific, lowest common denominator types, then passes these to a C algorithm.

Markers can be determined manually, or automatically using for example the local minima of the gradient of the image, or the local maxima of the distance function to the background for separating overlapping objects (see example).

References

[R46]http://en.wikipedia.org/wiki/Watershed_%28image_processing%29
[R47]http://cmm.ensmp.fr/~beucher/wtshed.html

Examples

The watershed algorithm is very useful to separate overlapping objects

>>> # Generate an initial image with two overlapping circles
>>> x, y = np.indices((80, 80))
>>> x1, y1, x2, y2 = 28, 28, 44, 52
>>> r1, r2 = 16, 20
>>> mask_circle1 = (x - x1)**2 + (y - y1)**2 < r1**2
>>> mask_circle2 = (x - x2)**2 + (y - y2)**2 < r2**2
>>> image = np.logical_or(mask_circle1, mask_circle2)
>>> # Now we want to separate the two objects in image
>>> # Generate the markers as local maxima of the distance
>>> # to the background
>>> from scipy import ndimage
>>> distance = ndimage.distance_transform_edt(image)
>>> local_maxi = is_local_maximum(distance, image, np.ones((3, 3)))
>>> markers = ndimage.label(local_maxi)[0]
>>> labels = watershed(-distance, markers, mask=image)

The algorithm works also for 3-D images, and can be used for example to separate overlapping spheres.

white_tophat

skimage.morphology.white_tophat(image, selem, out=None)

Return white top hat of an image.

The white top hat of an image is defined as the image minus its morphological opening. This operation returns the bright spots of the image that are smaller than the structuring element.

Parameters :

image : ndarray

Image array.

selem : ndarray

The neighborhood expressed as a 2-D array of 1’s and 0’s.

out : ndarray

The array to store the result of the morphology. If None is passed, a new array will be allocated.

Returns :

opening : uint8 array

The result of the morphological white top hat.

Examples

>>> # Subtract grey background from bright peak
>>> from skimage.morphology import square
>>> bright_on_grey = np.array([[2, 3, 3, 3, 2],
...                            [3, 4, 5, 4, 3],
...                            [3, 5, 9, 5, 3],
...                            [3, 4, 5, 4, 3],
...                            [2, 3, 3, 3, 2]], dtype=np.uint8)
>>> white_tophat(bright_on_grey, square(3))
array([[0, 0, 0, 0, 0],
       [0, 0, 1, 0, 0],
       [0, 1, 5, 1, 0],
       [0, 0, 1, 0, 0],
       [0, 0, 0, 0, 0]], dtype='uint8')