mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-13 01:17:49 +08:00
Add spacing support for new, speeded-up SLIC
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user