Merge pull request #2087 from jmetz/clearborder3d

Add nD support to clear_border
This commit is contained in:
Egor Panfilov
2016-05-17 16:27:52 +03:00
2 changed files with 116 additions and 12 deletions
+14 -12
View File
@@ -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
@@ -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()