mirror of
https://github.com/wassname/scikit-image.git
synced 2026-08-02 13:03:48 +08:00
Merge pull request #666 from jni/slic-scaling
Fix scaling (`ratio`) parameter in SLIC.
This commit is contained in:
@@ -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
|
||||
@@ -81,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
|
||||
@@ -92,7 +88,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)
|
||||
|
||||
@@ -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,15 +129,15 @@ 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))) / compactness
|
||||
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,
|
||||
ratio, max_iter, n_segments)
|
||||
max_iter, n_segments)
|
||||
if segment_map.shape[0] == 1:
|
||||
segment_map = segment_map[0]
|
||||
return segment_map
|
||||
|
||||
@@ -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)
|
||||
@@ -79,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)):
|
||||
|
||||
Reference in New Issue
Block a user