scikit-image
320 строк · 11.8 Кб
1"""
2Binary morphological operations
3"""
4
5import numpy as np
6from scipy import ndimage as ndi
7
8from .footprints import _footprint_is_sequence, pad_footprint
9from .misc import default_footprint
10
11
12def _iterate_binary_func(binary_func, image, footprint, out, border_value):
13"""Helper to call `binary_func` for each footprint in a sequence.
14
15binary_func is a binary morphology function that accepts "structure",
16"output" and "iterations" keyword arguments
17(e.g. `scipy.ndimage.binary_erosion`).
18"""
19fp, num_iter = footprint[0]
20binary_func(
21image, structure=fp, output=out, iterations=num_iter, border_value=border_value
22)
23for fp, num_iter in footprint[1:]:
24# Note: out.copy() because the computation cannot be in-place!
25# SciPy <= 1.7 did not automatically make a copy if needed.
26binary_func(
27out.copy(),
28structure=fp,
29output=out,
30iterations=num_iter,
31border_value=border_value,
32)
33return out
34
35
36# The default_footprint decorator provides a diamond footprint as
37# default with the same dimension as the input image and size 3 along each
38# axis.
39@default_footprint
40def binary_erosion(image, footprint=None, out=None, *, mode='ignore'):
41"""Return fast binary morphological erosion of an image.
42
43This function returns the same result as grayscale erosion but performs
44faster for binary images.
45
46Morphological erosion sets a pixel at ``(i,j)`` to the minimum over all
47pixels in the neighborhood centered at ``(i,j)``. Erosion shrinks bright
48regions and enlarges dark regions.
49
50Parameters
51----------
52image : ndarray
53Binary input image.
54footprint : ndarray or tuple, optional
55The neighborhood expressed as a 2-D array of 1's and 0's.
56If None, use a cross-shaped footprint (connectivity=1). The footprint
57can also be provided as a sequence of smaller footprints as described
58in the notes below.
59out : ndarray of bool, optional
60The array to store the result of the morphology. If None is
61passed, a new array will be allocated.
62mode : str, optional
63The `mode` parameter determines how the array borders are handled.
64Valid modes are: 'max', 'min', 'ignore'.
65If 'max' or 'ignore', pixels outside the image domain are assumed
66to be `True`, which causes them to not influence the result.
67Default is 'ignore'.
68
69.. versionadded:: 0.23
70`mode` was added in 0.23.
71
72Returns
73-------
74eroded : ndarray of bool or uint
75The result of the morphological erosion taking values in
76``[False, True]``.
77
78Notes
79-----
80The footprint can also be a provided as a sequence of 2-tuples where the
81first element of each 2-tuple is a footprint ndarray and the second element
82is an integer describing the number of times it should be iterated. For
83example ``footprint=[(np.ones((9, 1)), 1), (np.ones((1, 9)), 1)]``
84would apply a 9x1 footprint followed by a 1x9 footprint resulting in a net
85effect that is the same as ``footprint=np.ones((9, 9))``, but with lower
86computational cost. Most of the builtin footprints such as
87:func:`skimage.morphology.disk` provide an option to automatically generate a
88footprint sequence of this type.
89
90For even-sized footprints, :func:`skimage.morphology.erosion` and
91this function produce an output that differs: one is shifted by one pixel
92compared to the other.
93
94See also
95--------
96skimage.morphology.isotropic_erosion
97
98"""
99if out is None:
100out = np.empty(image.shape, dtype=bool)
101
102if mode not in {"max", "min", "ignore"}:
103raise ValueError(f"unsupported mode, got {mode!r}")
104border_value = False if mode == 'min' else True
105
106footprint = pad_footprint(footprint, pad_end=True)
107if not _footprint_is_sequence(footprint):
108footprint = [(footprint, 1)]
109
110out = _iterate_binary_func(
111binary_func=ndi.binary_erosion,
112image=image,
113footprint=footprint,
114out=out,
115border_value=border_value,
116)
117return out
118
119
120@default_footprint
121def binary_dilation(image, footprint=None, out=None, *, mode='ignore'):
122"""Return fast binary morphological dilation of an image.
123
124This function returns the same result as grayscale dilation but performs
125faster for binary images.
126
127Morphological dilation sets a pixel at ``(i,j)`` to the maximum over all
128pixels in the neighborhood centered at ``(i,j)``. Dilation enlarges bright
129regions and shrinks dark regions.
130
131Parameters
132----------
133image : ndarray
134Binary input image.
135footprint : ndarray or tuple, optional
136The neighborhood expressed as a 2-D array of 1's and 0's.
137If None, use a cross-shaped footprint (connectivity=1). The footprint
138can also be provided as a sequence of smaller footprints as described
139in the notes below.
140out : ndarray of bool, optional
141The array to store the result of the morphology. If None is
142passed, a new array will be allocated.
143mode : str, optional
144The `mode` parameter determines how the array borders are handled.
145Valid modes are: 'max', 'min', 'ignore'.
146If 'min' or 'ignore', pixels outside the image domain are assumed
147to be `False`, which causes them to not influence the result.
148Default is 'ignore'.
149
150.. versionadded:: 0.23
151`mode` was added in 0.23.
152
153Returns
154-------
155dilated : ndarray of bool or uint
156The result of the morphological dilation with values in
157``[False, True]``.
158
159Notes
160-----
161The footprint can also be a provided as a sequence of 2-tuples where the
162first element of each 2-tuple is a footprint ndarray and the second element
163is an integer describing the number of times it should be iterated. For
164example ``footprint=[(np.ones((9, 1)), 1), (np.ones((1, 9)), 1)]``
165would apply a 9x1 footprint followed by a 1x9 footprint resulting in a net
166effect that is the same as ``footprint=np.ones((9, 9))``, but with lower
167computational cost. Most of the builtin footprints such as
168:func:`skimage.morphology.disk` provide an option to automatically generate a
169footprint sequence of this type.
170
171For non-symmetric footprints, :func:`skimage.morphology.binary_dilation`
172and :func:`skimage.morphology.dilation` produce an output that differs:
173`binary_dilation` mirrors the footprint, whereas `dilation` does not.
174
175See also
176--------
177skimage.morphology.isotropic_dilation
178
179"""
180if out is None:
181out = np.empty(image.shape, dtype=bool)
182
183if mode not in {"max", "min", "ignore"}:
184raise ValueError(f"unsupported mode, got {mode!r}")
185border_value = True if mode == 'max' else False
186
187footprint = pad_footprint(footprint, pad_end=True)
188if not _footprint_is_sequence(footprint):
189footprint = [(footprint, 1)]
190
191out = _iterate_binary_func(
192binary_func=ndi.binary_dilation,
193image=image,
194footprint=footprint,
195out=out,
196border_value=border_value,
197)
198return out
199
200
201@default_footprint
202def binary_opening(image, footprint=None, out=None, *, mode='ignore'):
203"""Return fast binary morphological opening of an image.
204
205This function returns the same result as grayscale opening but performs
206faster for binary images.
207
208The morphological opening on an image is defined as an erosion followed by
209a dilation. Opening can remove small bright spots (i.e. "salt") and connect
210small dark cracks. This tends to "open" up (dark) gaps between (bright)
211features.
212
213Parameters
214----------
215image : ndarray
216Binary input image.
217footprint : ndarray or tuple, optional
218The neighborhood expressed as a 2-D array of 1's and 0's.
219If None, use a cross-shaped footprint (connectivity=1). The footprint
220can also be provided as a sequence of smaller footprints as described
221in the notes below.
222out : ndarray of bool, optional
223The array to store the result of the morphology. If None
224is passed, a new array will be allocated.
225mode : str, optional
226The `mode` parameter determines how the array borders are handled.
227Valid modes are: 'max', 'min', 'ignore'.
228If 'ignore', pixels outside the image domain are assumed to be `True`
229for the erosion and `False` for the dilation, which causes them to not
230influence the result. Default is 'ignore'.
231
232.. versionadded:: 0.23
233`mode` was added in 0.23.
234
235Returns
236-------
237opening : ndarray of bool
238The result of the morphological opening.
239
240Notes
241-----
242The footprint can also be a provided as a sequence of 2-tuples where the
243first element of each 2-tuple is a footprint ndarray and the second element
244is an integer describing the number of times it should be iterated. For
245example ``footprint=[(np.ones((9, 1)), 1), (np.ones((1, 9)), 1)]``
246would apply a 9x1 footprint followed by a 1x9 footprint resulting in a net
247effect that is the same as ``footprint=np.ones((9, 9))``, but with lower
248computational cost. Most of the builtin footprints such as
249:func:`skimage.morphology.disk` provide an option to automatically generate a
250footprint sequence of this type.
251
252See also
253--------
254skimage.morphology.isotropic_opening
255
256"""
257tmp = binary_erosion(image, footprint, mode=mode)
258out = binary_dilation(tmp, footprint, out=out, mode=mode)
259return out
260
261
262@default_footprint
263def binary_closing(image, footprint=None, out=None, *, mode='ignore'):
264"""Return fast binary morphological closing of an image.
265
266This function returns the same result as grayscale closing but performs
267faster for binary images.
268
269The morphological closing on an image is defined as a dilation followed by
270an erosion. Closing can remove small dark spots (i.e. "pepper") and connect
271small bright cracks. This tends to "close" up (dark) gaps between (bright)
272features.
273
274Parameters
275----------
276image : ndarray
277Binary input image.
278footprint : ndarray or tuple, optional
279The neighborhood expressed as a 2-D array of 1's and 0's.
280If None, use a cross-shaped footprint (connectivity=1). The footprint
281can also be provided as a sequence of smaller footprints as described
282in the notes below.
283out : ndarray of bool, optional
284The array to store the result of the morphology. If None,
285is passed, a new array will be allocated.
286mode : str, optional
287The `mode` parameter determines how the array borders are handled.
288Valid modes are: 'max', 'min', 'ignore'.
289If 'ignore', pixels outside the image domain are assumed to be `True`
290for the erosion and `False` for the dilation, which causes them to not
291influence the result. Default is 'ignore'.
292
293.. versionadded:: 0.23
294`mode` was added in 0.23.
295
296Returns
297-------
298closing : ndarray of bool
299The result of the morphological closing.
300
301Notes
302-----
303The footprint can also be a provided as a sequence of 2-tuples where the
304first element of each 2-tuple is a footprint ndarray and the second element
305is an integer describing the number of times it should be iterated. For
306example ``footprint=[(np.ones((9, 1)), 1), (np.ones((1, 9)), 1)]``
307would apply a 9x1 footprint followed by a 1x9 footprint resulting in a net
308effect that is the same as ``footprint=np.ones((9, 9))``, but with lower
309computational cost. Most of the builtin footprints such as
310:func:`skimage.morphology.disk` provide an option to automatically generate a
311footprint sequence of this type.
312
313See also
314--------
315skimage.morphology.isotropic_closing
316
317"""
318tmp = binary_dilation(image, footprint, mode=mode)
319out = binary_erosion(tmp, footprint, out=out, mode=mode)
320return out
321