diff --git a/doc/examples/plot_segmentations.py b/doc/examples/plot_segmentations.py index a8ee7cea..99bfefcc 100644 --- a/doc/examples/plot_segmentations.py +++ b/doc/examples/plot_segmentations.py @@ -7,7 +7,8 @@ This example compares three popular low-level image segmentation methods. As it is difficult to obtain good segmentations, and the definition of "good" often depends on the application, these methods are usually used for obtaining an oversegmentation, also known as superpixels. These superpixels then serve as -a basis for more sophisticated algorithms such as CRFs. +a basis for more sophisticated algorithms such as conditional random fields +(CRF). Felzenszwalb's efficient graph based segmentation diff --git a/skimage/graph/mcp.py b/skimage/graph/mcp.py index 68921371..28843cbf 100644 --- a/skimage/graph/mcp.py +++ b/skimage/graph/mcp.py @@ -1,7 +1,8 @@ from ._mcp import MCP, MCP_Geometric, make_offsets -def route_through_array(array, start, end, fully_connected=True, geometric=True): +def route_through_array(array, start, end, fully_connected=True, + geometric=True): """Simple example of how to use the MCP and MCP_Geometric classes. See the MCP and MCP_Geometric class documentation for explanation of the @@ -27,7 +28,54 @@ def route_through_array(array, start, end, fully_connected=True, geometric=True) path : list List of n-d index tuples defining the path from `start` to `end`. cost : float - Cost of the path. + Cost of the path. If `geometric` is False, the cost of the path is + the sum of the values of `array` along the path. If `geometric` is + True, a finer computation is made (see the documentation of the + MCP_Geometric class). + + See Also + -------- + MCP, MCP_Geometric + + Examples + -------- + >>> from skimage.graph import route_through_array + >>> image = np.array([[1, 3], [10, 12]]) + >>> image + array([[ 1, 3], + [10, 12]]) + >>> # Forbid diagonal steps + >>> route_through_array(image, [0, 0], [1, 1], fully_connected=False) + ([(0, 0), (0, 1), (1, 1)], 9.5) + >>> # Now allow diagonal steps: the path goes directly from start to end + >>> route_through_array(image, [0, 0], [1, 1]) + ([(0, 0), (1, 1)], 9.1923881554251192) + >>> # Cost is the sum of array values along the path (16 = 1 + 3 + 12) + >>> route_through_array(image, [0, 0], [1, 1], fully_connected=False, + ... geometric=False) + ([(0, 0), (0, 1), (1, 1)], 16.0) + >>> # Larger array where we display the path that is selected + >>> image = np.arange((36)).reshape((6, 6)) + >>> image + array([[ 0, 1, 2, 3, 4, 5], + [ 6, 7, 8, 9, 10, 11], + [12, 13, 14, 15, 16, 17], + [18, 19, 20, 21, 22, 23], + [24, 25, 26, 27, 28, 29], + [30, 31, 32, 33, 34, 35]]) + >>> # Find the path with lowest cost + >>> indices, weight = route_through_array(image, (0, 0), (5, 5)) + >>> indices = np.array(indices).T + >>> path = np.zeros_like(image) + >>> path[indices[0], indices[1]] = 1 + >>> path + array([[1, 1, 1, 1, 1, 0], + [0, 0, 0, 0, 0, 1], + [0, 0, 0, 0, 0, 1], + [0, 0, 0, 0, 0, 1], + [0, 0, 0, 0, 0, 1], + [0, 0, 0, 0, 0, 1]]) + """ start, end = tuple(start), tuple(end) if geometric: diff --git a/skimage/segmentation/_quickshift.pyx b/skimage/segmentation/_quickshift.pyx index 57be1040..b465eb08 100644 --- a/skimage/segmentation/_quickshift.pyx +++ b/skimage/segmentation/_quickshift.pyx @@ -13,8 +13,8 @@ from ..color import rgb2lab @cython.boundscheck(False) @cython.wraparound(False) @cython.cdivision(True) -def quickshift(image, ratio=1., float kernel_size=5, max_dist=10, return_tree=False, - sigma=0, convert2lab=True, random_seed=None): +def quickshift(image, ratio=1., float kernel_size=5, max_dist=10, + return_tree=False, sigma=0, convert2lab=True, random_seed=None): """Segments image using quickshift clustering in Color-(x,y) space. Produces an oversegmentation of the image using the quickshift mode-seeking @@ -106,7 +106,8 @@ def quickshift(image, ratio=1., float kernel_size=5, max_dist=10, return_tree=Fa for c_ in range(c_min, c_max): dist = 0 for channel in range(channels): - dist += (current_pixel_p[channel] - image_c[r_, c_, channel])**2 + dist += (current_pixel_p[channel] - + image_c[r_, c_, channel])**2 dist += (r - r_)**2 + (c - c_)**2 densities[r, c] += exp(-dist / (2 * kernel_size**2)) current_pixel_p += channels @@ -132,9 +133,11 @@ def quickshift(image, ratio=1., float kernel_size=5, max_dist=10, return_tree=Fa if densities[r_, c_] > current_density: dist = 0 # We compute the distances twice since otherwise - # we get crazy memory overhead (width * height * windowsize**2) + # we get crazy memory overhead + # (width * height * windowsize**2) for channel in range(channels): - dist += (current_pixel_p[channel] - image_c[r_, c_, channel])**2 + dist += (current_pixel_p[channel] - + image_c[r_, c_, channel])**2 dist += (r - r_)**2 + (c - c_)**2 if dist < closest: closest = dist diff --git a/skimage/segmentation/_slic.pyx b/skimage/segmentation/_slic.pyx index ecb58efe..d0e4c2a3 100644 --- a/skimage/segmentation/_slic.pyx +++ b/skimage/segmentation/_slic.pyx @@ -14,6 +14,8 @@ def slic(image, n_segments=100, ratio=10., max_iter=10, sigma=1, ---------- image : (width, height, 3) ndarray Input image. + n_segments : int + The (approximate) number of labels in the segmented output image. ratio: float Balances color-space proximity and image-space proximity. Higher values give more weight to color-space. @@ -42,6 +44,14 @@ def slic(image, n_segments=100, ratio=10., max_iter=10, sigma=1, Pascal Fua, and Sabine Süsstrunk, SLIC Superpixels Compared to State-of-the-art Superpixel Methods, TPAMI, May 2012. + Examples + -------- + >>> from skimage.segmentation import slic + >>> from skimage.data import lena + >>> img = lena() + >>> segments = slic(img, n_segments=100, ratio=10) + >>> # Increasing the ratio parameter yields more square regions + >>> segments = slic(img, n_segments=100, ratio=20) """ image = np.atleast_3d(image) if image.shape[2] != 3: