mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-28 11:25:42 +08:00
Merge pull request #669 from ankit-maverick/octagon
Adding Octagon structural element
This commit is contained in:
@@ -4,7 +4,8 @@ from .grey import (erosion, dilation, opening, closing, white_tophat,
|
||||
black_tophat, greyscale_erode, greyscale_dilate,
|
||||
greyscale_open, greyscale_close, greyscale_white_top_hat,
|
||||
greyscale_black_top_hat)
|
||||
from .selem import square, rectangle, diamond, disk, cube, octahedron, ball
|
||||
from .selem import (square, rectangle, diamond, disk, cube, octahedron, ball,
|
||||
octagon, star)
|
||||
from .ccomp import label
|
||||
from .watershed import watershed, is_local_maximum
|
||||
from ._skeletonize import skeletonize, medial_axis
|
||||
@@ -36,6 +37,7 @@ __all__ = ['binary_erosion',
|
||||
'cube',
|
||||
'octahedron',
|
||||
'ball',
|
||||
'octagon',
|
||||
'label',
|
||||
'watershed',
|
||||
'is_local_maximum',
|
||||
|
||||
+119
-30
@@ -15,18 +15,18 @@ def square(width, dtype=np.uint8):
|
||||
Parameters
|
||||
----------
|
||||
width : int
|
||||
The width and height of the square
|
||||
The width and height of the square
|
||||
|
||||
Other Parameters
|
||||
----------------
|
||||
dtype : data-type
|
||||
The data type of the structuring element.
|
||||
The data type of the structuring element.
|
||||
|
||||
Returns
|
||||
-------
|
||||
selem : ndarray
|
||||
A structuring element consisting only of ones, i.e. every
|
||||
pixel belongs to the neighborhood.
|
||||
A structuring element consisting only of ones, i.e. every
|
||||
pixel belongs to the neighborhood.
|
||||
|
||||
"""
|
||||
return np.ones((width, width), dtype=dtype)
|
||||
@@ -41,21 +41,20 @@ def rectangle(width, height, dtype=np.uint8):
|
||||
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
|
||||
----------------
|
||||
dtype : data-type
|
||||
The data type of the structuring element.
|
||||
The data type of the structuring element.
|
||||
|
||||
Returns
|
||||
-------
|
||||
selem : ndarray
|
||||
A structuring element consisting only of ones, i.e. every
|
||||
pixel belongs to the neighborhood.
|
||||
A structuring element consisting only of ones, i.e. every
|
||||
pixel belongs to the neighborhood.
|
||||
|
||||
"""
|
||||
return np.ones((width, height), dtype=dtype)
|
||||
@@ -71,17 +70,19 @@ def diamond(radius, dtype=np.uint8):
|
||||
Parameters
|
||||
----------
|
||||
radius : int
|
||||
The radius of the diamond-shaped structuring element.
|
||||
The radius of the diamond-shaped structuring element.
|
||||
|
||||
Other Parameters
|
||||
----------------
|
||||
dtype : data-type
|
||||
The data type of the structuring element.
|
||||
The data type of the structuring element.
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
||||
selem : ndarray
|
||||
The structuring element where elements of the neighborhood
|
||||
are 1 and 0 otherwise.
|
||||
The structuring element where elements of the neighborhood
|
||||
are 1 and 0 otherwise.
|
||||
"""
|
||||
half = radius
|
||||
(I, J) = np.meshgrid(range(0, radius * 2 + 1), range(0, radius * 2 + 1))
|
||||
@@ -98,16 +99,18 @@ def disk(radius, dtype=np.uint8):
|
||||
Parameters
|
||||
----------
|
||||
radius : int
|
||||
The radius of the disk-shaped structuring element.
|
||||
The radius of the disk-shaped structuring element.
|
||||
|
||||
Other Parameters
|
||||
----------------
|
||||
dtype : data-type
|
||||
The data type of the structuring element.
|
||||
The data type of the structuring element.
|
||||
|
||||
Returns
|
||||
-------
|
||||
selem : ndarray
|
||||
The structuring element where elements of the neighborhood
|
||||
are 1 and 0 otherwise.
|
||||
The structuring element where elements of the neighborhood
|
||||
are 1 and 0 otherwise.
|
||||
"""
|
||||
L = np.linspace(-radius, radius, 2 * radius + 1)
|
||||
(X, Y) = np.meshgrid(L, L)
|
||||
@@ -125,18 +128,18 @@ def cube(width, dtype=np.uint8):
|
||||
Parameters
|
||||
----------
|
||||
width : int
|
||||
The width, height and depth of the cube
|
||||
The width, height and depth of the cube
|
||||
|
||||
Other Parameters
|
||||
----------------
|
||||
dtype : data-type
|
||||
The data type of the structuring element.
|
||||
The data type of the structuring element.
|
||||
|
||||
Returns
|
||||
-------
|
||||
selem : ndarray
|
||||
A structuring element consisting only of ones, i.e. every
|
||||
pixel belongs to the neighborhood.
|
||||
A structuring element consisting only of ones, i.e. every
|
||||
pixel belongs to the neighborhood.
|
||||
|
||||
"""
|
||||
return np.ones((width, width, width), dtype=dtype)
|
||||
@@ -153,17 +156,19 @@ def octahedron(radius, dtype=np.uint8):
|
||||
Parameters
|
||||
----------
|
||||
radius : int
|
||||
The radius of the octahedron-shaped structuring element.
|
||||
The radius of the octahedron-shaped structuring element.
|
||||
|
||||
Other Parameters
|
||||
----------------
|
||||
dtype : data-type
|
||||
The data type of the structuring element.
|
||||
The data type of the structuring element.
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
||||
selem : ndarray
|
||||
The structuring element where elements of the neighborhood
|
||||
are 1 and 0 otherwise.
|
||||
The structuring element where elements of the neighborhood
|
||||
are 1 and 0 otherwise.
|
||||
"""
|
||||
# note that in contrast to diamond(), this method allows non-integer radii
|
||||
n = 2 * radius + 1
|
||||
@@ -184,16 +189,18 @@ def ball(radius, dtype=np.uint8):
|
||||
Parameters
|
||||
----------
|
||||
radius : int
|
||||
The radius of the ball-shaped structuring element.
|
||||
The radius of the ball-shaped structuring element.
|
||||
|
||||
Other Parameters
|
||||
----------------
|
||||
dtype : data-type
|
||||
The data type of the structuring element.
|
||||
The data type of the structuring element.
|
||||
|
||||
Returns
|
||||
-------
|
||||
selem : ndarray
|
||||
The structuring element where elements of the neighborhood
|
||||
are 1 and 0 otherwise.
|
||||
The structuring element where elements of the neighborhood
|
||||
are 1 and 0 otherwise.
|
||||
"""
|
||||
n = 2 * radius + 1
|
||||
Z, Y, X = np.mgrid[ -radius:radius:n*1j,
|
||||
@@ -201,3 +208,85 @@ def ball(radius, dtype=np.uint8):
|
||||
-radius:radius:n*1j]
|
||||
s = X**2 + Y**2 + Z**2
|
||||
return np.array(s <= radius * radius, dtype=dtype)
|
||||
|
||||
|
||||
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
|
||||
and hence the widths and heights are equal.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
m : int
|
||||
The size of the horizontal and vertical sides.
|
||||
n : int
|
||||
The height or width of the slanted sides.
|
||||
|
||||
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.
|
||||
|
||||
"""
|
||||
from . import convex_hull_image
|
||||
selem = np.zeros((m + 2*n, m + 2*n))
|
||||
selem[0, n] = 1
|
||||
selem[n, 0] = 1
|
||||
selem[0, m + n -1] = 1
|
||||
selem[m + n - 1, 0] = 1
|
||||
selem[-1, n] = 1
|
||||
selem[n, -1] = 1
|
||||
selem[-1, m + n - 1] = 1
|
||||
selem[m + n - 1, -1] = 1
|
||||
selem = convex_hull_image(selem).astype(dtype)
|
||||
return selem
|
||||
|
||||
|
||||
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.
|
||||
The slanted sides are 45 or 135 degrees to the horizontal axis.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
a : int
|
||||
Parameter deciding the size of the star structural element. The side
|
||||
of the square array returned is `2*a + 1 + 2*floor(a / 2)`.
|
||||
|
||||
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.
|
||||
|
||||
"""
|
||||
from . import convex_hull_image
|
||||
if a == 1:
|
||||
bfilter = np.zeros((3, 3), dtype)
|
||||
bfilter[:] = 1
|
||||
return bfilter
|
||||
m = 2 * a + 1
|
||||
n = a / 2
|
||||
selem_square = np.zeros((m + 2 * n, m + 2 * n))
|
||||
selem_square[n: m + n, n: m + n] = 1
|
||||
c = (m + 2 * n - 1) / 2
|
||||
selem_rotated = np.zeros((m + 2 * n, m + 2 * n))
|
||||
selem_rotated[0, c] = selem_rotated[-1, c] = selem_rotated[c, 0] = selem_rotated[c, -1] = 1
|
||||
selem_rotated = convex_hull_image(selem_rotated).astype(int)
|
||||
selem = selem_square + selem_rotated
|
||||
selem[selem > 0] = 1
|
||||
return selem.astype(dtype)
|
||||
|
||||
@@ -66,6 +66,48 @@ class TestSElem():
|
||||
def test_selem_octahedron(self):
|
||||
self.strel_worker_3d("diamond-matlab-output.npz", selem.octahedron)
|
||||
|
||||
def test_selem_octagon(self):
|
||||
expected_mask1 = np.array([[0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0]], dtype=np.uint8)
|
||||
actual_mask1 = selem.octagon(5, 3)
|
||||
expected_mask2 = np.array([[0, 1, 0],
|
||||
[1, 1, 1],
|
||||
[0, 1, 0]], dtype=np.uint8)
|
||||
actual_mask2 = selem.octagon(1, 1)
|
||||
assert_equal(expected_mask1, actual_mask1)
|
||||
assert_equal(expected_mask2, actual_mask2)
|
||||
|
||||
def test_selem_star(self):
|
||||
expected_mask1 = np.array([[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||
[0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]], dtype=np.uint8)
|
||||
actual_mask1 = selem.star(4)
|
||||
expected_mask2 = np.array([[1, 1, 1],
|
||||
[1, 1, 1],
|
||||
[1, 1, 1]], dtype=np.uint8)
|
||||
actual_mask2 = selem.star(1)
|
||||
assert_equal(expected_mask1, actual_mask1)
|
||||
assert_equal(expected_mask2, actual_mask2)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
np.testing.run_module_suite()
|
||||
|
||||
Reference in New Issue
Block a user