diff --git a/TASKS.txt b/TASKS.txt index a20cbddb..da715573 100644 --- a/TASKS.txt +++ b/TASKS.txt @@ -1,64 +1,6 @@ .. role:: strike -SciPy 2012 Sprint -================= - -Welcome! Stefan van der Walt and Tony Yu are organizing a coding sprint for -scikits-image at SciPy 2012. Anyone who's interested can join the party on July -20th starting at 9 AM (location to be determined). - -We have a list of tasks for all levels of programmers, but we'd be really -interested in new ideas as well. - -Basic ------ - -These tasks should just require some basic Python knowledge. - -Code review -``````````` - -* geometric transformation PR -* morphological reconstruction PR -* Testing visualization tools - -Docs -```` - -* Task-based examples (`Where's Waldo`_, `Flatten Sudoku Puzzle`_) -* Organize/add-topics to user guide (Add overview of packages) - -.. _Flatten Sudoku Puzzle: http://stackoverflow.com/questions/10196198/how-to-remove-convexity-defects-in-sudoku-square/11366549#11366549 -.. _Where's Waldo: http://stackoverflow.com/questions/8479058/how-do-i-find-waldo-with-mathematica - -Features -```````` - -* Add text, anti-aliasing to the draw module -* Lab color space conversion -* Add slicing to ImageCollection object -* Add imread_collection to all imread backends -* Resurrect the `Image object `__ and add - EXIF and TIFF tags. - - Add IPython display protocol. - - Add an htmlrepr to the Image object. Should we return image objects from - all I/O routines? -* Add @greyimage decorator to check if input is a greyscale image - -Intermediate ------------- - -These tasks may require some understanding of image processing algorithms or -scikits-image internals. - -* Add binary features (BRIEF, BRISK, FREAK) -* Add `STAR features `__ -* Using the visualization tools, add an FFT-domain image editor -* `Blurring kernel estimation `__ -* Better video loading (move to plugin framework, add backends) - - .. _howto_contribute: How to contribute to ``skimage`` @@ -102,14 +44,19 @@ Implement Algorithms - Convex hulls of objects in a labels matrix (simply adapt current convex hull image code--this one's low hanging fruit). Generalise this solution to also skeletonize objects in a labels matrix. +- Add binary features (BRIEF, BRISK, FREAK) +- Add `STAR features `__ +- `Blurring kernel estimation `__ Drawing (directly on an ndarray) ```````````````````````````````` - Wu's algorithm for circles - Text rendering +- Add anti-aliasing Infrastructure -------------- +- Add @greyimage decorator to check if input is a greyscale image - :strike:`Implement a new backend system so that we may start including PyOpenCL-based algorithms` @@ -175,6 +122,12 @@ io * Update ``qt_plugin.py`` and other plugins to view collections. * Rewrite GTK backend using GObject Introspection for Py3K compatibility. * Add DICOM plugin for `GDCM `__. +* Add ``imread_collection`` to all ``imread`` backends +* Better video loading (move to plugin framework, add backends) + +viewer +`````` +* Using the visualization tools, add an FFT-domain image editor docs ```` diff --git a/doc/tools/apigen.py b/doc/tools/apigen.py index 86791383..f13f2a1b 100644 --- a/doc/tools/apigen.py +++ b/doc/tools/apigen.py @@ -269,10 +269,6 @@ class ApiDocWriter(object): ad = '.. AUTO-GENERATED FILE -- DO NOT EDIT!\n\n' - chap_title = uri_short - #ad += (chap_title+'\n'+ self.rst_section_levels[1] * len(chap_title) - # + '\n\n') - # Set the chapter title to read 'module' for all modules except for the # main packages if '.' in uri: @@ -281,21 +277,8 @@ class ApiDocWriter(object): title = ':mod:`' + uri_short + '`' ad += title + '\n' + self.rst_section_levels[1] * len(title) - if len(classes): - ad += '\nInheritance diagram for ``%s``:\n\n' % uri - ad += '.. inheritance-diagram:: %s \n' % uri - ad += ' :parts: 3\n' - ad += '\n.. automodule:: ' + uri + '\n' ad += '\n.. currentmodule:: ' + uri + '\n' -# multi_class = len(classes) > 1 -# multi_fx = len(functions) > 1 -# if multi_class: -# ad += '\n' + 'Classes' + '\n' + \ -# self.rst_section_levels[2] * 7 + '\n' -# elif len(classes) and multi_fx: -# ad += '\n' + 'Class' + '\n' + \ -# self.rst_section_levels[2] * 5 + '\n' for c in classes: ad += '\n:class:`' + c + '`\n' \ + self.rst_section_levels[2] * \ @@ -305,15 +288,8 @@ class ApiDocWriter(object): ad += ' :members:\n' \ ' :undoc-members:\n' \ ' :show-inheritance:\n' \ - ' :inherited-members:\n' \ '\n' \ ' .. automethod:: __init__\n' -# if multi_fx: -# ad += '\n' + 'Functions' + '\n' + \ -# self.rst_section_levels[2] * 9 + '\n\n' -# elif len(functions) and multi_class: -# ad += '\n' + 'Function' + '\n' + \ -# self.rst_section_levels[2] * 8 + '\n\n' ad += '.. autosummary::\n\n' for f in functions: ad += ' ' + uri + '.' + f + '\n' diff --git a/skimage/filter/thresholding.py b/skimage/filter/thresholding.py index 3f8acdef..77f244fc 100644 --- a/skimage/filter/thresholding.py +++ b/skimage/filter/thresholding.py @@ -24,11 +24,13 @@ def threshold_adaptive(image, block_size, method='gaussian', offset=0, method : {'generic', 'gaussian', 'mean', 'median'}, optional Method used to determine adaptive threshold for local neighbourhood in weighted mean image. - * 'generic': use custom function (see `param` parameter) - * 'gaussian': apply gaussian filter (see `param` parameter for custom - sigma value) - * 'mean': apply arithmetic mean filter - * 'median' apply median rank filter + + * 'generic': use custom function (see `param` parameter) + * 'gaussian': apply gaussian filter (see `param` parameter for custom + sigma value) + * 'mean': apply arithmetic mean filter + * 'median' apply median rank filter + By default the 'gaussian' method is used. offset : float, optional Constant subtracted from weighted mean of neighborhood to calculate diff --git a/skimage/graph/_mcp.pyx b/skimage/graph/_mcp.pyx index beb814fe..320493c2 100644 --- a/skimage/graph/_mcp.pyx +++ b/skimage/graph/_mcp.pyx @@ -102,7 +102,7 @@ def _offset_edge_map(shape, offsets): """ indices = np.indices(shape) # indices.shape = (n,)+shape - + #get the distance from each index to the upper or lower edge in each dim pos_edges = (shape - indices.T).T neg_edges = -1 - indices @@ -112,7 +112,7 @@ def _offset_edge_map(shape, offsets): mins = offsets.min(axis=0) for pos, neg, mx, mn in zip(pos_edges, neg_edges, maxes, mins): pos[pos > mx] = 0 - neg[neg < mn] = 0 + neg[neg < mn] = 0 return pos_edges.astype(EDGE_D), neg_edges.astype(EDGE_D) def make_offsets(d, fully_connected): @@ -130,8 +130,8 @@ def make_offsets(d, fully_connected): ------- offsets : list of tuples of length `d` - Example - ------- + Examples + -------- The singly-connected 2-d neighborhood is four offsets: @@ -216,7 +216,7 @@ cdef class MCP: `costs` array at each point on the path. The class MCP_Geometric, on the other hand, accounts for the fact that diagonal vs. axial moves are of different lengths, and weights the path cost accordingly. - + Array elements with infinite or negative costs will simply be ignored, as will paths whose cumulative cost overflows to infinite. @@ -295,7 +295,7 @@ cdef class MCP: pos, neg = _offset_edge_map(costs.shape, self.offsets) self.flat_pos_edge_map = pos.reshape((self.dim, size), order='F') self.flat_neg_edge_map = neg.reshape((self.dim, size), order='F') - + # The offset lengths are the distances traveled along each offset self.offset_lengths = np.sqrt( @@ -449,7 +449,7 @@ cdef class MCP: # edge along any axis is_at_edge = 0 for d in range(dim): - if (flat_pos_edge_map[d, index] != 0 or + if (flat_pos_edge_map[d, index] != 0 or flat_neg_edge_map[d, index] != 0): is_at_edge = 1 break @@ -490,7 +490,7 @@ cdef class MCP: new_cost = flat_costs[new_index] if new_cost < 0 or new_cost == inf: continue - + # Now we ask the heap to append or update the cost to # this new point, but only if that point isn't already # in the heap, or it is but the new cost is lower. diff --git a/skimage/io/_io.py b/skimage/io/_io.py index 122ddbd6..4ff8cc27 100644 --- a/skimage/io/_io.py +++ b/skimage/io/_io.py @@ -29,8 +29,8 @@ class Image(np.ndarray): def __new__(cls, arr, **kwargs): """Set the image data and tags according to given parameters. - Input: - ------ + Parameters + ---------- arr : ndarray Image data. kwargs : Image tags as keywords diff --git a/skimage/io/_plugins/tifffile_plugin.ini b/skimage/io/_plugins/tifffile_plugin.ini index 4666e503..bf83fce2 100644 --- a/skimage/io/_plugins/tifffile_plugin.ini +++ b/skimage/io/_plugins/tifffile_plugin.ini @@ -1,3 +1,3 @@ [tifffile] -description = Open and save TIFF and TIFF-based (LSM, STK, etc.) images using tifffile.py +description = Load and save TIFF and TIFF-based images using tifffile.py provides = imread, imsave diff --git a/skimage/measure/_regionprops.py b/skimage/measure/_regionprops.py index dfc88b4f..5615ecc5 100644 --- a/skimage/measure/_regionprops.py +++ b/skimage/measure/_regionprops.py @@ -58,102 +58,145 @@ def regionprops(label_image, properties=['Area', 'Centroid'], Parameters ---------- - label_image : N x M ndarray + label_image : (N, M) ndarray Labelled input image. properties : {'all', list} Shape measurements to be determined for each labelled image region. Default is `['Area', 'Centroid']`. The following properties can be determined: + * Area : int Number of pixels of region. + * BoundingBox : tuple Bounding box `(min_row, min_col, max_row, max_col)` - * CentralMoments : 3 x 3 ndarray + + * CentralMoments : (3, 3) ndarray Central moments (translation invariant) up to 3rd order. + mu_ji = sum{ array(x, y) * (x - x_c)^j * (y - y_c)^i } + where the sum is over the `x`, `y` coordinates of the region, and `x_c` and `y_c` are the coordinates of the region's centroid. + * Centroid : array Centroid coordinate tuple `(row, col)`. + * ConvexArea : int Number of pixels of convex hull image. + * ConvexImage : (H, J) ndarray Binary convex hull image which has the same size as bounding box. + * Coordinates : (N, 2) ndarray Coordinate list `(row, col)` of the region. + * Eccentricity : float Eccentricity of the ellipse that has the same second-moments as the region. The eccentricity is the ratio of the distance between its minor and major axis length. The value is between 0 and 1. + * EquivDiameter : float The diameter of a circle with the same area as the region. + * EulerNumber : int Euler number of region. Computed as number of objects (= 1) subtracted by number of holes (8-connectivity). + * Extent : float Ratio of pixels in the region to pixels in the total bounding box. Computed as `Area / (rows*cols)` + * FilledArea : int Number of pixels of filled region. + * FilledImage : (H, J) ndarray Binary region image with filled holes which has the same size as bounding box. + * HuMoments : tuple Hu moments (translation, scale and rotation invariant). + * Image : (H, J) ndarray Sliced binary region image which has the same size as bounding box. + * MajorAxisLength : float The length of the major axis of the ellipse that has the same normalized second central moments as the region. + * MaxIntensity: float Value with the greatest intensity in the region. + * MeanIntensity: float Value with the mean intensity in the region. + * MinIntensity: float Value with the least intensity in the region. + * MinorAxisLength : float The length of the minor axis of the ellipse that has the same normalized second central moments as the region. - * Moments : 3 x 3 ndarray + + * Moments : (3, 3) ndarray Spatial moments up to 3rd order. + m_ji = sum{ array(x, y) * x^j * y^i } + where the sum is over the `x`, `y` coordinates of the region. - * NormalizedMoments : 3 x 3 ndarray + + * NormalizedMoments : (3, 3) ndarray Normalized moments (translation and scale invariant) up to 3rd order. + nu_ji = mu_ji / m_00^[(i+j)/2 + 1] + where `m_00` is the zeroth spatial moment. + * Orientation : float Angle between the X-axis and the major axis of the ellipse that has the same second-moments as the region. Ranging from `-pi/2` to `pi/2` in counter-clockwise direction. + * Perimeter : float Perimeter of object which approximates the contour as a line through the centers of border pixels using a 4-connectivity. + * Solidity : float Ratio of pixels in the region to pixels of the convex hull image. - * WeightedCentralMoments : 3 x 3 ndarray + + * WeightedCentralMoments : (3, 3) ndarray Central moments (translation invariant) of intensity image up to 3rd order. + wmu_ji = sum{ array(x, y) * (x - x_c)^j * (y - y_c)^i } + where the sum is over the `x`, `y` coordinates of the region, and `x_c` and `y_c` are the coordinates of the region's centroid. + * WeightedCentroid : array Centroid coordinate tuple `(row, col)` weighted with intensity image. + * WeightedHuMoments : tuple Hu moments (translation, scale and rotation invariant) of intensity image. + * WeightedMoments : (3, 3) ndarray Spatial moments of intensity image up to 3rd order. + wm_ji = sum{ array(x, y) * x^j * y^i } + where the sum is over the `x`, `y` coordinates of the region. - * WeightedNormalizedMoments : 3 x 3 ndarray + + * WeightedNormalizedMoments : (3, 3) ndarray Normalized moments (translation and scale invariant) of intensity image up to 3rd order. + wnu_ji = wmu_ji / wm_00^[(i+j)/2 + 1] + where `wm_00` is the zeroth spatial moment (intensity-weighted area). + intensity_image : (N, M) ndarray, optional Intensity image with same size as labelled image. Default is None. @@ -214,11 +257,11 @@ def regionprops(label_image, properties=['Area', 'Centroid'], cc = m[1, 0] / m[0, 0] mu = _moments.central_moments(array, cr, cc, 3) - #: elements of the inertia tensor [a b; b c] + # elements of the inertia tensor [a b; b c] a = mu[2, 0] / mu[0, 0] b = mu[1, 1] / mu[0, 0] c = mu[0, 2] / mu[0, 0] - #: eigen values of inertia tensor + # eigen values of inertia tensor l1 = (a + c) / 2 + sqrt(4 * b ** 2 + (a - c) ** 2) / 2 l2 = (a + c) / 2 - sqrt(4 * b ** 2 + (a - c) ** 2) / 2 @@ -378,7 +421,7 @@ def perimeter(image, neighbourhood=4): ---------- image : array binary image - neighbourhood: 4 or 8, optional + neighbourhood : 4 or 8, optional neighbourhood connectivity for border pixel determination, default 4 Returns @@ -388,9 +431,9 @@ def perimeter(image, neighbourhood=4): References ---------- - K. Benkrid, D. Crookes. Design and FPGA Implementation of a Perimeter - Estimator. The Queen's University of Belfast. - http://www.cs.qub.ac.uk/~d.crookes/webpubs/papers/perimeter.doc + .. [1] K. Benkrid, D. Crookes. Design and FPGA Implementation of + a Perimeter Estimator. The Queen's University of Belfast. + http://www.cs.qub.ac.uk/~d.crookes/webpubs/papers/perimeter.doc """ if neighbourhood == 4: strel = STREL_4 diff --git a/skimage/morphology/greyreconstruct.py b/skimage/morphology/greyreconstruct.py index 9e447800..1bbf33ca 100644 --- a/skimage/morphology/greyreconstruct.py +++ b/skimage/morphology/greyreconstruct.py @@ -101,17 +101,18 @@ def reconstruction(seed, mask, method='dilation', selem=None, offset=None): Notes ----- - The algorithm is taken from: - [1] Robinson, "Efficient morphological reconstruction: a downhill filter", - Pattern Recognition Letters 25 (2004) 1759-1767. + The algorithm is taken from [1]_. Applications for greyscale reconstruction + are discussed in [2]_ and [3]_. - Applications for greyscale reconstruction are discussed in: - - [2] Vincent, L., "Morphological Grayscale Reconstruction in Image Analysis: - Applications and Efficient Algorithms", IEEE Transactions on Image - Processing (1993) - [3] Soille, P., "Morphological Image Analysis: Principles and Applications", - Chapter 6, 2nd edition (2003), ISBN 3540429883. + References + ---------- + .. [1] Robinson, "Efficient morphological reconstruction: a downhill + filter", Pattern Recognition Letters 25 (2004) 1759-1767. + .. [2] Vincent, L., "Morphological Grayscale Reconstruction in Image + Analysis: Applications and Efficient Algorithms", IEEE Transactions + on Image Processing (1993) + .. [3] Soille, P., "Morphological Image Analysis: Principles and + Applications", Chapter 6, 2nd edition (2003), ISBN 3540429883. """ assert tuple(seed.shape) == tuple(mask.shape) if method == 'dilation' and np.any(seed > mask): diff --git a/skimage/transform/_geometric.py b/skimage/transform/_geometric.py index 3e469ba7..0f76b50e 100644 --- a/skimage/transform/_geometric.py +++ b/skimage/transform/_geometric.py @@ -787,7 +787,7 @@ def warp(image, inverse_map=None, map_args={}, output_shape=None, order=1, ---------- image : 2-D array Input image. - inverse_map : transformation object, callable xy = f(xy, **kwargs) + inverse_map : transformation object, callable ``xy = f(xy, **kwargs)`` Inverse coordinate map. A function that transforms a (N, 2) array of ``(x, y)`` coordinates in the *output image* into their corresponding coordinates in the *source image* (e.g. a transformation object or its diff --git a/skimage/transform/hough_transform.py b/skimage/transform/hough_transform.py index e4cb5b5c..5b36b103 100644 --- a/skimage/transform/hough_transform.py +++ b/skimage/transform/hough_transform.py @@ -61,8 +61,9 @@ except ImportError: pass -def probabilistic_hough(img, threshold=10, line_length=50, line_gap=10, theta=None): - """Performs a progressive probabilistic line Hough transform and returns the detected lines. +def probabilistic_hough(img, threshold=10, line_length=50, line_gap=10, + theta=None): + """Return lines from a progressive probabilistic line Hough transform. Parameters ---------- @@ -87,9 +88,9 @@ def probabilistic_hough(img, threshold=10, line_length=50, line_gap=10, theta=No References ---------- - .. [1] C. Galamhos, J. Matas and J. Kittler,"Progressive probabilistic Hough - transform for line detection", in IEEE Computer Society Conference on - Computer Vision and Pattern Recognition, 1999. + .. [1] C. Galamhos, J. Matas and J. Kittler, "Progressive probabilistic + Hough transform for line detection", in IEEE Computer Society + Conference on Computer Vision and Pattern Recognition, 1999. """ return _probabilistic_hough(img, threshold, line_length, line_gap, theta) diff --git a/skimage/util/dtype.py b/skimage/util/dtype.py index 4a5a6f23..0ca3197b 100644 --- a/skimage/util/dtype.py +++ b/skimage/util/dtype.py @@ -344,7 +344,7 @@ def img_as_bool(image, force_copy=False): Returns ------- - out : ndarray of bool (bool_) + out : ndarray of bool (`bool_`) Output image. Notes diff --git a/skimage/util/montage.py b/skimage/util/montage.py index 6c23ccbf..1a8cda23 100644 --- a/skimage/util/montage.py +++ b/skimage/util/montage.py @@ -45,8 +45,8 @@ def montage2d(arr_in, fill='mean', rescale_intensity=False): Output array where 'alpha' has been determined automatically to fit (at least) the `n_images` in `arr_in`. - Example - ------- + Examples + -------- >>> import numpy as np >>> from skimage.util.montage import montage2d >>> arr_in = np.arange(3 * 2 * 2).reshape(3, 2, 2)