diff --git a/skimage/segmentation/random_walker_segmentation.py b/skimage/segmentation/random_walker_segmentation.py index 1fbec7ae..7c3916eb 100644 --- a/skimage/segmentation/random_walker_segmentation.py +++ b/skimage/segmentation/random_walker_segmentation.py @@ -169,13 +169,13 @@ def _mask_edges_weights(edges, weights, mask): # Reassign edges labels to 0, 1, ... edges_number - 1 order = np.searchsorted(np.unique(edges.ravel()), np.arange(max_node_index + 1)) - edges = order[edges] + edges = order[edges.astype(np.int64)] return edges, weights def _build_laplacian(data, spacing, mask=None, beta=50, multichannel=False): - l_x, l_y, l_z = tuple(data.shape[i] * spacing[i] for i in range(3)) + l_x, l_y, l_z = tuple(data.shape[i] for i in range(3)) edges = _make_graph_edges_3d(l_x, l_y, l_z) weights = _compute_weights_3d(data, spacing, beta=beta, eps=1.e-10, multichannel=multichannel) @@ -257,7 +257,7 @@ def random_walker(data, labels, beta=130, mode='bf', tol=1.e-3, copy=True, out-of-plane voxel spacing represents the third spatial dimension. `depth` is deprecated as of 0.9, in favor of `spacing`. spacing : iterable of floats - spacing between voxels in each spatial dimension. If `None`, then + Spacing between voxels in each spatial dimension. If `None`, then the spacing between pixels/voxels in each dimension is assumed 1. Returns @@ -357,9 +357,17 @@ def random_walker(data, labels, beta=130, mode='bf', tol=1.e-3, copy=True, '(see the docstrings)') if depth != 1.: warnings.warn('`depth` kwarg is deprecated, and will be removed in the' - ' next major version. Use `spacing` instead.') + ' next major release. Use `spacing` instead.') + + # Spacing kwarg checks if spacing is None: - spacing = (1., 1.) + (depth, ) + spacing = (1., 1.) + (depth, ) + elif len(spacing) == 2: + spacing = tuple(spacing) + (depth, ) + elif len(spacing) == 3: + pass + else: + raise ValueError('Input argument `spacing` incorrect, see docstring.') # Parse input data if not multichannel: diff --git a/skimage/segmentation/tests/test_random_walker.py b/skimage/segmentation/tests/test_random_walker.py index 050a8590..46a82d8e 100644 --- a/skimage/segmentation/tests/test_random_walker.py +++ b/skimage/segmentation/tests/test_random_walker.py @@ -8,16 +8,16 @@ def make_2d_syntheticdata(lx, ly=None): ly = lx np.random.seed(1234) data = np.zeros((lx, ly)) + 0.1 * np.random.randn(lx, ly) - small_l = int(lx / 5) - data[lx / 2 - small_l:lx / 2 + small_l, - ly / 2 - small_l:ly / 2 + small_l] = 1 - data[lx / 2 - small_l + 1:lx / 2 + small_l - 1, - ly / 2 - small_l + 1:ly / 2 + small_l - 1] = \ - 0.1 * np.random.randn(2 * small_l - 2, 2 * small_l - 2) - data[lx / 2 - small_l, ly / 2 - small_l / 8:ly / 2 + small_l / 8] = 0 + small_l = int(lx // 5) + data[lx // 2 - small_l:lx // 2 + small_l, + ly // 2 - small_l:ly // 2 + small_l] = 1 + data[lx // 2 - small_l + 1:lx // 2 + small_l - 1, + ly // 2 - small_l + 1:ly // 2 + small_l - 1] = ( + 0.1 * np.random.randn(2 * small_l - 2, 2 * small_l - 2)) + data[lx // 2 - small_l, ly // 2 - small_l // 8:ly // 2 + small_l // 8] = 0 seeds = np.zeros_like(data) - seeds[lx / 5, ly / 5] = 1 - seeds[lx / 2 + small_l / 4, ly / 2 - small_l / 4] = 2 + seeds[lx // 5, ly // 5] = 1 + seeds[lx // 2 + small_l // 4, ly // 2 - small_l // 4] = 2 return data, seeds @@ -28,21 +28,23 @@ def make_3d_syntheticdata(lx, ly=None, lz=None): lz = lx np.random.seed(1234) data = np.zeros((lx, ly, lz)) + 0.1 * np.random.randn(lx, ly, lz) - small_l = int(lx / 5) - data[lx / 2 - small_l:lx / 2 + small_l, - ly / 2 - small_l:ly / 2 + small_l, - lz / 2 - small_l:lz / 2 + small_l] = 1 - data[lx / 2 - small_l + 1:lx / 2 + small_l - 1, - ly / 2 - small_l + 1:ly / 2 + small_l - 1, - lz / 2 - small_l + 1:lz / 2 + small_l - 1] = 0 + small_l = int(lx // 5) + data[lx // 2 - small_l:lx // 2 + small_l, + ly // 2 - small_l:ly // 2 + small_l, + lz // 2 - small_l:lz // 2 + small_l] = 1 + data[lx // 2 - small_l + 1:lx // 2 + small_l - 1, + ly // 2 - small_l + 1:ly // 2 + small_l - 1, + lz // 2 - small_l + 1:lz // 2 + small_l - 1] = 0 # make a hole - hole_size = np.max([1, small_l / 8]) - data[lx / 2 - small_l, - ly / 2 - hole_size:ly / 2 + hole_size, - lz / 2 - hole_size:lz / 2 + hole_size] = 0 + hole_size = np.max([1, small_l // 8]) + data[lx // 2 - small_l, + ly // 2 - hole_size:ly // 2 + hole_size, + lz // 2 - hole_size:lz // 2 + hole_size] = 0 seeds = np.zeros_like(data) - seeds[lx / 5, ly / 5, lz / 5] = 1 - seeds[lx / 2 + small_l / 4, ly / 2 - small_l / 4, lz / 2 - small_l / 4] = 2 + seeds[lx // 5, ly // 5, lz // 5] = 1 + seeds[lx // 2 + small_l // 4, + ly // 2 - small_l // 4, + lz // 2 - small_l // 4] = 2 return data, seeds @@ -102,7 +104,7 @@ def test_types(): lx = 70 ly = 100 data, labels = make_2d_syntheticdata(lx, ly) - data = 255 * (data - data.min()) / (data.max() - data.min()) + data = 255 * (data - data.min()) // (data.max() - data.min()) data = data.astype(np.uint8) labels_cg_mg = random_walker(data, labels, beta=90, mode='cg_mg') assert (labels_cg_mg[25:45, 40:60] == 2).all() @@ -236,19 +238,19 @@ def test_spacing(): # `resize` is not yet 3D capable, so this must be done by looping in 2D. data_aniso = np.zeros((n, n * 2, n)) for i in range(data.shape[1]): - data_aniso[i, :, :] = resize(data[:, 1, :], (n * 1.5, n)) + data_aniso[i, :, :] = resize(data[:, 1, :], (n * 2, n)) # Generate new labels small_l = int(lx // 5) - labels_aniso = np.zeros_like(data_aniso) - labels_aniso[lx // 5, ly // 5, lz // 5] = 1 - labels_aniso[lx - small_l // 2, - ly // 2 + small_l // 4, - lz // 2 - small_l // 4] = 2 + labels_aniso2 = np.zeros_like(data_aniso) + labels_aniso2[lx // 5, ly // 5, lz // 5] = 1 + labels_aniso2[lx - small_l // 2, + ly // 2 + small_l // 4, + lz // 2 - small_l // 4] = 2 # Anisotropic along X - labels_aniso2 = random_walker(np.rollaxis(data_aniso, 1).copy(), - np.rollaxis(labels_aniso, 1).copy(), + labels_aniso2 = random_walker(data_aniso, + labels_aniso2, mode='cg', spacing=(2., 1., 1.)) assert (labels_aniso2[26:34, 13:17, 13:17] == 2).all()