Merged the separate loops for SLIC-zero and SLIC into one, and some minor improvements based on feedback on Github.

This commit is contained in:
Michal Romaniuk
2014-01-21 20:08:07 +00:00
parent b4ac25200b
commit 131dea07a0
3 changed files with 28 additions and 45 deletions
+19 -36
View File
@@ -10,12 +10,13 @@ cimport numpy as cnp
from skimage.util import regular_grid
def _slic_cython(double[:, :, :, ::1] image_zyx,
double[:, ::1] segments,
float step,
Py_ssize_t max_iter,
double[::1] spacing,
bool slic_zero,
bint slic_zero,
):
"""Helper function for SLIC segmentation.
@@ -36,7 +37,6 @@ def _slic_cython(double[:, :, :, ::1] image_zyx,
slic_zero : bool
True to run SLIC-zero, False to run original SLIC.
Returns
-------
nearest_segments : 3D array of int, shape (Z, Y, X)
@@ -122,42 +122,25 @@ def _slic_cython(double[:, :, :, ::1] image_zyx,
x_min = <Py_ssize_t>max(cx - 2 * step_x, 0)
x_max = <Py_ssize_t>min(cx + 2 * step_x + 1, width)
# The loop is duplicated to avoid looking up slic_zero in every
# iteration but perhaps it's better to improve readability at
# the cost of performance.
if slic_zero:
for z in range(z_min, z_max):
dz = (sz * (cz - z)) ** 2
for y in range(y_min, y_max):
dy = (sy * (cy - y)) ** 2
for x in range(x_min, x_max):
dist_center = (dz + dy + (sx * (cx - x)) ** 2) * zyx_wt
dist_color = 0
for c in range(3, n_features):
dist_color += (image_zyx[z, y, x, c - 3]
- segments[k, c]) ** 2
for z in range(z_min, z_max):
dz = (sz * (cz - z)) ** 2
for y in range(y_min, y_max):
dy = (sy * (cy - y)) ** 2
for x in range(x_min, x_max):
dist_center = (dz + dy + (sx * (cx - x)) ** 2) * zyx_wt
dist_color = 0
for c in range(3, n_features):
dist_color += (image_zyx[z, y, x, c - 3]
- segments[k, c]) ** 2
if slic_zero:
dist_center += dist_color / max_dist_color[k]
else:
dist_center += dist_color
if distance[z, y, x] > dist_center:
nearest_segments[z, y, x] = k
distance[z, y, x] = dist_center
change = 1
else:
for z in range(z_min, z_max):
dz = (sz * (cz - z)) ** 2
for y in range(y_min, y_max):
dy = (sy * (cy - y)) ** 2
for x in range(x_min, x_max):
dist_center = (dz + dy + (sx * (cx - x)) ** 2) * zyx_wt
for c in range(3, n_features):
dist_center += (image_zyx[z, y, x, c - 3]
- segments[k, c]) ** 2
if distance[z, y, x] > dist_center:
nearest_segments[z, y, x] = k
distance[z, y, x] = dist_center
change = 1
if distance[z, y, x] > dist_center:
nearest_segments[z, y, x] = k
distance[z, y, x] = dist_center
change = 1
# stop if no pixel changed its segment
if change == 0:
+8 -9
View File
@@ -12,7 +12,8 @@ from skimage.color import rgb2lab
def slic(image, n_segments=100, compactness=10., max_iter=10, sigma=None,
spacing=None, multichannel=True, convert2lab=True, ratio=None,
enforce_connectivity=False, min_size_factor=0.5, max_size_factor=3):
enforce_connectivity=False, min_size_factor=0.5, max_size_factor=3,
slic_zero=False):
"""Segments image using k-means clustering in Color-(x,y,z) space.
Parameters
@@ -47,8 +48,6 @@ def slic(image, n_segments=100, compactness=10., max_iter=10, sigma=None,
Whether the input should be converted to Lab colorspace prior to
segmentation. For this purpose, the input is assumed to be RGB. Highly
recommended.
slic_zero: bool, optional
True to run SLIC-zero, False to run original SLIC.
ratio : float, optional
Synonym for `compactness`. This keyword is deprecated.
enforce_connectivity: bool, optional (default False)
@@ -59,6 +58,8 @@ def slic(image, n_segments=100, compactness=10., max_iter=10, sigma=None,
max_size_factor: float, optional
Proportion of the maximum connected segment size. A value of 3 works
in most of the cases.
slic_zero: bool, optional
True to run SLIC-zero, False to run original SLIC.
Returns
-------
labels : 2D or 3D array
@@ -169,21 +170,19 @@ def slic(image, n_segments=100, compactness=10., max_iter=10, sigma=None,
segments_y[..., np.newaxis],
segments_x[..., np.newaxis],
segments_color
], axis=-1).reshape(-1, 3 + image.shape[3])
], axis=-1).reshape(-1, 3 + image.shape[3])
segments = np.ascontiguousarray(segments)
# we do the scaling of ratio in the same way as in the SLIC paper
# so the values have the same meaning
step = float(max((step_z, step_y, step_x)))
ratio = float(1) / compactness
ratio = 1.0 / compactness
if slic_zero:
image = np.ascontiguousarray(image * ratio)
else:
image = np.ascontiguousarray(image * ratio)
# _slic_cython expects the image in zyx format... but isn't image in xyz
# format???
labels = _slic_cython(image, segments, step, max_iter, spacing, slic_zero)
if enforce_connectivity:
@@ -198,4 +197,4 @@ def slic(image, n_segments=100, compactness=10., max_iter=10, sigma=None,
if is_2d:
labels = labels[0]
return labels
return labels
+1
View File
@@ -147,6 +147,7 @@ def test_enforce_connectivity():
assert_equal(segments_connected, result_connected)
assert_equal(segments_disconnected, result_disconnected)
if __name__ == '__main__':
from numpy import testing