Merge pull request #1298 from pratapvardhan/morph-selem

Morph selem ellipse structuring element
This commit is contained in:
Johannes Schönberger
2014-12-16 12:21:10 +01:00
2 changed files with 109 additions and 44 deletions
+90 -44
View File
@@ -5,18 +5,18 @@
import numpy as np
from scipy import ndimage
from skimage import draw
def square(width, dtype=np.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.
"""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
The width and height of the square.
Other Parameters
----------------
@@ -34,17 +34,17 @@ def square(width, dtype=np.uint8):
def rectangle(width, height, dtype=np.uint8):
"""
Generates a flat, rectangular-shaped structuring element of a
given width and height. Every pixel in the rectangle belongs
to the neighboorhood.
"""Generates a flat, rectangular-shaped structuring element.
Every pixel in the rectangle generated for a given width and given height
belongs to the neighboorhood.
Parameters
----------
width : int
The width of the rectangle
The width of the rectangle.
height : int
The height of the rectangle
The height of the rectangle.
Other Parameters
----------------
@@ -62,11 +62,11 @@ def rectangle(width, height, dtype=np.uint8):
def diamond(radius, dtype=np.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.
"""Generates a flat, diamond-shaped structuring element.
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
----------
@@ -92,8 +92,8 @@ def diamond(radius, dtype=np.uint8):
def disk(radius, dtype=np.uint8):
"""
Generates a flat, disk-shaped structuring element of a given radius.
"""Generates a flat, disk-shaped structuring element.
A pixel is within the neighborhood if the euclidean distance between
it and the origin is no greater than radius.
@@ -118,16 +118,60 @@ def disk(radius, dtype=np.uint8):
return np.array((X ** 2 + Y ** 2) <= radius ** 2, dtype=dtype)
def cube(width, dtype=np.uint8):
def ellipse(width, height, dtype=np.uint8):
"""Generates a flat, ellipse-shaped structuring element.
Every pixel along the perimeter of ellipse satisfies
the equation ``(x/width+1)**2 + (y/height+1)**2 = 1``.
Parameters
----------
width : int
The width of the ellipse-shaped structuring element.
height : int
The height of the ellipse-shaped structuring element.
Other Parameters
----------------
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.
Examples
--------
>>> from skimage.morphology import selem
>>> selem.ellipse(5, 3)
array([[0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0]], dtype=uint8)
"""
Generates a cube-shaped structuring element (the 3D equivalent of
a square). Every pixel along the perimeter has a chessboard distance
selem = np.zeros((2 * height + 1, 2 * width + 1), dtype=dtype)
rows, cols = draw.ellipse(height, width, height + 1, width + 1)
selem[rows, cols] = 1
return selem
def cube(width, dtype=np.uint8):
""" Generates a cube-shaped structuring element.
This is the 3D equivalent of a square.
Every pixel along the perimeter has a chessboard distance
no greater than radius (radius=floor(width/2)) pixels.
Parameters
----------
width : int
The width, height and depth of the cube
The width, height and depth of the cube.
Other Parameters
----------------
@@ -145,12 +189,12 @@ def cube(width, dtype=np.uint8):
def octahedron(radius, dtype=np.uint8):
"""
Generates a octahedron-shaped structuring element of a given radius
(the 3D equivalent of a diamond). 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.
"""Generates a octahedron-shaped structuring element.
This is the 3D equivalent of a diamond.
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
----------
@@ -179,11 +223,11 @@ def octahedron(radius, dtype=np.uint8):
def ball(radius, dtype=np.uint8):
"""
Generates a ball-shaped structuring element of a given radius (the
3D equivalent of a disk). A pixel is within the neighborhood if the
euclidean distance between it and the origin is no greater than
radius.
"""Generates a ball-shaped structuring element.
This is the 3D equivalent of a disk.
A pixel is within the neighborhood if the euclidean distance between
it and the origin is no greater than radius.
Parameters
----------
@@ -210,10 +254,11 @@ def ball(radius, dtype=np.uint8):
def octagon(m, n, dtype=np.uint8):
"""
Generates an octagon shaped structuring element with a given size of
horizontal and vertical sides and a given height or width of slanted
sides. The slanted sides are 45 or 135 degrees to the horizontal axis
"""Generates an octagon shaped structuring element.
For a given size of (m) horizontal and vertical sides
and a given (n) height or width of slanted sides octagon is generated.
The slanted sides are 45 or 135 degrees to the horizontal axis
and hence the widths and heights are equal.
Parameters
@@ -250,9 +295,10 @@ def octagon(m, n, dtype=np.uint8):
def star(a, dtype=np.uint8):
"""
Generates a star shaped structuring element that has 8 vertices and is an
overlap of square of size `2*a + 1` with its 45 degree rotated version.
"""Generates a star shaped structuring element.
Start has 8 vertices and is an overlap of square of size `2*a + 1`
with its 45 degree rotated version.
The slanted sides are 45 or 135 degrees to the horizontal axis.
Parameters
@@ -298,9 +344,9 @@ def star(a, dtype=np.uint8):
def _default_selem(ndim):
"""
Generates a cross-shaped structuring element (connectivity=1). This is the
default structuring element (selem) if no selem was specified.
"""Generates a cross-shaped structuring element (connectivity=1).
This is the default structuring element (selem) if no selem was specified.
Parameters
----------
+19
View File
@@ -102,6 +102,25 @@ class TestSElem():
assert_equal(expected_mask1, actual_mask1)
assert_equal(expected_mask2, actual_mask2)
def test_selem_ellipse(self):
"""Test ellipse structuring elements"""
expected_mask1 = np.array([[0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0]], dtype=np.uint8)
actual_mask1 = selem.ellipse(5, 3)
expected_mask2 = np.array([[1, 1, 1],
[1, 1, 1],
[1, 1, 1]], dtype=np.uint8)
actual_mask2 = selem.ellipse(1, 1)
assert_equal(expected_mask1, actual_mask1)
assert_equal(expected_mask2, actual_mask2)
assert_equal(expected_mask1, selem.ellipse(3, 5).T)
assert_equal(expected_mask2, selem.ellipse(1, 1).T)
def test_selem_star(self):
"""Test star structuring elements"""
expected_mask1 = np.array([[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],