diff --git a/skimage/segmentation/_clear_border.py b/skimage/segmentation/_clear_border.py index a44f0785..3a920e44 100644 --- a/skimage/segmentation/_clear_border.py +++ b/skimage/segmentation/_clear_border.py @@ -5,12 +5,10 @@ from ..measure import label def clear_border(labels, buffer_size=0, bgval=0, in_place=False): """Clear objects connected to the label image border. - The changes will be applied directly to the input. - Parameters ---------- - labels : (N, M) array of int - Label or binary image. + labels : (M[, N[, ..., P]]) array of int or bool + Imaging data labels. buffer_size : int, optional The width of the border examined. By default, only objects that touch the outside of the image are removed. @@ -21,8 +19,8 @@ def clear_border(labels, buffer_size=0, bgval=0, in_place=False): Returns ------- - labels : (N, M) array - Cleared binary image. + out : (M[, N[, ..., P]]) array + Imaging data labels with cleared borders Examples -------- @@ -45,17 +43,21 @@ def clear_border(labels, buffer_size=0, bgval=0, in_place=False): """ image = labels - rows, cols = image.shape - if buffer_size >= rows or buffer_size >= cols: + if any( ( buffer_size >= s for s in image.shape)): raise ValueError("buffer size may not be greater than image size") # create borders with buffer_size borders = np.zeros_like(image, dtype=np.bool_) ext = buffer_size + 1 - borders[:ext] = True - borders[- ext:] = True - borders[:, :ext] = True - borders[:, - ext:] = True + slstart = slice(ext) + slend = slice(-ext, None) + slices = [slice(s) for s in image.shape] + for d in range(image.ndim): + slicedim = list(slices) + slicedim[d] = slstart + borders[slicedim] = True + slicedim[d] = slend + borders[slicedim] = True # Re-label, in case we are dealing with a binary image # and to get consistent labeling diff --git a/skimage/segmentation/tests/test_clear_border.py b/skimage/segmentation/tests/test_clear_border.py index b626ea2b..34ba5979 100644 --- a/skimage/segmentation/tests/test_clear_border.py +++ b/skimage/segmentation/tests/test_clear_border.py @@ -28,6 +28,36 @@ def test_clear_border(): assert_array_equal(result, 2 * np.ones_like(image)) +def test_clear_border_3d(): + image = np.array([ + [[0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [1, 0, 0, 0]], + [[0, 0, 0, 0], + [0, 1, 1, 0], + [0, 0, 1, 0], + [0, 0, 0, 0]], + [[0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0], + [0, 0, 0, 0]], + ]) + # test default case + result = clear_border(image.copy()) + ref = image.copy() + ref[0, 3, 0] = 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(), buffer_size=1, bgval=2) + assert_array_equal(result, 2 * np.ones_like(image)) + + def test_clear_border_non_binary(): image = np.array([[1, 2, 3, 1, 2], [3, 3, 5, 4, 2], @@ -44,6 +74,42 @@ def test_clear_border_non_binary(): assert_(not np.all(image == result)) +def test_clear_border_non_binary_3d(): + image3d = np.array( + [[[1, 2, 3, 1, 2], + [3, 3, 3, 4, 2], + [3, 4, 3, 4, 2], + [3, 3, 2, 1, 2]], + [[1, 2, 3, 1, 2], + [3, 3, 5, 4, 2], + [3, 4, 5, 4, 2], + [3, 3, 2, 1, 2]], + [[1, 2, 3, 1, 2], + [3, 3, 3, 4, 2], + [3, 4, 3, 4, 2], + [3, 3, 2, 1, 2]], + ]) + + result = clear_border(image3d) + expected = np.array( + [[[0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0]], + [[0, 0, 0, 0, 0], + [0, 0, 5, 0, 0], + [0, 0, 5, 0, 0], + [0, 0, 0, 0, 0]], + [[0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0]], + ]) + + assert_array_equal(result, expected) + assert_(not np.all(image3d == result)) + + def test_clear_border_non_binary_inplace(): image = np.array([[1, 2, 3, 1, 2], [3, 3, 5, 4, 2], @@ -59,5 +125,41 @@ def test_clear_border_non_binary_inplace(): assert_array_equal(result, expected) assert_array_equal(image, result) + +def test_clear_border_non_binary_inplace_3d(): + image3d = np.array( + [[[1, 2, 3, 1, 2], + [3, 3, 3, 4, 2], + [3, 4, 3, 4, 2], + [3, 3, 2, 1, 2]], + [[1, 2, 3, 1, 2], + [3, 3, 5, 4, 2], + [3, 4, 5, 4, 2], + [3, 3, 2, 1, 2]], + [[1, 2, 3, 1, 2], + [3, 3, 3, 4, 2], + [3, 4, 3, 4, 2], + [3, 3, 2, 1, 2]], + ]) + + result = clear_border(image3d, in_place=True) + expected = np.array( + [[[0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0]], + [[0, 0, 0, 0, 0], + [0, 0, 5, 0, 0], + [0, 0, 5, 0, 0], + [0, 0, 0, 0, 0]], + [[0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0], + [0, 0, 0, 0, 0]], + ]) + + assert_array_equal(result, expected) + assert_array_equal(image3d, result) + if __name__ == "__main__": np.testing.run_module_suite()