From aadd346964a192a4ced9b177e03d1a201e0f72c9 Mon Sep 17 00:00:00 2001 From: Juan Nunez-Iglesias Date: Mon, 22 Jul 2013 20:19:24 +1000 Subject: [PATCH 1/5] Fix ratio scaling in SLIC --- skimage/segmentation/slic_superpixels.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/skimage/segmentation/slic_superpixels.py b/skimage/segmentation/slic_superpixels.py index 2caf8ade..478093a1 100644 --- a/skimage/segmentation/slic_superpixels.py +++ b/skimage/segmentation/slic_superpixels.py @@ -122,11 +122,11 @@ def slic(image, n_segments=100, ratio=10., max_iter=10, sigma=1, means = np.ascontiguousarray(means) # we do the scaling of ratio in the same way as in the SLIC paper # so the values have the same meaning - ratio = (ratio / float(max((step_z, step_y, step_x)))) ** 2 + ratio = float(max((step_z, step_y, step_x))) / ratio image_zyx = np.concatenate([grid_z[..., np.newaxis], grid_y[..., np.newaxis], grid_x[..., np.newaxis], - image / ratio], axis=-1).copy("C") + image * ratio], axis=-1).copy("C") nearest_mean = np.zeros((depth, height, width), dtype=np.intp) distance = np.empty((depth, height, width), dtype=np.float) segment_map = _slic_cython(image_zyx, nearest_mean, distance, means, From af3ea5f81784cfbaed37d4a25f670751e426f2b4 Mon Sep 17 00:00:00 2001 From: Juan Nunez-Iglesias Date: Thu, 25 Jul 2013 00:23:01 +1000 Subject: [PATCH 2/5] Remove unused 'ratio' argument from _slic_cython --- skimage/segmentation/_slic.pyx | 8 +++----- skimage/segmentation/slic_superpixels.py | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/skimage/segmentation/_slic.pyx b/skimage/segmentation/_slic.pyx index f6c6788c..055907e9 100644 --- a/skimage/segmentation/_slic.pyx +++ b/skimage/segmentation/_slic.pyx @@ -17,7 +17,7 @@ def _slic_cython(double[:, :, :, ::1] image_zyx, long[:, :, ::1] nearest_mean, double[:, :, ::1] distance, double[:, ::1] means, - float ratio, int max_iter, int n_segments): + int max_iter, int n_segments): """Helper function for SLIC segmentation. Parameters @@ -32,8 +32,6 @@ def _slic_cython(double[:, :, :, ::1] image_zyx, The (initially infinity) array of distances to the nearest centroid. means : 2D np.ndarray of double, shape (n_segments, 6) The centroids obtained by SLIC. - ratio : float - The ratio of xyz-space and colorspace in the clustering. max_iter : int The maximum number of k-means iterations. n_segments : int @@ -58,7 +56,6 @@ def _slic_cython(double[:, :, :, ::1] image_zyx, cdef Py_ssize_t i, k, x, y, z, x_min, x_max, y_min, y_max, z_min, z_max, \ changes cdef double dist_mean - cdef double tmp for i in range(max_iter): changes = 0 @@ -92,7 +89,8 @@ def _slic_cython(double[:, :, :, ::1] image_zyx, nearest_mean_ravel = np.asarray(nearest_mean).ravel() means_list = [] for j in range(6): - image_zyx_ravel = np.ascontiguousarray(image_zyx[:, :, :, j]).ravel() + image_zyx_ravel = ( + np.ascontiguousarray(image_zyx[:, :, :, j]).ravel()) means_list.append(np.bincount(nearest_mean_ravel, image_zyx_ravel)) in_mean = np.bincount(nearest_mean_ravel) diff --git a/skimage/segmentation/slic_superpixels.py b/skimage/segmentation/slic_superpixels.py index 478093a1..cef668ef 100644 --- a/skimage/segmentation/slic_superpixels.py +++ b/skimage/segmentation/slic_superpixels.py @@ -130,7 +130,7 @@ def slic(image, n_segments=100, ratio=10., max_iter=10, sigma=1, nearest_mean = np.zeros((depth, height, width), dtype=np.intp) distance = np.empty((depth, height, width), dtype=np.float) segment_map = _slic_cython(image_zyx, nearest_mean, distance, means, - ratio, max_iter, n_segments) + max_iter, n_segments) if segment_map.shape[0] == 1: segment_map = segment_map[0] return segment_map From 3e99079107291e956e387981578ace4f18e479cd Mon Sep 17 00:00:00 2001 From: Juan Nunez-Iglesias Date: Thu, 25 Jul 2013 00:24:04 +1000 Subject: [PATCH 3/5] Precision issues appear to have vanished --- skimage/segmentation/_slic.pyx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/skimage/segmentation/_slic.pyx b/skimage/segmentation/_slic.pyx index 055907e9..d4121721 100644 --- a/skimage/segmentation/_slic.pyx +++ b/skimage/segmentation/_slic.pyx @@ -78,8 +78,7 @@ def _slic_cython(double[:, :, :, ::1] image_zyx, # squaring itself. mine can't (with O2) tmp = image_zyx[z, y, x, c] - means[k, c] dist_mean += tmp * tmp - # some precision issue here. Doesnt work if testing ">" - if distance[z, y, x] - dist_mean > 1e-10: + if distance[z, y, x] > dist_mean: nearest_mean[z, y, x] = k distance[z, y, x] = dist_mean changes = 1 From 878c562a4528b1515c62a1e58800dff2a411757d Mon Sep 17 00:00:00 2001 From: Juan Nunez-Iglesias Date: Mon, 29 Jul 2013 00:28:38 +1000 Subject: [PATCH 4/5] Replace 'ratio' kwarg with 'compactness' in SLIC --- skimage/segmentation/slic_superpixels.py | 19 +++++++++++++------ skimage/segmentation/tests/test_slic.py | 5 +++-- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/skimage/segmentation/slic_superpixels.py b/skimage/segmentation/slic_superpixels.py index cef668ef..b905f199 100644 --- a/skimage/segmentation/slic_superpixels.py +++ b/skimage/segmentation/slic_superpixels.py @@ -10,8 +10,8 @@ from ..color import rgb2lab, gray2rgb, guess_spatial_dimensions from ._slic import _slic_cython -def slic(image, n_segments=100, ratio=10., max_iter=10, sigma=1, - multichannel=None, convert2lab=True): +def slic(image, n_segments=100, compactness=10., max_iter=10, sigma=1, + multichannel=None, convert2lab=True, ratio=None): """Segments image using k-means clustering in Color-(x,y) space. Parameters @@ -21,9 +21,10 @@ def slic(image, n_segments=100, ratio=10., max_iter=10, sigma=1, (see `multichannel` parameter). n_segments : int, optional (default: 100) The (approximate) number of labels in the segmented output image. - ratio: float, optional (default: 10) - Balances color-space proximity and image-space proximity. - Higher values give more weight to color-space. + compactness: float, optional (default: 10) + Balances color-space proximity and image-space proximity. Higher + values give more weight to image-space. As `compactness` tends to + infinity, superpixel shapes become square/cubic. max_iter : int, optional (default: 10) Maximum number of iterations of k-means. sigma : float, optional (default: 1) @@ -38,6 +39,8 @@ def slic(image, n_segments=100, ratio=10., max_iter=10, sigma=1, Whether the input should be converted to Lab colorspace prior to segmentation. For this purpose, the input is assumed to be RGB. Highly recommended. + ratio : float, optional + Synonym for `compactness`. This keyword is deprecated. Returns ------- @@ -79,6 +82,10 @@ def slic(image, n_segments=100, ratio=10., max_iter=10, sigma=1, >>> # Increasing the ratio parameter yields more square regions >>> segments = slic(img, n_segments=100, ratio=20) """ + if ratio is not None: + msg = 'Keyword `ratio` is deprecated. Use `compactness` instead.' + warnings.warn(msg) + compactness = ratio spatial_dims = guess_spatial_dimensions(image) if spatial_dims is None and multichannel is None: msg = ("Images with dimensions (M, N, 3) are interpreted as 2D+RGB" + @@ -122,7 +129,7 @@ def slic(image, n_segments=100, ratio=10., max_iter=10, sigma=1, means = np.ascontiguousarray(means) # we do the scaling of ratio in the same way as in the SLIC paper # so the values have the same meaning - ratio = float(max((step_z, step_y, step_x))) / ratio + ratio = float(max((step_z, step_y, step_x))) / compactness image_zyx = np.concatenate([grid_z[..., np.newaxis], grid_y[..., np.newaxis], grid_x[..., np.newaxis], diff --git a/skimage/segmentation/tests/test_slic.py b/skimage/segmentation/tests/test_slic.py index d0539cd2..8da5bcb9 100644 --- a/skimage/segmentation/tests/test_slic.py +++ b/skimage/segmentation/tests/test_slic.py @@ -16,7 +16,7 @@ def test_color_2d(): img[img < 0] = 0 with warnings.catch_warnings(): warnings.simplefilter("ignore") - seg = slic(img, sigma=0, n_segments=4) + seg = slic(img, n_segments=4, sigma=0) # we expect 4 segments assert_equal(len(np.unique(seg)), 4) @@ -35,7 +35,8 @@ def test_gray_2d(): img += 0.0033 * rnd.normal(size=img.shape) img[img > 1] = 1 img[img < 0] = 0 - seg = slic(img, sigma=0, n_segments=4, ratio=20.0, multichannel=False) + seg = slic(img, sigma=0, n_segments=4, compactness=20.0, + multichannel=False) assert_equal(len(np.unique(seg)), 4) assert_array_equal(seg[:10, :10], 0) From 72833f1729d451bbfb911ca17fe08c489f6ebe6f Mon Sep 17 00:00:00 2001 From: Juan Nunez-Iglesias Date: Mon, 29 Jul 2013 00:30:51 +1000 Subject: [PATCH 5/5] Do not use 'ratio' in test_slic.py either --- skimage/segmentation/tests/test_slic.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/skimage/segmentation/tests/test_slic.py b/skimage/segmentation/tests/test_slic.py index 8da5bcb9..9e6a39e2 100644 --- a/skimage/segmentation/tests/test_slic.py +++ b/skimage/segmentation/tests/test_slic.py @@ -80,7 +80,8 @@ def test_gray_3d(): img += 0.001 * rnd.normal(size=img.shape) img[img > 1] = 1 img[img < 0] = 0 - seg = slic(img, sigma=0, n_segments=8, ratio=20.0, multichannel=False) + seg = slic(img, sigma=0, n_segments=8, compactness=20.0, + multichannel=False) assert_equal(len(np.unique(seg)), 8) for s, c in zip(slices, range(8)):