Add spacing support for new, speeded-up SLIC

This commit is contained in:
Juan Nunez-Iglesias
2013-09-16 17:52:25 +10:00
parent 610a0d1793
commit 846765e5f9
3 changed files with 39 additions and 6 deletions
+11 -4
View File
@@ -12,7 +12,8 @@ from skimage.util import regular_grid
def _slic_cython(double[:, :, :, ::1] image_zyx,
double[:, ::1] segments,
Py_ssize_t max_iter):
Py_ssize_t max_iter,
double[:] spacing):
"""Helper function for SLIC segmentation.
Parameters
@@ -23,6 +24,7 @@ def _slic_cython(double[:, :, :, ::1] image_zyx,
The initial centroids obtained by SLIC as [Z, Y, X, C...].
max_iter : int
The maximum number of k-means iterations.
spacing : 1D array of double, shape (3,)
Returns
-------
@@ -55,6 +57,11 @@ def _slic_cython(double[:, :, :, ::1] image_zyx,
cdef char change
cdef double dist_center, cx, cy, cz, dy, dz
cdef double sz, sy, sx
sz = spacing[0]
sy = spacing[1]
sx = spacing[2]
for i in range(max_iter):
change = 0
distance[:, :, :] = DBL_MAX
@@ -76,11 +83,11 @@ def _slic_cython(double[:, :, :, ::1] image_zyx,
x_max = <Py_ssize_t>min(cx + 2 * step_x + 1, width)
for z in range(z_min, z_max):
dz = (cz - z) ** 2
dz = (sz * (cz - z)) ** 2
for y in range(y_min, y_max):
dy = (cy - y) ** 2
dy = (sy * (cy - y)) ** 2
for x in range(x_min, x_max):
dist_center = dz + dy + (cx - x) ** 2
dist_center = dz + dy + (sx * (cx - x)) ** 2
for c in range(3, n_features):
dist_center += (image_zyx[z, y, x, c - 3]
- segments[k, c]) ** 2
+10 -2
View File
@@ -11,7 +11,7 @@ from skimage.color import rgb2lab
def slic(image, n_segments=100, compactness=10., max_iter=10, sigma=None,
multichannel=True, convert2lab=True, ratio=None):
spacing=None, multichannel=True, convert2lab=True, ratio=None):
"""Segments image using k-means clustering in Color-(x,y,z) space.
Parameters
@@ -31,6 +31,9 @@ def slic(image, n_segments=100, compactness=10., max_iter=10, sigma=None,
Width of Gaussian smoothing kernel for pre-processing for each
dimension of the image. The same sigma is applied to each dimension in
case of a scalar value. Zero means no smoothing.
spacing : (3,) array-like of floats, optional
The voxel spacing along each image dimension. By default, `slic`
assumes uniform spacing (same voxel resolution along z, y and x).
multichannel : bool, optional
Whether the last axis of the image is to be interpreted as multiple
channels or another spatial dimension.
@@ -103,11 +106,16 @@ def slic(image, n_segments=100, compactness=10., max_iter=10, sigma=None,
# Add channel as single last dimension
image = image[..., np.newaxis]
if spacing is None:
spacing = np.ones(3)
elif type(spacing) in [list, tuple]:
spacing = np.array(spacing, float)
if not isinstance(sigma, coll.Iterable):
sigma = np.array([sigma, sigma, sigma], float)
elif type(sigma) in [list, tuple]:
sigma = np.array(sigma, float)
if (sigma > 0).any():
sigma /= spacing.astype(float)
sigma = list(sigma) + [0]
image = ndimage.gaussian_filter(image, sigma)
@@ -139,7 +147,7 @@ def slic(image, n_segments=100, compactness=10., max_iter=10, sigma=None,
ratio = float(max((step_z, step_y, step_x))) / compactness
image = np.ascontiguousarray(image * ratio)
labels = _slic_cython(image, segments, max_iter)
labels = _slic_cython(image, segments, max_iter, spacing)
if is2d:
labels = labels[0]
+18
View File
@@ -101,6 +101,24 @@ def test_list_sigma():
assert_equal(seg_sigma, result_sigma)
def test_spacing():
rnd = np.random.RandomState(0)
img = np.array([[1, 1, 1, 0, 0],
[1, 1, 0, 0, 0]], np.float)
result_non_spaced = np.array([[0, 0, 0, 1, 1],
[0, 0, 1, 1, 1]], np.int)
result_spaced = np.array([[0, 0, 0, 0, 0],
[1, 1, 1, 1, 1]], np.int)
img += 0.1 * rnd.normal(size=img.shape)
seg_non_spaced = slic(img, n_segments=2, sigma=0, multichannel=False,
compactness=1.0)
seg_spaced = slic(img, n_segments=2, sigma=0, spacing=[1, 500, 1],
compactness=1.0, multichannel=False)
assert_equal(seg_non_spaced, result_non_spaced)
assert_equal(seg_spaced, result_spaced)
if __name__ == '__main__':
from numpy import testing
testing.run_module_suite()