From bb51f62f93f347487edb71e0fcc518e80cf1a840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Thu, 16 Aug 2012 22:35:04 +0200 Subject: [PATCH 1/5] Add function to clear border in binary images --- skimage/morphology/_clear_border.py | 36 +++++++++++++++++++ skimage/morphology/tests/test_clear_border.py | 32 +++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 skimage/morphology/_clear_border.py create mode 100644 skimage/morphology/tests/test_clear_border.py diff --git a/skimage/morphology/_clear_border.py b/skimage/morphology/_clear_border.py new file mode 100644 index 00000000..4185b0d9 --- /dev/null +++ b/skimage/morphology/_clear_border.py @@ -0,0 +1,36 @@ +import numpy as np +from skimage.measure import regionprops +from skimage.morphology import label + + +def clear_border(image, buffer_size=0, bgval=0): + """Clear objects connected to image border. + + The changes will be applied to the input image. + + Parameters + ---------- + image : (N, M) array + binary image + buffer_size : int, optional + define additional buffer around image border + bgval : float or int, optional + value for cleared objects + + Returns + ------- + image : (N, M) array + cleared binary image + """ + rows, cols = image.shape + for prop in regionprops(label(image), ['BoundingBox', 'Image']): + minr, minc, maxr, maxc = prop['BoundingBox'] + if ( + minr <= buffer_size + or minc <= buffer_size + or maxr >= rows - buffer_size + or maxc >= cols - buffer_size + ): + r, c = np.nonzero(prop['Image']) + image[minr + r, minc + c] = bgval + return image diff --git a/skimage/morphology/tests/test_clear_border.py b/skimage/morphology/tests/test_clear_border.py new file mode 100644 index 00000000..c4cdd4af --- /dev/null +++ b/skimage/morphology/tests/test_clear_border.py @@ -0,0 +1,32 @@ +import numpy as np +from numpy.testing import assert_array_equal, assert_equal +from skimage.morphology import clear_border + + +def test_possible_hull(): + image = np.array( + [[0, 0, 0, 0, 0, 0, 0, 1, 0], + [0, 0, 0, 0, 1, 0, 0, 0, 0], + [1, 0, 0, 1, 0, 1, 0, 0, 0], + [0, 0, 1, 1, 1, 1, 1, 0, 0], + [0, 1, 1, 1, 1, 1, 1, 1, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0]]) + + # test default case + result = clear_border(image.copy()) + ref = image.copy() + ref[2, 0] = 0 + ref[0, -2] = 0 + assert_array_equal(result, ref) + + # test buffer + result = clear_border(image.copy(), 1) + assert_array_equal(result, np.zeros(result.shape)) + + # test background value + result = clear_border(image.copy(), 1, 2) + assert_array_equal(result, 2 * image) + + +if __name__ == "__main__": + np.testing.run_module_suite() From 156b484bc2150cfe6089a1658cbff08a7682274a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Mon, 27 Aug 2012 18:49:14 +0200 Subject: [PATCH 2/5] Refactor clear_border for better performance --- skimage/morphology/_clear_border.py | 47 ++++++++++++------- skimage/morphology/tests/test_clear_border.py | 4 +- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/skimage/morphology/_clear_border.py b/skimage/morphology/_clear_border.py index 4185b0d9..47de7e49 100644 --- a/skimage/morphology/_clear_border.py +++ b/skimage/morphology/_clear_border.py @@ -1,6 +1,5 @@ import numpy as np -from skimage.measure import regionprops -from skimage.morphology import label +from scipy.ndimage import label def clear_border(image, buffer_size=0, bgval=0): @@ -11,26 +10,42 @@ def clear_border(image, buffer_size=0, bgval=0): Parameters ---------- image : (N, M) array - binary image + Binary image. buffer_size : int, optional - define additional buffer around image border + Define additional buffer around image border. bgval : float or int, optional - value for cleared objects + Value for cleared objects. Returns ------- image : (N, M) array - cleared binary image + Cleared binary image. + """ + rows, cols = image.shape - for prop in regionprops(label(image), ['BoundingBox', 'Image']): - minr, minc, maxr, maxc = prop['BoundingBox'] - if ( - minr <= buffer_size - or minc <= buffer_size - or maxr >= rows - buffer_size - or maxc >= cols - buffer_size - ): - r, c = np.nonzero(prop['Image']) - image[minr + r, minc + c] = bgval + if buffer_size >= rows or buffer_size >= cols: + raise ValueError("buffer size may not be greater than image size") + + # create borders with buffer_size + borders = np.zeros_like(image, np.bool_) + ext = buffer_size + 1 + borders[:ext] = True + borders[- ext:] = True + borders[:, :ext] = True + borders[:, - ext:] = True + + labels, number = label(image) + + # determine all objects that are connected to borders + borders_indices = np.unique(labels[borders]) + indices = np.arange(number + 1) + # mask all label indices that are connected to borders + label_mask = np.in1d(indices, borders_indices) + # create mask for pixels to clear + mask = label_mask[labels.ravel()].reshape(labels.shape) + + # clear border pixels + image[mask] = bgval + return image diff --git a/skimage/morphology/tests/test_clear_border.py b/skimage/morphology/tests/test_clear_border.py index c4cdd4af..6d1cf562 100644 --- a/skimage/morphology/tests/test_clear_border.py +++ b/skimage/morphology/tests/test_clear_border.py @@ -3,7 +3,7 @@ from numpy.testing import assert_array_equal, assert_equal from skimage.morphology import clear_border -def test_possible_hull(): +def test_clear_border(): image = np.array( [[0, 0, 0, 0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 1, 0, 0, 0, 0], @@ -25,7 +25,7 @@ def test_possible_hull(): # test background value result = clear_border(image.copy(), 1, 2) - assert_array_equal(result, 2 * image) + assert_array_equal(result, 2 * np.ones_like(image)) if __name__ == "__main__": From 1177cf1393e3ea0f4aee4a8ef14c5a577591075c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Mon, 27 Aug 2012 18:51:57 +0200 Subject: [PATCH 3/5] Move clear_border to segmentation package --- skimage/segmentation/__init__.py | 1 + skimage/{morphology => segmentation}/_clear_border.py | 0 skimage/{morphology => segmentation}/tests/test_clear_border.py | 2 +- 3 files changed, 2 insertions(+), 1 deletion(-) rename skimage/{morphology => segmentation}/_clear_border.py (100%) rename skimage/{morphology => segmentation}/tests/test_clear_border.py (94%) diff --git a/skimage/segmentation/__init__.py b/skimage/segmentation/__init__.py index 69a580c6..9dca2bc3 100644 --- a/skimage/segmentation/__init__.py +++ b/skimage/segmentation/__init__.py @@ -3,3 +3,4 @@ from ._felzenszwalb import felzenszwalb from ._slic import slic from ._quickshift import quickshift from .boundaries import find_boundaries, visualize_boundaries +from ._clear_border import clear_border diff --git a/skimage/morphology/_clear_border.py b/skimage/segmentation/_clear_border.py similarity index 100% rename from skimage/morphology/_clear_border.py rename to skimage/segmentation/_clear_border.py diff --git a/skimage/morphology/tests/test_clear_border.py b/skimage/segmentation/tests/test_clear_border.py similarity index 94% rename from skimage/morphology/tests/test_clear_border.py rename to skimage/segmentation/tests/test_clear_border.py index 6d1cf562..d87f3d25 100644 --- a/skimage/morphology/tests/test_clear_border.py +++ b/skimage/segmentation/tests/test_clear_border.py @@ -1,6 +1,6 @@ import numpy as np from numpy.testing import assert_array_equal, assert_equal -from skimage.morphology import clear_border +from skimage.segmentation import clear_border def test_clear_border(): From bbeaec6b3faebc0c3308423303228e6c6b8a7259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Thu, 30 Aug 2012 09:36:28 +0200 Subject: [PATCH 4/5] Add examples to doc string of clear_border --- skimage/segmentation/_clear_border.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/skimage/segmentation/_clear_border.py b/skimage/segmentation/_clear_border.py index 47de7e49..733f7000 100644 --- a/skimage/segmentation/_clear_border.py +++ b/skimage/segmentation/_clear_border.py @@ -21,6 +21,24 @@ def clear_border(image, buffer_size=0, bgval=0): image : (N, M) array Cleared binary image. + Examples + -------- + >>> import numpy as np + >>> from skimage.segmentation import clear_border + >>> image = np.array([[0, 0, 0, 0, 0, 0, 0, 1, 0], + ... [0, 0, 0, 0, 1, 0, 0, 0, 0], + ... [1, 0, 0, 1, 0, 1, 0, 0, 0], + ... [0, 0, 1, 1, 1, 1, 1, 0, 0], + ... [0, 1, 1, 1, 1, 1, 1, 1, 0], + ... [0, 0, 0, 0, 0, 0, 0, 0, 0]]) + >>> clear_border(image) + array([[0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 0, 0, 1, 0, 0, 0, 0], + [0, 0, 0, 1, 0, 1, 0, 0, 0], + [0, 0, 1, 1, 1, 1, 1, 0, 0], + [0, 1, 1, 1, 1, 1, 1, 1, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0]]) + """ rows, cols = image.shape From dd45f15ced95ed43b889f464b4116bb8f4124d99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Sch=C3=B6nberger?= Date: Thu, 30 Aug 2012 09:40:54 +0200 Subject: [PATCH 5/5] Use explicit keyword for dtype --- skimage/segmentation/_clear_border.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/skimage/segmentation/_clear_border.py b/skimage/segmentation/_clear_border.py index 733f7000..266e17e2 100644 --- a/skimage/segmentation/_clear_border.py +++ b/skimage/segmentation/_clear_border.py @@ -46,7 +46,7 @@ def clear_border(image, buffer_size=0, bgval=0): raise ValueError("buffer size may not be greater than image size") # create borders with buffer_size - borders = np.zeros_like(image, np.bool_) + borders = np.zeros_like(image, dtype=np.bool_) ext = buffer_size + 1 borders[:ext] = True borders[- ext:] = True