1"""
2Binary morphological operations
3"""
4import numpy as np
5from scipy import ndimage as ndi
6
7from .._shared.utils import deprecate_kwarg
8from .misc import default_footprint
9
10
11# The default_footprint decorator provides a diamond footprint as
12# default with the same dimension as the input image and size 3 along each
13# axis.
14@default_footprint
15@deprecate_kwarg(kwarg_mapping={'selem': 'footprint'}, removed_version="1.0",
16                 deprecated_version="0.19")
17def binary_erosion(image, footprint=None, out=None):
18    """Return fast binary morphological erosion of an image.
19
20    This function returns the same result as grayscale erosion but performs
21    faster for binary images.
22
23    Morphological erosion sets a pixel at ``(i,j)`` to the minimum over all
24    pixels in the neighborhood centered at ``(i,j)``. Erosion shrinks bright
25    regions and enlarges dark regions.
26
27    Parameters
28    ----------
29    image : ndarray
30        Binary input image.
31    footprint : ndarray, optional
32        The neighborhood expressed as a 2-D array of 1's and 0's.
33        If None, use a cross-shaped footprint (connectivity=1).
34    out : ndarray of bool, optional
35        The array to store the result of the morphology. If None is
36        passed, a new array will be allocated.
37
38    Returns
39    -------
40    eroded : ndarray of bool or uint
41        The result of the morphological erosion taking values in
42        ``[False, True]``.
43
44    """
45    if out is None:
46        out = np.empty(image.shape, dtype=bool)
47    ndi.binary_erosion(image, structure=footprint, output=out,
48                       border_value=True)
49    return out
50
51
52@default_footprint
53@deprecate_kwarg(kwarg_mapping={'selem': 'footprint'}, removed_version="1.0",
54                 deprecated_version="0.19")
55def binary_dilation(image, footprint=None, out=None):
56    """Return fast binary morphological dilation of an image.
57
58    This function returns the same result as grayscale dilation but performs
59    faster for binary images.
60
61    Morphological dilation sets a pixel at ``(i,j)`` to the maximum over all
62    pixels in the neighborhood centered at ``(i,j)``. Dilation enlarges bright
63    regions and shrinks dark regions.
64
65    Parameters
66    ----------
67    image : ndarray
68        Binary input image.
69    footprint : ndarray, optional
70        The neighborhood expressed as a 2-D array of 1's and 0's.
71        If None, use a cross-shaped footprint (connectivity=1).
72    out : ndarray of bool, optional
73        The array to store the result of the morphology. If None is
74        passed, a new array will be allocated.
75
76    Returns
77    -------
78    dilated : ndarray of bool or uint
79        The result of the morphological dilation with values in
80        ``[False, True]``.
81    """
82    if out is None:
83        out = np.empty(image.shape, dtype=bool)
84    ndi.binary_dilation(image, structure=footprint, output=out)
85    return out
86
87
88@default_footprint
89@deprecate_kwarg(kwarg_mapping={'selem': 'footprint'}, removed_version="1.0",
90                 deprecated_version="0.19")
91def binary_opening(image, footprint=None, out=None):
92    """Return fast binary morphological opening of an image.
93
94    This function returns the same result as grayscale opening but performs
95    faster for binary images.
96
97    The morphological opening on an image is defined as an erosion followed by
98    a dilation. Opening can remove small bright spots (i.e. "salt") and connect
99    small dark cracks. This tends to "open" up (dark) gaps between (bright)
100    features.
101
102    Parameters
103    ----------
104    image : ndarray
105        Binary input image.
106    footprint : ndarray, optional
107        The neighborhood expressed as a 2-D array of 1's and 0's.
108        If None, use a cross-shaped footprint (connectivity=1).
109    out : ndarray of bool, optional
110        The array to store the result of the morphology. If None
111        is passed, a new array will be allocated.
112
113    Returns
114    -------
115    opening : ndarray of bool
116        The result of the morphological opening.
117
118    """
119    eroded = binary_erosion(image, footprint)
120    out = binary_dilation(eroded, footprint, out=out)
121    return out
122
123
124@default_footprint
125@deprecate_kwarg(kwarg_mapping={'selem': 'footprint'}, removed_version="1.0",
126                 deprecated_version="0.19")
127def binary_closing(image, footprint=None, out=None):
128    """Return fast binary morphological closing of an image.
129
130    This function returns the same result as grayscale closing but performs
131    faster for binary images.
132
133    The morphological closing on an image is defined as a dilation followed by
134    an erosion. Closing can remove small dark spots (i.e. "pepper") and connect
135    small bright cracks. This tends to "close" up (dark) gaps between (bright)
136    features.
137
138    Parameters
139    ----------
140    image : ndarray
141        Binary input image.
142    footprint : ndarray, optional
143        The neighborhood expressed as a 2-D array of 1's and 0's.
144        If None, use a cross-shaped footprint (connectivity=1).
145    out : ndarray of bool, optional
146        The array to store the result of the morphology. If None,
147        is passed, a new array will be allocated.
148
149    Returns
150    -------
151    closing : ndarray of bool
152        The result of the morphological closing.
153
154    """
155    dilated = binary_dilation(image, footprint)
156    out = binary_erosion(dilated, footprint, out=out)
157    return out
158