Skip to content

Commit 9bab0e4

Browse files
committed
Raise on unsupported mode in morph. operators
1 parent 768a301 commit 9bab0e4

4 files changed

Lines changed: 59 additions & 9 deletions

File tree

skimage/morphology/binary.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ def binary_erosion(image, footprint=None, out=None, mode='ignore'):
9999
if out is None:
100100
out = np.empty(image.shape, dtype=bool)
101101

102+
if mode not in {"max", "min", "ignore"}:
103+
raise ValueError(f"unsupported mode, got {mode!r}")
102104
border_value = False if mode == 'min' else True
103105

104106
footprint = pad_footprint(footprint, pad_end=True)
@@ -177,6 +179,8 @@ def binary_dilation(image, footprint=None, out=None, mode='ignore'):
177179
if out is None:
178180
out = np.empty(image.shape, dtype=bool)
179181

182+
if mode not in {"max", "min", "ignore"}:
183+
raise ValueError(f"unsupported mode, got {mode!r}")
180184
border_value = True if mode == 'max' else False
181185

182186
footprint = pad_footprint(footprint, pad_end=True)

skimage/morphology/gray.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,18 @@ def _min_max_to_constant_mode(dtype, mode, cval):
109109
return mode, cval
110110

111111

112+
_SUPPORTED_MODES = {
113+
"reflect",
114+
"constant",
115+
"nearest",
116+
"mirror",
117+
"wrap",
118+
"max",
119+
"min",
120+
"ignore",
121+
}
122+
123+
112124
@default_footprint
113125
def erosion(
114126
image,
@@ -203,6 +215,8 @@ def erosion(
203215
if out is None:
204216
out = np.empty_like(image)
205217

218+
if mode not in _SUPPORTED_MODES:
219+
raise ValueError(f"unsupported mode, got {mode!r}")
206220
if mode == "ignore":
207221
mode = "max"
208222
mode, cval = _min_max_to_constant_mode(image.dtype, mode, cval)
@@ -312,6 +326,8 @@ def dilation(
312326
if out is None:
313327
out = np.empty_like(image)
314328

329+
if mode not in _SUPPORTED_MODES:
330+
raise ValueError(f"unsupported mode, got {mode!r}")
315331
if mode == "ignore":
316332
mode = "min"
317333
mode, cval = _min_max_to_constant_mode(image.dtype, mode, cval)

skimage/morphology/tests/test_binary.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,21 @@ def test_out_argument():
235235
]
236236

237237

238+
@pytest.mark.parametrize("func", binary_functions)
239+
@pytest.mark.parametrize("mode", ['max', 'min', 'ignore'])
240+
def test_supported_mode(func, mode):
241+
img = np.ones((10, 10), dtype=bool)
242+
func(img, mode=mode)
243+
244+
245+
@pytest.mark.parametrize("func", binary_functions)
246+
@pytest.mark.parametrize("mode", ["reflect", 3, None])
247+
def test_unsupported_mode(func, mode):
248+
img = np.ones((10, 10))
249+
with pytest.raises(ValueError, match="unsupported mode"):
250+
func(img, mode=mode)
251+
252+
238253
@pytest.mark.parametrize("function", binary_functions)
239254
def test_default_footprint(function):
240255
footprint = morphology.diamond(radius=1)

skimage/morphology/tests/test_gray.py

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ def cell3d_image():
2424
return np.ascontiguousarray(data.cells3d()[30:48, 0, 20:36, 20:32])
2525

2626

27+
gray_morphology_funcs = (
28+
gray.erosion,
29+
gray.dilation,
30+
gray.opening,
31+
gray.closing,
32+
gray.white_tophat,
33+
gray.black_tophat,
34+
)
35+
36+
2737
class TestMorphology:
2838
# These expected outputs were generated with skimage v0.22.0 + PR #6695
2939
# using:
@@ -34,14 +44,6 @@ class TestMorphology:
3444
# np.savez_compressed('gray_morph_output.npz', **output)
3545

3646
def _build_expected_output(self):
37-
funcs = (
38-
gray.erosion,
39-
gray.dilation,
40-
gray.opening,
41-
gray.closing,
42-
gray.white_tophat,
43-
gray.black_tophat,
44-
)
4547
footprints_2D = (
4648
footprints.square,
4749
footprints.diamond,
@@ -56,7 +58,7 @@ def _build_expected_output(self):
5658
output = {}
5759
for n in range(1, 4):
5860
for strel in footprints_2D:
59-
for func in funcs:
61+
for func in gray_morphology_funcs:
6062
key = f'{strel.__name__}_{n}_{func.__name__}'
6163
output[key] = func(image, strel(n))
6264

@@ -89,6 +91,19 @@ def test_gray_opening_anti_extensive(self):
8991
result_ignore = gray.opening(img, footprint=footprint, mode="ignore")
9092
assert np.all(result_ignore <= img)
9193

94+
@pytest.mark.parametrize("func", gray_morphology_funcs)
95+
@pytest.mark.parametrize("mode", gray._SUPPORTED_MODES)
96+
def test_supported_mode(self, func, mode):
97+
img = np.ones((10, 10))
98+
func(img, mode=mode)
99+
100+
@pytest.mark.parametrize("func", gray_morphology_funcs)
101+
@pytest.mark.parametrize("mode", ["", "symmetric", 3, None])
102+
def test_unsupported_mode(self, func, mode):
103+
img = np.ones((10, 10))
104+
with pytest.raises(ValueError, match="unsupported mode"):
105+
func(img, mode=mode)
106+
92107

93108
class TestEccentricStructuringElements:
94109
def setup_class(self):

0 commit comments

Comments
 (0)