From 6a8889d0b0bb89714755e6f7f0821cd533076af4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Thu, 3 Oct 2013 08:39:15 +0200 Subject: [PATCH 1/7] Fix numpy 1.8 bug --- skimage/morphology/binary.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/skimage/morphology/binary.py b/skimage/morphology/binary.py index e2e0f20b..eaea6773 100644 --- a/skimage/morphology/binary.py +++ b/skimage/morphology/binary.py @@ -29,7 +29,7 @@ def binary_erosion(image, selem, out=None): """ - conv = ndimage.convolve(image > 0, selem, output=out, + conv = ndimage.convolve((image > 0).view(np.uint8), selem, output=out, mode='constant', cval=1) if conv is not None: out = conv @@ -64,7 +64,7 @@ def binary_dilation(image, selem, out=None): """ - conv = ndimage.convolve(image > 0, selem, output=out, + conv = ndimage.convolve((image > 0).view(np.uint8), selem, output=out, mode='constant', cval=0) if conv is not None: out = conv From 895b025a3a875b49ab183c5f43dd7f5364d8faed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Thu, 3 Oct 2013 08:39:19 +0200 Subject: [PATCH 2/7] Split grey and binary erosion tests in two files --- skimage/morphology/tests/test_binary.py | 49 +++++++++++++++++++++++++ skimage/morphology/tests/test_grey.py | 37 +------------------ 2 files changed, 50 insertions(+), 36 deletions(-) create mode 100644 skimage/morphology/tests/test_binary.py diff --git a/skimage/morphology/tests/test_binary.py b/skimage/morphology/tests/test_binary.py new file mode 100644 index 00000000..2f47c917 --- /dev/null +++ b/skimage/morphology/tests/test_binary.py @@ -0,0 +1,49 @@ +import numpy as np +from numpy import testing + +from skimage import data, color +from skimage.util import img_as_bool +from skimage.morphology import binary, grey, selem + + +lena = color.rgb2gray(data.lena()) +bw_lena = lena > 100 + + +def test_non_square_image(): + strel = selem.square(3) + binary_res = binary.binary_erosion(bw_lena[:100, :200], strel) + grey_res = img_as_bool(grey.erosion(bw_lena[:100, :200], strel)) + testing.assert_array_equal(binary_res, grey_res) + + +def test_binary_erosion(): + strel = selem.square(3) + binary_res = binary.binary_erosion(bw_lena, strel) + grey_res = img_as_bool(grey.erosion(bw_lena, strel)) + testing.assert_array_equal(binary_res, grey_res) + + +def test_binary_dilation(): + strel = selem.square(3) + binary_res = binary.binary_dilation(bw_lena, strel) + grey_res = img_as_bool(grey.dilation(bw_lena, strel)) + testing.assert_array_equal(binary_res, grey_res) + + +def test_binary_closing(): + strel = selem.square(3) + binary_res = binary.binary_closing(bw_lena, strel) + grey_res = img_as_bool(grey.closing(bw_lena, strel)) + testing.assert_array_equal(binary_res, grey_res) + + +def test_binary_opening(): + strel = selem.square(3) + binary_res = binary.binary_opening(bw_lena, strel) + grey_res = img_as_bool(grey.opening(bw_lena, strel)) + testing.assert_array_equal(binary_res, grey_res) + + +if __name__ == '__main__': + testing.run_module_suite() diff --git a/skimage/morphology/tests/test_grey.py b/skimage/morphology/tests/test_grey.py index 244ec566..e2a3928d 100644 --- a/skimage/morphology/tests/test_grey.py +++ b/skimage/morphology/tests/test_grey.py @@ -6,7 +6,7 @@ from numpy import testing import skimage from skimage import data_dir from skimage.util import img_as_bool -from skimage.morphology import binary, grey, selem +from skimage.morphology import grey, selem lena = np.load(os.path.join(data_dir, 'lena_GRAY_U8.npy')) @@ -155,40 +155,5 @@ class TestDTypes(): self._test_image(image) -def test_non_square_image(): - strel = selem.square(3) - binary_res = binary.binary_erosion(bw_lena[:100, :200], strel) - grey_res = img_as_bool(grey.erosion(bw_lena[:100, :200], strel)) - testing.assert_array_equal(binary_res, grey_res) - - -def test_binary_erosion(): - strel = selem.square(3) - binary_res = binary.binary_erosion(bw_lena, strel) - grey_res = img_as_bool(grey.erosion(bw_lena, strel)) - testing.assert_array_equal(binary_res, grey_res) - - -def test_binary_dilation(): - strel = selem.square(3) - binary_res = binary.binary_dilation(bw_lena, strel) - grey_res = img_as_bool(grey.dilation(bw_lena, strel)) - testing.assert_array_equal(binary_res, grey_res) - - -def test_binary_closing(): - strel = selem.square(3) - binary_res = binary.binary_closing(bw_lena, strel) - grey_res = img_as_bool(grey.closing(bw_lena, strel)) - testing.assert_array_equal(binary_res, grey_res) - - -def test_binary_opening(): - strel = selem.square(3) - binary_res = binary.binary_opening(bw_lena, strel) - grey_res = img_as_bool(grey.opening(bw_lena, strel)) - testing.assert_array_equal(binary_res, grey_res) - - if __name__ == '__main__': testing.run_module_suite() From 95a5a98c937a1f8d9cdb5e09de90620704e6cc0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Mon, 7 Oct 2013 22:56:56 +0200 Subject: [PATCH 3/7] Fix overflow error --- skimage/morphology/binary.py | 45 +++++++++++++++++++------ skimage/morphology/tests/test_binary.py | 21 ++++++++++++ 2 files changed, 56 insertions(+), 10 deletions(-) diff --git a/skimage/morphology/binary.py b/skimage/morphology/binary.py index eaea6773..70fcd6b4 100644 --- a/skimage/morphology/binary.py +++ b/skimage/morphology/binary.py @@ -1,7 +1,38 @@ import numpy as np +import warnings from scipy import ndimage +def _convolve(image, selem, out, cval): + + # determine the smallest integer dtype which does not overflow + selem = selem != 0 + selem_sum = np.sum(selem) + if selem_sum < 2 ** 8: + out_dtype = np.uint8 + elif selem_sum < 2 ** 16: + out_dtype = np.uint16 + else: + out_dtype = np.uint32 + + if out is None: + out = np.zeros_like(image, dtype=out_dtype) + else: + iinfo = np.iinfo(out.dtype) + if iinfo.max - iinfo.min < selem_sum: + raise ValueError('Sum of structuring (=%d) element results in ' + 'overflow for dtype of `out`. You must raise the ' + 'bit-depth.') + + conv = ndimage.convolve(image > 0, selem, output=out, + mode='constant', cval=cval) + + if conv is not None: + out = conv + + return out, selem_sum + + def binary_erosion(image, selem, out=None): """Return fast binary morphological erosion of an image. @@ -29,11 +60,8 @@ def binary_erosion(image, selem, out=None): """ - conv = ndimage.convolve((image > 0).view(np.uint8), selem, output=out, - mode='constant', cval=1) - if conv is not None: - out = conv - return np.equal(out, np.sum(selem), out=out) + out, selem_sum = _convolve(image, selem, out, 1) + return np.equal(out, selem_sum, out=out).astype(np.bool, copy=False) def binary_dilation(image, selem, out=None): @@ -64,11 +92,8 @@ def binary_dilation(image, selem, out=None): """ - conv = ndimage.convolve((image > 0).view(np.uint8), selem, output=out, - mode='constant', cval=0) - if conv is not None: - out = conv - return np.not_equal(out, 0, out=out) + out, _ = _convolve(image, selem, out, 0) + return np.not_equal(out, 0, out=out).astype(np.bool, copy=False) def binary_opening(image, selem, out=None): diff --git a/skimage/morphology/tests/test_binary.py b/skimage/morphology/tests/test_binary.py index 2f47c917..5f831669 100644 --- a/skimage/morphology/tests/test_binary.py +++ b/skimage/morphology/tests/test_binary.py @@ -17,6 +17,27 @@ def test_non_square_image(): testing.assert_array_equal(binary_res, grey_res) +def test_selem_overflow(): + strel = np.ones((17, 17), dtype=np.uint8) + img = np.zeros((20, 20)) + img[2:19, 2:19] = 1 + binary_res = binary.binary_erosion(img, strel) + grey_res = img_as_bool(grey.erosion(img, strel)) + testing.assert_array_equal(binary_res, grey_res) + + +def test_selem_overflow_exception(): + strel = np.ones((17, 17), dtype=np.uint8) + img = np.zeros((20, 20)) + img[2:19, 2:19] = 1 + out = np.zeros((20, 20), dtype=np.uint8) + testing.assert_raises(ValueError, binary.binary_erosion, img, strel, out) + out = np.zeros((20, 20), dtype=np.uint16) + binary_res = binary.binary_erosion(img, strel, out=out) + grey_res = img_as_bool(grey.erosion(img, strel)) + testing.assert_array_equal(binary_res, grey_res) + + def test_binary_erosion(): strel = selem.square(3) binary_res = binary.binary_erosion(bw_lena, strel) From ecf10a7a48ed0205a61da10a91153345266dcd1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Mon, 7 Oct 2013 23:33:12 +0200 Subject: [PATCH 4/7] Reduce number of specializations --- skimage/morphology/binary.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/skimage/morphology/binary.py b/skimage/morphology/binary.py index 70fcd6b4..7262c573 100644 --- a/skimage/morphology/binary.py +++ b/skimage/morphology/binary.py @@ -10,10 +10,8 @@ def _convolve(image, selem, out, cval): selem_sum = np.sum(selem) if selem_sum < 2 ** 8: out_dtype = np.uint8 - elif selem_sum < 2 ** 16: - out_dtype = np.uint16 else: - out_dtype = np.uint32 + out_dtype = np.intp if out is None: out = np.zeros_like(image, dtype=out_dtype) From 2a84e4538927a689fec6d6aa26c1af482fb2f933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Mon, 7 Oct 2013 23:35:54 +0200 Subject: [PATCH 5/7] Remove unused import --- skimage/morphology/binary.py | 1 - 1 file changed, 1 deletion(-) diff --git a/skimage/morphology/binary.py b/skimage/morphology/binary.py index 7262c573..4a7b1578 100644 --- a/skimage/morphology/binary.py +++ b/skimage/morphology/binary.py @@ -1,5 +1,4 @@ import numpy as np -import warnings from scipy import ndimage From b187144a5fe24d0370a77d36c656eeabfd885690 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Thu, 10 Oct 2013 09:04:17 +0200 Subject: [PATCH 6/7] Add support older numpy versions --- skimage/morphology/binary.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/skimage/morphology/binary.py b/skimage/morphology/binary.py index 4a7b1578..d248d8db 100644 --- a/skimage/morphology/binary.py +++ b/skimage/morphology/binary.py @@ -58,7 +58,8 @@ def binary_erosion(image, selem, out=None): """ out, selem_sum = _convolve(image, selem, out, 1) - return np.equal(out, selem_sum, out=out).astype(np.bool, copy=False) + return np.array(np.equal(out, selem_sum, out=out), dtype=np.bool, + copy=False) def binary_dilation(image, selem, out=None): @@ -90,7 +91,7 @@ def binary_dilation(image, selem, out=None): """ out, _ = _convolve(image, selem, out, 0) - return np.not_equal(out, 0, out=out).astype(np.bool, copy=False) + return np.array(np.not_equal(out, 0, out=out), dtype=np.bool, copy=False) def binary_opening(image, selem, out=None): From f8d34e8bf91f1fed3970b770abdfec94efc949df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Thu, 10 Oct 2013 09:10:42 +0200 Subject: [PATCH 7/7] Deprecate out parameter --- TODO.txt | 1 + skimage/morphology/binary.py | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/TODO.txt b/TODO.txt index db7ffe48..29d1ebac 100644 --- a/TODO.txt +++ b/TODO.txt @@ -6,6 +6,7 @@ Version 0.10 * Remove {`ratio`, `sigma`} deprecation warnings of `skimage.segmentation.slic` * Change default mode of random_walker segmentation to 'cg_mg' > 'cg' > 'bf', depending on which optional dependencies are available. +* Remove deprecated `out` parameter of `skimage.morphology.binary_*` Version 0.9 ----------- diff --git a/skimage/morphology/binary.py b/skimage/morphology/binary.py index d248d8db..11a14d49 100644 --- a/skimage/morphology/binary.py +++ b/skimage/morphology/binary.py @@ -1,3 +1,4 @@ +import warnings import numpy as np from scipy import ndimage @@ -15,6 +16,9 @@ def _convolve(image, selem, out, cval): if out is None: out = np.zeros_like(image, dtype=out_dtype) else: + warnings.warn('Parameter `out` is deprecated and it does not equal ' + 'the output image if the sum of the structuring element ' + 'overflows the dtype of `out`.') iinfo = np.iinfo(out.dtype) if iinfo.max - iinfo.min < selem_sum: raise ValueError('Sum of structuring (=%d) element results in '