mirror of
https://github.com/wassname/scikit-image.git
synced 2026-06-30 20:18:47 +08:00
Add default structuring element to morphology
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import warnings
|
||||
import numpy as np
|
||||
from scipy import ndimage
|
||||
from .selem import _default_selem
|
||||
|
||||
|
||||
def binary_erosion(image, selem, out=None):
|
||||
def binary_erosion(image, selem=None, out=None):
|
||||
"""Return fast binary morphological erosion of an image.
|
||||
|
||||
This function returns the same result as greyscale erosion but performs
|
||||
@@ -29,6 +30,11 @@ def binary_erosion(image, selem, out=None):
|
||||
The result of the morphological erosion with values in ``[0, 1]``.
|
||||
|
||||
"""
|
||||
|
||||
# Default structure element
|
||||
if selem is None:
|
||||
selem = _default_selem(image.ndim)
|
||||
|
||||
selem = (selem != 0)
|
||||
selem_sum = np.sum(selem)
|
||||
|
||||
@@ -45,7 +51,7 @@ def binary_erosion(image, selem, out=None):
|
||||
return np.equal(conv, selem_sum, out=out)
|
||||
|
||||
|
||||
def binary_dilation(image, selem, out=None):
|
||||
def binary_dilation(image, selem=None, out=None):
|
||||
"""Return fast binary morphological dilation of an image.
|
||||
|
||||
This function returns the same result as greyscale dilation but performs
|
||||
@@ -72,6 +78,11 @@ def binary_dilation(image, selem, out=None):
|
||||
The result of the morphological dilation with values in ``[0, 1]``.
|
||||
|
||||
"""
|
||||
|
||||
# Default structure element
|
||||
if selem is None:
|
||||
selem = _default_selem(image.ndim)
|
||||
|
||||
selem = (selem != 0)
|
||||
|
||||
if np.sum(selem) <= 255:
|
||||
@@ -87,7 +98,7 @@ def binary_dilation(image, selem, out=None):
|
||||
return np.not_equal(conv, 0, out=out)
|
||||
|
||||
|
||||
def binary_opening(image, selem, out=None):
|
||||
def binary_opening(image, selem=None, out=None):
|
||||
"""Return fast binary morphological opening of an image.
|
||||
|
||||
This function returns the same result as greyscale opening but performs
|
||||
@@ -119,7 +130,7 @@ def binary_opening(image, selem, out=None):
|
||||
return out
|
||||
|
||||
|
||||
def binary_closing(image, selem, out=None):
|
||||
def binary_closing(image, selem=None, out=None):
|
||||
"""Return fast binary morphological closing of an image.
|
||||
|
||||
This function returns the same result as greyscale closing but performs
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import warnings
|
||||
from skimage import img_as_ubyte
|
||||
from scipy import ndimage
|
||||
from .selem import _default_selem
|
||||
|
||||
|
||||
from . import cmorph
|
||||
|
||||
@@ -8,7 +11,7 @@ __all__ = ['erosion', 'dilation', 'opening', 'closing', 'white_tophat',
|
||||
'black_tophat']
|
||||
|
||||
|
||||
def erosion(image, selem, out=None, shift_x=False, shift_y=False):
|
||||
def erosion(image, selem=None, 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
|
||||
@@ -21,7 +24,7 @@ def erosion(image, selem, out=None, shift_x=False, shift_y=False):
|
||||
Image array.
|
||||
selem : ndarray
|
||||
The neighborhood expressed as a 2-D array of 1's and 0's.
|
||||
out : ndarray
|
||||
out : ndarrays
|
||||
The array to store the result of the morphology. If None is
|
||||
passed, a new array will be allocated.
|
||||
shift_x, shift_y : bool
|
||||
@@ -52,6 +55,10 @@ def erosion(image, selem, out=None, shift_x=False, shift_y=False):
|
||||
|
||||
"""
|
||||
|
||||
# Default structure element
|
||||
if selem is None:
|
||||
selem = _default_selem(image.ndim)
|
||||
|
||||
if image is out:
|
||||
raise NotImplementedError("In-place erosion not supported!")
|
||||
image = img_as_ubyte(image)
|
||||
@@ -60,7 +67,7 @@ def erosion(image, selem, out=None, shift_x=False, shift_y=False):
|
||||
shift_x=shift_x, shift_y=shift_y)
|
||||
|
||||
|
||||
def dilation(image, selem, out=None, shift_x=False, shift_y=False):
|
||||
def dilation(image, selem=None, 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
|
||||
@@ -105,6 +112,10 @@ def dilation(image, selem, out=None, shift_x=False, shift_y=False):
|
||||
|
||||
"""
|
||||
|
||||
# Default structure element
|
||||
if selem is None:
|
||||
selem = _default_selem(image.ndim)
|
||||
|
||||
if image is out:
|
||||
raise NotImplementedError("In-place dilation not supported!")
|
||||
image = img_as_ubyte(image)
|
||||
@@ -113,7 +124,7 @@ def dilation(image, selem, out=None, shift_x=False, shift_y=False):
|
||||
shift_x=shift_x, shift_y=shift_y)
|
||||
|
||||
|
||||
def opening(image, selem, out=None):
|
||||
def opening(image, selem=None, out=None):
|
||||
"""Return greyscale morphological opening of an image.
|
||||
|
||||
The morphological opening on an image is defined as an erosion followed by
|
||||
@@ -154,7 +165,11 @@ def opening(image, selem, out=None):
|
||||
[0, 0, 0, 0, 0]], dtype=uint8)
|
||||
|
||||
"""
|
||||
|
||||
|
||||
# Default structure element
|
||||
if selem is None:
|
||||
selem = _default_selem(image.ndim)
|
||||
|
||||
h, w = selem.shape
|
||||
shift_x = True if (w % 2) == 0 else False
|
||||
shift_y = True if (h % 2) == 0 else False
|
||||
@@ -164,7 +179,7 @@ def opening(image, selem, out=None):
|
||||
return out
|
||||
|
||||
|
||||
def closing(image, selem, out=None):
|
||||
def closing(image, selem=None, out=None):
|
||||
"""Return greyscale morphological closing of an image.
|
||||
|
||||
The morphological closing on an image is defined as a dilation followed by
|
||||
@@ -206,6 +221,10 @@ def closing(image, selem, out=None):
|
||||
|
||||
"""
|
||||
|
||||
# Default structure element
|
||||
if selem is None:
|
||||
selem = _default_selem(image.ndim)
|
||||
|
||||
h, w = selem.shape
|
||||
shift_x = True if (w % 2) == 0 else False
|
||||
shift_y = True if (h % 2) == 0 else False
|
||||
@@ -215,7 +234,7 @@ def closing(image, selem, out=None):
|
||||
return out
|
||||
|
||||
|
||||
def white_tophat(image, selem, out=None):
|
||||
def white_tophat(image, selem=None, out=None):
|
||||
"""Return white top hat of an image.
|
||||
|
||||
The white top hat of an image is defined as the image minus its
|
||||
@@ -254,7 +273,12 @@ def white_tophat(image, selem, out=None):
|
||||
[0, 0, 1, 0, 0],
|
||||
[0, 0, 0, 0, 0]], dtype=uint8)
|
||||
|
||||
"""
|
||||
"""
|
||||
|
||||
# Default structure element
|
||||
if selem is None:
|
||||
selem = _default_selem(image.ndim)
|
||||
|
||||
if image is out:
|
||||
raise NotImplementedError("Cannot perform white top hat in place.")
|
||||
|
||||
@@ -263,7 +287,7 @@ def white_tophat(image, selem, out=None):
|
||||
return out
|
||||
|
||||
|
||||
def black_tophat(image, selem, out=None):
|
||||
def black_tophat(image, selem=None, out=None):
|
||||
"""Return black top hat of an image.
|
||||
|
||||
The black top hat of an image is defined as its morphological closing minus
|
||||
@@ -305,6 +329,10 @@ def black_tophat(image, selem, out=None):
|
||||
|
||||
"""
|
||||
|
||||
# Default structure element
|
||||
if selem is None:
|
||||
selem = _default_selem(image.ndim)
|
||||
|
||||
if image is out:
|
||||
raise NotImplementedError("Cannot perform white top hat in place.")
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
from scipy import ndimage
|
||||
|
||||
|
||||
def square(width, dtype=np.uint8):
|
||||
@@ -290,3 +291,23 @@ def star(a, dtype=np.uint8):
|
||||
selem = selem_square + selem_rotated
|
||||
selem[selem > 0] = 1
|
||||
return selem.astype(dtype)
|
||||
|
||||
|
||||
def _default_selem(ndim):
|
||||
"""
|
||||
Generates a cross-shaped structuring element (connectivity=1). This is the
|
||||
default structuring element (selem) if no selem was specified.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
ndim : int
|
||||
Number of dimensions of the image.
|
||||
|
||||
Returns
|
||||
-------
|
||||
selem : ndarray
|
||||
The structuring element where elements of the neighborhood
|
||||
are 1 and 0 otherwise.
|
||||
|
||||
"""
|
||||
return ndimage.morphology.generate_binary_structure(ndim, 1)
|
||||
@@ -64,5 +64,30 @@ def test_out_argument():
|
||||
testing.assert_(np.any(out != out_saved))
|
||||
testing.assert_array_equal(out, func(img, strel))
|
||||
|
||||
def test_default_selem():
|
||||
|
||||
functions = [binary.binary_erosion, binary.binary_dilation,
|
||||
binary.binary_opening, binary.binary_closing]
|
||||
|
||||
strel = selem.diamond(radius=1)
|
||||
image = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 0, 0, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 0, 0, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 0, 0, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], np.uint8)
|
||||
|
||||
for function in functions:
|
||||
im_expected = function(image, strel)
|
||||
im_test = function(image)
|
||||
yield testing.assert_array_equal, im_expected, im_test
|
||||
|
||||
if __name__ == '__main__':
|
||||
testing.run_module_suite()
|
||||
|
||||
@@ -119,7 +119,33 @@ class TestEccentricStructuringElements():
|
||||
tophat = grey.black_tophat(self.white_pixel, s)
|
||||
assert np.all(tophat == 0)
|
||||
|
||||
def test_default_selem():
|
||||
|
||||
functions = [grey.erosion, grey.dilation,
|
||||
grey.opening, grey.closing,
|
||||
grey.white_tophat, grey.black_tophat]
|
||||
|
||||
strel = selem.diamond(radius=1)
|
||||
image = np.array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 0, 0, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 0, 0, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 0, 0, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], np.uint8)
|
||||
|
||||
for function in functions:
|
||||
im_expected = function(image, strel)
|
||||
im_test = function(image)
|
||||
yield testing.assert_array_equal, im_expected, im_test
|
||||
|
||||
|
||||
class TestDTypes():
|
||||
|
||||
def setUp(self):
|
||||
|
||||
Reference in New Issue
Block a user