From f1a8132fbfadc8621f81423e238dc50f42027ff6 Mon Sep 17 00:00:00 2001 From: Nelson Brown Date: Sun, 13 Jul 2014 11:28:27 -0700 Subject: [PATCH] Add doctrings and comments in response to reviewers --- skimage/morphology/binary.py | 17 +++++++++++++++- skimage/morphology/grey.py | 35 ++++++++++++++++++++++----------- skimage/morphology/misc.py | 38 +++++++++++++++++++++++++++++++++++- 3 files changed, 77 insertions(+), 13 deletions(-) diff --git a/skimage/morphology/binary.py b/skimage/morphology/binary.py index 69634912..5324b0f5 100644 --- a/skimage/morphology/binary.py +++ b/skimage/morphology/binary.py @@ -1,10 +1,13 @@ import warnings import numpy as np from scipy import ndimage -from .selem import _default_selem from .misc import default_fallback +# Our functions only work in 2D, so for 3D or higher input we should fall back +# on `scipy.ndimage`. Additionally, we want to use a cross-shaped structuring +# element of the appropriate dimension for each of these functions. +# The `default_callback` provides all these. @default_fallback def binary_erosion(image, selem=None, out=None): """Return fast binary morphological erosion of an image. @@ -50,6 +53,10 @@ def binary_erosion(image, selem=None, out=None): return np.equal(conv, selem_sum, out=out) +# Our functions only work in 2D, so for 3D or higher input we should fall back +# on `scipy.ndimage`. Additionally, we want to use a cross-shaped structuring +# element of the appropriate dimension for each of these functions. +# The `default_callback` provides all these. @default_fallback def binary_dilation(image, selem=None, out=None): """Return fast binary morphological dilation of an image. @@ -95,6 +102,10 @@ def binary_dilation(image, selem=None, out=None): return np.not_equal(conv, 0, out=out) +# Our functions only work in 2D, so for 3D or higher input we should fall back +# on `scipy.ndimage`. Additionally, we want to use a cross-shaped structuring +# element of the appropriate dimension for each of these functions. +# The `default_callback` provides all these. @default_fallback def binary_opening(image, selem=None, out=None): """Return fast binary morphological opening of an image. @@ -129,6 +140,10 @@ def binary_opening(image, selem=None, out=None): return out +# Our functions only work in 2D, so for 3D or higher input we should fall back +# on `scipy.ndimage`. Additionally, we want to use a cross-shaped structuring +# element of the appropriate dimension for each of these functions. +# The `default_callback` provides all these. @default_fallback def binary_closing(image, selem=None, out=None): """Return fast binary morphological closing of an image. diff --git a/skimage/morphology/grey.py b/skimage/morphology/grey.py index 0d0290c4..e09872cb 100644 --- a/skimage/morphology/grey.py +++ b/skimage/morphology/grey.py @@ -1,7 +1,5 @@ import warnings from skimage import img_as_ubyte -from scipy import ndimage -from .selem import _default_selem from .misc import default_fallback from . import cmorph @@ -10,7 +8,10 @@ from . import cmorph __all__ = ['erosion', 'dilation', 'opening', 'closing', 'white_tophat', 'black_tophat'] - +# Our functions only work in 2D, so for 3D or higher input we should fall back +# on `scipy.ndimage`. Additionally, we want to use a cross-shaped structuring +# element of the appropriate dimension for each of these functions. +# The `default_callback` provides all these. @default_fallback def erosion(image, selem=None, out=None, shift_x=False, shift_y=False): """Return greyscale morphological erosion of an image. @@ -57,10 +58,6 @@ def erosion(image, selem=None, out=None, shift_x=False, shift_y=False): """ - # If image has more than 2 dimensions, use scipy.ndimage - if image.ndim > 2: - return ndimage.morphology.grey_erosion(image, footprint=selem, out=out) - if image is out: raise NotImplementedError("In-place erosion not supported!") image = img_as_ubyte(image) @@ -69,6 +66,10 @@ def erosion(image, selem=None, out=None, shift_x=False, shift_y=False): shift_x=shift_x, shift_y=shift_y) +# Our functions only work in 2D, so for 3D or higher input we should fall back +# on `scipy.ndimage`. Additionally, we want to use a cross-shaped structuring +# element of the appropriate dimension for each of these functions. +# The `default_callback` provides all these. @default_fallback def dilation(image, selem=None, out=None, shift_x=False, shift_y=False): """Return greyscale morphological dilation of an image. @@ -116,10 +117,6 @@ def dilation(image, selem=None, out=None, shift_x=False, shift_y=False): """ - # If image has more than 2 dimensions, use scipy.ndimage - if image.ndim > 2: - return ndimage.morphology.grey_dilation(image, footprint=selem,out=out) - if image is out: raise NotImplementedError("In-place dilation not supported!") @@ -129,6 +126,10 @@ def dilation(image, selem=None, out=None, shift_x=False, shift_y=False): shift_x=shift_x, shift_y=shift_y) +# Our functions only work in 2D, so for 3D or higher input we should fall back +# on `scipy.ndimage`. Additionally, we want to use a cross-shaped structuring +# element of the appropriate dimension for each of these functions. +# The `default_callback` provides all these. @default_fallback def opening(image, selem=None, out=None): """Return greyscale morphological opening of an image. @@ -182,6 +183,10 @@ def opening(image, selem=None, out=None): return out +# Our functions only work in 2D, so for 3D or higher input we should fall back +# on `scipy.ndimage`. Additionally, we want to use a cross-shaped structuring +# element of the appropriate dimension for each of these functions. +# The `default_callback` provides all these. @default_fallback def closing(image, selem=None, out=None): """Return greyscale morphological closing of an image. @@ -235,6 +240,10 @@ def closing(image, selem=None, out=None): return out +# Our functions only work in 2D, so for 3D or higher input we should fall back +# on `scipy.ndimage`. Additionally, we want to use a cross-shaped structuring +# element of the appropriate dimension for each of these functions. +# The `default_callback` provides all these. @default_fallback def white_tophat(image, selem=None, out=None): """Return white top hat of an image. @@ -286,6 +295,10 @@ def white_tophat(image, selem=None, out=None): return out +# Our functions only work in 2D, so for 3D or higher input we should fall back +# on `scipy.ndimage`. Additionally, we want to use a cross-shaped structuring +# element of the appropriate dimension for each of these functions. +# The `default_callback` provides all these. @default_fallback def black_tophat(image, selem=None, out=None): """Return black top hat of an image. diff --git a/skimage/morphology/misc.py b/skimage/morphology/misc.py index f61d4e56..db922fd7 100644 --- a/skimage/morphology/misc.py +++ b/skimage/morphology/misc.py @@ -2,6 +2,8 @@ import numpy as np import scipy.ndimage as nd from .selem import _default_selem +# Our function names don't exactly correspond to ndimages. +# These dictionaries translate from our names to scipy's. skimage2ndimage = {x: 'grey_' + x for x in ('erosion','dilation','opening','closing')} skimage2ndimage.update({x: x @@ -9,9 +11,43 @@ skimage2ndimage.update({x: x 'binary_opening','binary_closing', 'black_tophat','white_tophat')}) - def default_fallback(func): + """Decorator to fall back on ndimage for images with more than 2 dimensions + + Parameters + ---------- + func : function + A morphology function such as erosion, dilation, opening, closing, + white_tophat, or black_tophat. + + Returns + ------- + func_out : function + If the image dimentionality is greater than 2D, the ndimage + function is returned, otherwise skimage function is used. + """ + def func_out(image, selem=None, out=None, **kwargs): + """Select a function appropriate for the image dimensionality + + Parameters + ---------- + image : ndarray + Image array. + selem : ndarray, optional + The neighborhood expressed as a 2-D array of 1's and 0's. + If None, use cross-shaped structuring element (connectivity=1). + out : ndarray of bool, optional + The array to store the result of the morphology. If None is + passed, a new array will be allocated. + + Returns + ------- + func_out : function + If the image dimentionality is greater than 2D, the ndimage + function is returned, otherwise skimage function is used. + """ + # Default structure element if selem is None: selem = _default_selem(image.ndim)