| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- """
- Binary morphological operations
- """
- import warnings
- import numpy as np
- from scipy import ndimage as ndi
- from .footprints import _footprint_is_sequence, pad_footprint
- from .misc import default_footprint
- from .._shared.utils import deprecate_func
- def _iterate_binary_func(binary_func, image, footprint, out, border_value):
- """Helper to call `binary_func` for each footprint in a sequence.
- binary_func is a binary morphology function that accepts "structure",
- "output" and "iterations" keyword arguments
- (e.g. `scipy.ndimage.binary_erosion`).
- """
- fp, num_iter = footprint[0]
- binary_func(
- image, structure=fp, output=out, iterations=num_iter, border_value=border_value
- )
- for fp, num_iter in footprint[1:]:
- # Note: out.copy() because the computation cannot be in-place!
- # SciPy <= 1.7 did not automatically make a copy if needed.
- binary_func(
- out.copy(),
- structure=fp,
- output=out,
- iterations=num_iter,
- border_value=border_value,
- )
- return out
- # The default_footprint decorator provides a diamond footprint as
- # default with the same dimension as the input image and size 3 along each
- # axis.
- @default_footprint
- @deprecate_func(
- deprecated_version="0.26",
- removed_version="0.28",
- hint="Use `skimage.morphology.erosion` instead. "
- "Note the pixel shift by 1 for even-sized footprints (see docstring notes).",
- )
- def binary_erosion(image, footprint=None, out=None, *, mode='ignore'):
- """Return fast binary morphological erosion of an image.
- This function returns the same result as grayscale erosion but performs
- faster for binary images.
- 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
- Binary input image.
- footprint : ndarray or tuple, optional
- The neighborhood expressed as a 2-D array of 1's and 0's.
- If None, use a cross-shaped footprint (connectivity=1). The footprint
- can also be provided as a sequence of smaller footprints as described
- in the notes below.
- out : ndarray of bool, optional
- The array to store the result of the morphology. If None is
- passed, a new array will be allocated.
- mode : str, optional
- The `mode` parameter determines how the array borders are handled.
- Valid modes are: 'max', 'min', 'ignore'.
- If 'max' or 'ignore', pixels outside the image domain are assumed
- to be `True`, which causes them to not influence the result.
- Default is 'ignore'.
- .. versionadded:: 0.23
- `mode` was added in 0.23.
- Returns
- -------
- eroded : ndarray of bool or uint
- The result of the morphological erosion taking values in
- ``[False, True]``.
- Notes
- -----
- The footprint can also be a provided as a sequence of 2-tuples where the
- first element of each 2-tuple is a footprint ndarray and the second element
- is an integer describing the number of times it should be iterated. For
- example ``footprint=[(np.ones((9, 1)), 1), (np.ones((1, 9)), 1)]``
- would apply a 9x1 footprint followed by a 1x9 footprint resulting in a net
- effect that is the same as ``footprint=np.ones((9, 9))``, but with lower
- computational cost. Most of the builtin footprints such as
- :func:`skimage.morphology.disk` provide an option to automatically generate a
- footprint sequence of this type.
- For even-sized footprints, :func:`skimage.morphology.erosion` and
- this function produce an output that differs: one is shifted by one pixel
- compared to the other. :func:`skimage.morphology.pad_footprint´ is available
- to account for this.
- See also
- --------
- skimage.morphology.isotropic_erosion
- """
- if out is None:
- out = np.empty(image.shape, dtype=bool)
- if mode not in {"max", "min", "ignore"}:
- raise ValueError(f"unsupported mode, got {mode!r}")
- border_value = False if mode == 'min' else True
- footprint = pad_footprint(footprint, pad_end=True)
- if not _footprint_is_sequence(footprint):
- footprint = [(footprint, 1)]
- out = _iterate_binary_func(
- binary_func=ndi.binary_erosion,
- image=image,
- footprint=footprint,
- out=out,
- border_value=border_value,
- )
- return out
- @default_footprint
- @deprecate_func(
- deprecated_version="0.26",
- removed_version="0.28",
- hint="Use `skimage.morphology.dilation` instead. "
- "Note the lack of mirroring for non-symmetric footprints (see docstring notes).",
- )
- def binary_dilation(image, footprint=None, out=None, *, mode='ignore'):
- """Return fast binary morphological dilation of an image.
- This function returns the same result as grayscale dilation but performs
- faster for binary images.
- 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
- Binary input image.
- footprint : ndarray or tuple, optional
- The neighborhood expressed as a 2-D array of 1's and 0's.
- If None, use a cross-shaped footprint (connectivity=1). The footprint
- can also be provided as a sequence of smaller footprints as described
- in the notes below.
- out : ndarray of bool, optional
- The array to store the result of the morphology. If None is
- passed, a new array will be allocated.
- mode : str, optional
- The `mode` parameter determines how the array borders are handled.
- Valid modes are: 'max', 'min', 'ignore'.
- If 'min' or 'ignore', pixels outside the image domain are assumed
- to be `False`, which causes them to not influence the result.
- Default is 'ignore'.
- .. versionadded:: 0.23
- `mode` was added in 0.23.
- Returns
- -------
- dilated : ndarray of bool or uint
- The result of the morphological dilation with values in
- ``[False, True]``.
- Notes
- -----
- The footprint can also be a provided as a sequence of 2-tuples where the
- first element of each 2-tuple is a footprint ndarray and the second element
- is an integer describing the number of times it should be iterated. For
- example ``footprint=[(np.ones((9, 1)), 1), (np.ones((1, 9)), 1)]``
- would apply a 9x1 footprint followed by a 1x9 footprint resulting in a net
- effect that is the same as ``footprint=np.ones((9, 9))``, but with lower
- computational cost. Most of the builtin footprints such as
- :func:`skimage.morphology.disk` provide an option to automatically generate a
- footprint sequence of this type.
- For non-symmetric footprints, :func:`skimage.morphology.binary_dilation`
- and :func:`skimage.morphology.dilation` produce an output that differs:
- `binary_dilation` mirrors the footprint, whereas `dilation` does not.
- :func:`skimage.morphology.mirror_footprint` is available to correct for this.
- See also
- --------
- skimage.morphology.isotropic_dilation
- """
- if out is None:
- out = np.empty(image.shape, dtype=bool)
- if mode not in {"max", "min", "ignore"}:
- raise ValueError(f"unsupported mode, got {mode!r}")
- border_value = True if mode == 'max' else False
- footprint = pad_footprint(footprint, pad_end=True)
- if not _footprint_is_sequence(footprint):
- footprint = [(footprint, 1)]
- out = _iterate_binary_func(
- binary_func=ndi.binary_dilation,
- image=image,
- footprint=footprint,
- out=out,
- border_value=border_value,
- )
- return out
- @default_footprint
- @deprecate_func(
- deprecated_version="0.26",
- removed_version="0.28",
- hint="Use `skimage.morphology.opening` instead.",
- )
- def binary_opening(image, footprint=None, out=None, *, mode='ignore'):
- """Return fast binary morphological opening of an image.
- This function returns the same result as grayscale opening but performs
- faster for binary images.
- 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
- Binary input image.
- footprint : ndarray or tuple, optional
- The neighborhood expressed as a 2-D array of 1's and 0's.
- If None, use a cross-shaped footprint (connectivity=1). The footprint
- can also be provided as a sequence of smaller footprints as described
- in the notes below.
- out : ndarray of bool, optional
- The array to store the result of the morphology. If None
- is passed, a new array will be allocated.
- mode : str, optional
- The `mode` parameter determines how the array borders are handled.
- Valid modes are: 'max', 'min', 'ignore'.
- If 'ignore', pixels outside the image domain are assumed to be `True`
- for the erosion and `False` for the dilation, which causes them to not
- influence the result. Default is 'ignore'.
- .. versionadded:: 0.23
- `mode` was added in 0.23.
- Returns
- -------
- opening : ndarray of bool
- The result of the morphological opening.
- Notes
- -----
- The footprint can also be a provided as a sequence of 2-tuples where the
- first element of each 2-tuple is a footprint ndarray and the second element
- is an integer describing the number of times it should be iterated. For
- example ``footprint=[(np.ones((9, 1)), 1), (np.ones((1, 9)), 1)]``
- would apply a 9x1 footprint followed by a 1x9 footprint resulting in a net
- effect that is the same as ``footprint=np.ones((9, 9))``, but with lower
- computational cost. Most of the builtin footprints such as
- :func:`skimage.morphology.disk` provide an option to automatically generate a
- footprint sequence of this type.
- See also
- --------
- skimage.morphology.isotropic_opening
- """
- with warnings.catch_warnings():
- warnings.filterwarnings(
- action="ignore",
- message="`binary_(dilation|erosion)` is deprecated",
- category=FutureWarning,
- module="skimage",
- )
- tmp = binary_erosion(image, footprint, mode=mode)
- out = binary_dilation(tmp, footprint, out=out, mode=mode)
- return out
- @default_footprint
- @deprecate_func(
- deprecated_version="0.26",
- removed_version="0.28",
- hint="Use `skimage.morphology.closing` instead.",
- )
- def binary_closing(image, footprint=None, out=None, *, mode='ignore'):
- """Return fast binary morphological closing of an image.
- This function returns the same result as grayscale closing but performs
- faster for binary images.
- 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
- Binary input image.
- footprint : ndarray or tuple, optional
- The neighborhood expressed as a 2-D array of 1's and 0's.
- If None, use a cross-shaped footprint (connectivity=1). The footprint
- can also be provided as a sequence of smaller footprints as described
- in the notes below.
- out : ndarray of bool, optional
- The array to store the result of the morphology. If None,
- is passed, a new array will be allocated.
- mode : str, optional
- The `mode` parameter determines how the array borders are handled.
- Valid modes are: 'max', 'min', 'ignore'.
- If 'ignore', pixels outside the image domain are assumed to be `True`
- for the erosion and `False` for the dilation, which causes them to not
- influence the result. Default is 'ignore'.
- .. versionadded:: 0.23
- `mode` was added in 0.23.
- Returns
- -------
- closing : ndarray of bool
- The result of the morphological closing.
- Notes
- -----
- The footprint can also be a provided as a sequence of 2-tuples where the
- first element of each 2-tuple is a footprint ndarray and the second element
- is an integer describing the number of times it should be iterated. For
- example ``footprint=[(np.ones((9, 1)), 1), (np.ones((1, 9)), 1)]``
- would apply a 9x1 footprint followed by a 1x9 footprint resulting in a net
- effect that is the same as ``footprint=np.ones((9, 9))``, but with lower
- computational cost. Most of the builtin footprints such as
- :func:`skimage.morphology.disk` provide an option to automatically generate a
- footprint sequence of this type.
- See also
- --------
- skimage.morphology.isotropic_closing
- """
- with warnings.catch_warnings():
- warnings.filterwarnings(
- action="ignore",
- message="`binary_(dilation|erosion)` is deprecated",
- category=FutureWarning,
- module="skimage",
- )
- tmp = binary_dilation(image, footprint, mode=mode)
- out = binary_erosion(tmp, footprint, out=out, mode=mode)
- return out
|