diff --git a/doc/source/api_changes.rst b/doc/source/api_changes.rst index 50fed4f8..824762e0 100644 --- a/doc/source/api_changes.rst +++ b/doc/source/api_changes.rst @@ -6,6 +6,9 @@ Version 0.13 - Deprecated filters `hsobel`, `vsobel`, `hscharr`, `vscharr`, `hprewitt`, `vprewitt`, `roberts_positive_diagonal`, `roberts_negative_diagonal` have been removed from `skimage.filters.edges`. +- The `sigma` parameter of `skimage.filters.gaussian` and the `selem` parameter + of `skimage.filters.median` have been made optional, with default + values. Version 0.12 ------------ diff --git a/skimage/filters/_gaussian.py b/skimage/filters/_gaussian.py index 2a455fe9..9eb3fcf5 100644 --- a/skimage/filters/_gaussian.py +++ b/skimage/filters/_gaussian.py @@ -9,16 +9,16 @@ from .._shared.utils import warn __all__ = ['gaussian'] -def gaussian(image, sigma, output=None, mode='nearest', cval=0, +def gaussian(image, sigma=1, output=None, mode='nearest', cval=0, multichannel=None): """Multi-dimensional Gaussian filter Parameters ---------- image : array-like - input image (grayscale or color) to filter. - sigma : scalar or sequence of scalars - standard deviation for Gaussian kernel. The standard + Input image (grayscale or color) to filter. + sigma : scalar or sequence of scalars, optional + Standard deviation for Gaussian kernel. The standard deviations of the Gaussian filter are given for each axis as a sequence, or as a single number, in which case it is equal for all axes. diff --git a/skimage/filters/rank/generic.py b/skimage/filters/rank/generic.py index 998796c6..83b8fbc2 100644 --- a/skimage/filters/rank/generic.py +++ b/skimage/filters/rank/generic.py @@ -48,7 +48,9 @@ References """ +import functools import numpy as np +from scipy import ndimage as ndi from ... import img_as_ubyte from ..._shared.utils import assert_nD, warn @@ -127,6 +129,30 @@ def _apply_vector_per_pixel(func, image, selem, out, mask, shift_x, shift_y, return out +def _default_selem(func): + """Decorator to add a default structuring element to morphology functions. + + Parameters + ---------- + func : function + A morphology function such as erosion, dilation, opening, closing, + white_tophat, or black_tophat. + + Returns + ------- + func_out : function + The function, using a default structuring element of same dimension + as the input image with connectivity 1. + """ + @functools.wraps(func) + def func_out(image, selem=None, *args, **kwargs): + if selem is None: + selem = ndi.generate_binary_structure(image.ndim, image.ndim) + return func(image, selem=selem, *args, **kwargs) + + return func_out + + def autolevel(image, selem, out=None, mask=None, shift_x=False, shift_y=False): """Auto-level image using local histogram. @@ -374,7 +400,9 @@ def mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False): return _apply_scalar_per_pixel(generic_cy._mean, image, selem, out=out, mask=mask, shift_x=shift_x, shift_y=shift_y) -def geometric_mean(image, selem, out=None, mask=None, shift_x=False, shift_y=False): + +def geometric_mean(image, selem, out=None, mask=None, + shift_x=False, shift_y=False): """Return local geometric mean of an image. Parameters @@ -457,15 +485,18 @@ def subtract_mean(image, selem, out=None, mask=None, shift_x=False, shift_x=shift_x, shift_y=shift_y) -def median(image, selem, out=None, mask=None, shift_x=False, shift_y=False): +@_default_selem +def median(image, selem=None, out=None, mask=None, + shift_x=False, shift_y=False): """Return local median of an image. Parameters ---------- image : 2-D array (uint8, uint16) Input image. - selem : 2-D array - The neighborhood expressed as a 2-D array of 1's and 0's. + selem : 2-D array, optional + The neighborhood expressed as a 2-D array of 1's and 0's. If None, a + full square of size 3 is used. out : 2-D array (same dtype as input) If None, a new array is allocated. mask : ndarray diff --git a/skimage/filters/rank/tests/test_rank.py b/skimage/filters/rank/tests/test_rank.py index 3fcc79ac..200e20e3 100644 --- a/skimage/filters/rank/tests/test_rank.py +++ b/skimage/filters/rank/tests/test_rank.py @@ -713,5 +713,14 @@ def test_windowed_histogram(): assert larger_output.shape[2] == 5 +def test_median_default_value(): + a = np.zeros((3, 3), dtype=np.uint8) + a[1] = 1 + full_selem = np.ones((3, 3), dtype=np.uint8) + assert_equal(rank.median(a), rank.median(a, full_selem)) + assert rank.median(a)[1, 1] == 0 + assert rank.median(a, disk(1))[1, 1] == 1 + + if __name__ == "__main__": run_module_suite() diff --git a/skimage/filters/tests/test_gaussian.py b/skimage/filters/tests/test_gaussian.py index 2d78ce6c..da69fab0 100644 --- a/skimage/filters/tests/test_gaussian.py +++ b/skimage/filters/tests/test_gaussian.py @@ -19,6 +19,12 @@ def test_null_sigma(): assert np.all(gaussian(a, 0) == a) +def test_default_sigma(): + a = np.zeros((3, 3)) + a[1, 1] = 1. + assert np.all(gaussian(a) == gaussian(a, sigma=1)) + + def test_energy_decrease(): a = np.zeros((3, 3)) a[1, 1] = 1.