diff --git a/skimage/__init__.py b/skimage/__init__.py index b1c331ff..ad37f425 100644 --- a/skimage/__init__.py +++ b/skimage/__init__.py @@ -88,7 +88,6 @@ test = _setup_test() test_verbose = _setup_test(verbose=True) - def get_log(name=None): """Return a console logger. diff --git a/skimage/filter/tests/test_thresholding.py b/skimage/filter/tests/test_thresholding.py index d17f9b84..97d3d9e3 100644 --- a/skimage/filter/tests/test_thresholding.py +++ b/skimage/filter/tests/test_thresholding.py @@ -77,13 +77,11 @@ def test_otsu_camera_image(): assert 86 < threshold_otsu(camera) < 88 - def test_otsu_coins_image(): coins = skimage.img_as_ubyte(data.coins()) assert 106 < threshold_otsu(coins) < 108 - def test_otsu_coins_image_as_float(): coins = skimage.img_as_float(data.coins()) assert 0.41 < threshold_otsu(coins) < 0.42 diff --git a/skimage/segmentation/__init__.py b/skimage/segmentation/__init__.py index 2fb6902c..b1e6f783 100644 --- a/skimage/segmentation/__init__.py +++ b/skimage/segmentation/__init__.py @@ -3,6 +3,3 @@ from .felzenszwalb import felzenszwalb_segmentation from .slic import slic from .quickshift import quickshift from .boundaries import find_boundaries, visualize_boundaries - -__all__ = [random_walker, quickshift, felzenszwalb_segmentation, - slic, find_boundaries, visualize_boundaries] diff --git a/skimage/segmentation/_felzenszwalb.pyx b/skimage/segmentation/_felzenszwalb.pyx index b66fbd16..f4069274 100644 --- a/skimage/segmentation/_felzenszwalb.pyx +++ b/skimage/segmentation/_felzenszwalb.pyx @@ -8,7 +8,7 @@ from ..util import img_as_float def _felzenszwalb_segmentation_grey(image, scale=1, sigma=0.8, min_size=20): - """Computes Felsenszwalb's efficient graph based segmentation for a single channel. + """Felzenszwalb's efficient graph based segmentation for a single channel. Produces an oversegmentation of a 2d image using a fast, minimum spanning tree based clustering on the image grid. The parameter ``scale`` sets an @@ -37,8 +37,8 @@ def _felzenszwalb_segmentation_grey(image, scale=1, sigma=0.8, min_size=20): Integer mask indicating segment labels. """ if image.ndim != 2: - raise ValueError("This algorithm works only on single-channel 2d images." - "Got image of shape %s" % str(image.shape)) + raise ValueError("This algorithm works only on single-channel 2d" + "images. Got image of shape %s" % str(image.shape)) image = img_as_float(image) # rescale scale to behave like in reference implementation scale = float(scale) / 255. @@ -49,16 +49,19 @@ def _felzenszwalb_segmentation_grey(image, scale=1, sigma=0.8, min_size=20): down_cost = np.abs((image[:, 1:] - image[:, :-1])) dright_cost = np.abs((image[1:, 1:] - image[:-1, :-1])) uright_cost = np.abs((image[1:, :-1] - image[:-1, 1:])) - cdef np.ndarray[np.float_t, ndim=1] costs = np.hstack([right_cost.ravel(), down_cost.ravel(), - dright_cost.ravel(), uright_cost.ravel()]).astype(np.float) + cdef np.ndarray[np.float_t, ndim=1] costs = np.hstack([right_cost.ravel(), + down_cost.ravel(), dright_cost.ravel(), + uright_cost.ravel()]).astype(np.float) # compute edges between pixels: width, height = image.shape[:2] - cdef np.ndarray[np.int_t, ndim=2] segments = np.arange(width * height).reshape(width, height) + cdef np.ndarray[np.int_t, ndim=2] segments \ + = np.arange(width * height).reshape(width, height) right_edges = np.c_[segments[1:, :].ravel(), segments[:-1, :].ravel()] down_edges = np.c_[segments[:, 1:].ravel(), segments[:, :-1].ravel()] dright_edges = np.c_[segments[1:, 1:].ravel(), segments[:-1, :-1].ravel()] uright_edges = np.c_[segments[:-1, 1:].ravel(), segments[1:, :-1].ravel()] - cdef np.ndarray[np.int_t, ndim=2] edges = np.vstack([right_edges, down_edges, dright_edges, uright_edges]) + cdef np.ndarray[np.int_t, ndim=2] edges \ + = np.vstack([right_edges, down_edges, dright_edges, uright_edges]) # initialize data structures for segment size # and inner cost, then start greedy iteration over edges. edge_queue = np.argsort(costs) @@ -67,7 +70,8 @@ def _felzenszwalb_segmentation_grey(image, scale=1, sigma=0.8, min_size=20): cdef np.int_t *segments_p = segments.data cdef np.int_t *edges_p = edges.data cdef np.float_t *costs_p = costs.data - cdef np.ndarray[np.int_t, ndim=1] segment_size = np.ones(width * height, dtype=np.int) + cdef np.ndarray[np.int_t, ndim=1] segment_size \ + = np.ones(width * height, dtype=np.int) # inner cost of segments cdef np.ndarray[np.float_t, ndim=1] cint = np.zeros(width * height) cdef int seg0, seg1, seg_new diff --git a/skimage/segmentation/quickshift.pyx b/skimage/segmentation/quickshift.pyx index be805a37..37c9294b 100644 --- a/skimage/segmentation/quickshift.pyx +++ b/skimage/segmentation/quickshift.pyx @@ -16,14 +16,16 @@ cdef extern from "math.h": @cython.boundscheck(False) @cython.wraparound(False) @cython.cdivision(True) -def quickshift(image, ratio=1., kernel_size=5, max_dist=10, return_tree=False, sigma=0, convert2lab=True, random_seed=None): +def quickshift(image, ratio=1., 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 algorithm. + Produces an oversegmentation of the image using the quickshift mode-seeking + algorithm. Parameters ---------- - image: (width, height, channels) ndarray + image: (width, height, channels) ndarray Input image ratio: float, between 0 and 1. Balances color-space proximity and image-space proximity. @@ -39,8 +41,8 @@ def quickshift(image, ratio=1., kernel_size=5, max_dist=10, return_tree=False, s sigma: float Width for Gaussian smoothing as preprocessing. Zero means no smoothing. convert2lab: bool - Whether the input should be converted to Lab colorspace prior to segmentation. - For this purpose, the input is assumed to be RGB. + Whether the input should be converted to Lab colorspace prior to + segmentation. For this purpose, the input is assumed to be RGB. random_seed: None or int Random seed used for breaking ties @@ -51,12 +53,14 @@ def quickshift(image, ratio=1., kernel_size=5, max_dist=10, return_tree=False, s Notes ----- - The authors advocate to convert the image to Lab color space prior to segmentation, though - this is not strictly necessary. For this to work, the image must be given in RGB format. + The authors advocate to convert the image to Lab color space prior to + segmentation, though this is not strictly necessary. For this to work, the + image must be given in RGB format. References ---------- - .. [1] Quick shift and kernel methods for mode seeking, Vedaldi, A. and Soatto, S. + .. [1] Quick shift and kernel methods for mode seeking, + Vedaldi, A. and Soatto, S. European Conference on Computer Vision, 2008 @@ -68,7 +72,8 @@ def quickshift(image, ratio=1., kernel_size=5, max_dist=10, return_tree=False, s image = rgb2lab(image) image = ndimage.gaussian_filter(img_as_float(image), [sigma, sigma, 0]) - cdef np.ndarray[dtype=np.float_t, ndim=3, mode="c"] image_c = np.ascontiguousarray(image) * ratio + cdef np.ndarray[dtype=np.float_t, ndim=3, mode="c"] image_c \ + = np.ascontiguousarray(image) * ratio if random_seed is None: random_state = np.random.RandomState() @@ -98,7 +103,8 @@ def quickshift(image, ratio=1., kernel_size=5, max_dist=10, return_tree=False, s cdef np.float_t* image_p = image_c.data cdef np.float_t* current_pixel_p = image_p - cdef np.ndarray[dtype=np.float_t, ndim=2] densities = np.zeros((width, height)) + cdef np.ndarray[dtype=np.float_t, ndim=2] densities \ + = np.zeros((width, height)) # compute densities for x, y in product(xrange(width), xrange(height)): x_min, x_max = max(x - w, 0), min(x + w + 1, width) @@ -115,8 +121,10 @@ def quickshift(image, ratio=1., kernel_size=5, max_dist=10, return_tree=False, s densities += random_state.normal(scale=0.00001, size=(width, height)) # default parent to self: - cdef np.ndarray[dtype=np.int_t, ndim=2] parent = np.arange(width * height).reshape(width, height) - cdef np.ndarray[dtype=np.float_t, ndim=2] dist_parent = np.zeros((width, height)) + cdef np.ndarray[dtype=np.int_t, ndim=2] parent \ + = np.arange(width * height).reshape(width, height) + cdef np.ndarray[dtype=np.float_t, ndim=2] dist_parent \ + = np.zeros((width, height)) # find nearest node with higher density current_pixel_p = image_p for x, y in product(xrange(width), xrange(height)): @@ -139,7 +147,8 @@ def quickshift(image, ratio=1., kernel_size=5, max_dist=10, return_tree=False, s dist_parent_flat = dist_parent.ravel() flat = parent.ravel() # remove parents with distance > max_dist - flat[dist_parent_flat > max_dist] = np.arange(width * height)[dist_parent_flat > max_dist] + too_far = dist_parent_flat > max_dist + flat[too_far] = np.arange(width * height)[too_far] old = np.zeros_like(flat) # flatten forest (mark each pixel with root of corresponding tree) while (old != flat).any(): diff --git a/skimage/segmentation/slic.pyx b/skimage/segmentation/slic.pyx index 37c6b79c..0d0adc49 100644 --- a/skimage/segmentation/slic.pyx +++ b/skimage/segmentation/slic.pyx @@ -6,7 +6,8 @@ from ..util import img_as_float from ..color import rgb2lab -def slic(image, n_segments=100, ratio=10., max_iter=10, sigma=1, convert2lab=True): +def slic(image, n_segments=100, ratio=10., max_iter=10, sigma=1, + convert2lab=True): """Segments image using k-means clustering in Color-(x,y) space. Parameters @@ -19,10 +20,12 @@ def slic(image, n_segments=100, ratio=10., max_iter=10, sigma=1, convert2lab=Tru max_iter: int maximum number of iterations of k-means sigma: float - Width of Gaussian smoothing kernel for preprocessing. Zero means no smoothing. + Width of Gaussian smoothing kernel for preprocessing. Zero means no + smoothing. convert2lab: bool - Whether the input should be converted to Lab colorspace prior to segmentation. - For this purpose, the input is assumed to be RGB. Highly recommended. + Whether the input should be converted to Lab colorspace prior to + segmentation. For this purpose, the input is assumed to be RGB. Highly + recommended. Returns ------- @@ -57,19 +60,23 @@ def slic(image, n_segments=100, ratio=10., max_iter=10, sigma=1, convert2lab=Tru n_seeds = len(means_y) means_color = np.zeros((n_seeds, n_seeds, 3)) - cdef np.ndarray[dtype=np.float_t, ndim=2] means = np.dstack([means_y, means_x, means_color]).reshape(-1, 5) + cdef np.ndarray[dtype=np.float_t, ndim=2] means \ + = np.dstack([means_y, means_x, means_color]).reshape(-1, 5) cdef np.float_t* current_mean cdef np.float_t* mean_entry n_means = means.shape[0] # 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(step)) ** 2 - cdef np.ndarray[dtype=np.float_t, ndim=3] image_yx = np.dstack([grid_y, grid_x, image / ratio]).copy("C") + cdef np.ndarray[dtype=np.float_t, ndim=3] image_yx \ + = np.dstack([grid_y, grid_x, image / ratio]).copy("C") cdef int i, k, x, y, x_min, x_max, y_min, y_max, changes cdef double dist_mean - cdef np.ndarray[dtype=np.int_t, ndim=2] nearest_mean = np.zeros((height, width), dtype=np.int) - cdef np.ndarray[dtype=np.float_t, ndim=2] distance = np.empty((height, width)) + cdef np.ndarray[dtype=np.int_t, ndim=2] nearest_mean \ + = np.zeros((height, width), dtype=np.int) + cdef np.ndarray[dtype=np.float_t, ndim=2] distance \ + = np.empty((height, width)) cdef np.float_t* image_p = image_yx.data cdef np.float_t* distance_p = distance.data cdef np.float_t* current_distance @@ -93,8 +100,8 @@ def slic(image, n_segments=100, ratio=10., max_iter=10, sigma=1, convert2lab=Tru mean_entry = current_mean dist_mean = 0 for c in range(5): - # you would think the compiler can optimize this itself. - # mine can't (with O2) + # you would think the compiler can optimize this + # itself. mine can't (with O2) tmp = current_pixel[0] - mean_entry[0] dist_mean += tmp * tmp current_pixel += 1 @@ -109,8 +116,8 @@ def slic(image, n_segments=100, ratio=10., max_iter=10, sigma=1, convert2lab=Tru if changes == 0: break # recompute means: - means_list = [np.bincount(nearest_mean.ravel(), image_yx[:, :, j].ravel()) - for j in xrange(5)] + means_list = [np.bincount(nearest_mean.ravel(), + image_yx[:, :, j].ravel()) for j in xrange(5)] in_mean = np.bincount(nearest_mean.ravel()) in_mean[in_mean == 0] = 1 means = (np.vstack(means_list) / in_mean).T.copy("C")