From 10dd45d01dc25c4423c3b128751d32f14c8fec5c Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Sun, 13 Mar 2011 16:25:56 +0200 Subject: [PATCH] ENH: Execute median filter without mask array by default. --- scikits/image/filter/_ctmf.pyx | 16 +++----- scikits/image/filter/ctmf.py | 53 ++++++++++++++++--------- scikits/image/filter/tests/test_ctmf.py | 7 ++++ 3 files changed, 47 insertions(+), 29 deletions(-) diff --git a/scikits/image/filter/_ctmf.pyx b/scikits/image/filter/_ctmf.pyx index b58572de..2b779470 100644 --- a/scikits/image/filter/_ctmf.pyx +++ b/scikits/image/filter/_ctmf.pyx @@ -761,21 +761,15 @@ def median_filter( mask : (M,N) array, dtype uint8 A value of 1 indicates a significant pixel, 0 that a pixel is masked. - output : (M,N) array, dtype uint8, optional + output : (M,N) array, dtype uint8 Array of same size as the input in which to store the filtered image. radius : int Radius of the inscribed circle to the octagon. - percent : int - Sort the unmasked pixels within the octagon into and array - (conceptually) and take the value indexed by the size of that - array times `percent` divided by 100. 50 gives the median. - - Returns - ------- - output : (M,N) ndarray, dtype uint8 - A reference to `output`, if specified, otherwise - the new output array. + percent : int, optional + The unmasked pixels within the octagon are sorted, and the + value at the `percent`-th index chosen. For example, the + default value of 50 chooses the median pixel. """ if percent < 0: diff --git a/scikits/image/filter/ctmf.py b/scikits/image/filter/ctmf.py index 03128660..9cb7e320 100644 --- a/scikits/image/filter/ctmf.py +++ b/scikits/image/filter/ctmf.py @@ -15,19 +15,38 @@ import numpy as np import _ctmf from rank_order import rank_order -def median_filter(data, mask, radius, percent=50): - '''Masked median filter with octagonal shape - - data - array of data to be median filtered. - mask - mask of significant pixels in data - radius - the radius of a circle inscribed into the filtering octagon - percent - conceptually, order the significant pixels in the octagon, - count them and choose the pixel indexed by the percent - times the count divided by 100. More simply, 50 = median - returns a filtered array. In areas where the median filter does - not overlap the mask, the filtered result is undefined, but in - practice, it will be the lowest value in the valid area. +def median_filter(data, mask=None, radius=1, percent=50): + '''Masked median filter with octagon shape. + + Parameters + ---------- + data : (M,N) ndarray, dtype uint8 + Input image. + mask : (M,N) ndarray, dtype uint8, optional + A value of 1 indicates a significant pixel, 0 + that a pixel is masked. By default, all pixels + are considered. + radius : {int, 1}, optional + The radius of a circle inscribed into the filtering + octagon. Default radius is 1. + percent : {int, 50}, optional + The unmasked pixels within the octagon are sorted, and the + value at the `percent`-th index chosen. For example, the + default value of 50 chooses the median pixel. + + Returns + ------- + out : (M,N) ndarray, dtype uint8 + Filtered array. In areas where the median filter does + not overlap the mask, the filtered result is underfined, but + in practice, it will be the lowest value in the valid area. + ''' + + if mask is None: + mask = np.ones(data.shape, dtype=np.bool) + mask = np.ascontiguousarray(mask, dtype=np.bool) + if np.all(~ mask): return data.copy() # @@ -47,12 +66,11 @@ def median_filter(data, mask, radius, percent=50): was_ranked = False input = np.zeros(data.shape, np.uint8 ) input[mask] = ranked_data - - mmask = np.ascontiguousarray(mask, np.uint8) - + + mask.dtype = np.uint8 output = np.zeros(data.shape, np.uint8) - - _ctmf.median_filter(input, mmask, output, radius, percent) + + _ctmf.median_filter(input, mask, output, radius, percent) if was_ranked: # # The translation gives the original value at each ranking. @@ -66,4 +84,3 @@ def median_filter(data, mask, radius, percent=50): else: result = output return result - diff --git a/scikits/image/filter/tests/test_ctmf.py b/scikits/image/filter/tests/test_ctmf.py index c8151f8b..02795b3c 100644 --- a/scikits/image/filter/tests/test_ctmf.py +++ b/scikits/image/filter/tests/test_ctmf.py @@ -94,5 +94,12 @@ def test_04_01_half_masked(): # in zero coverage areas, the result should be the lowest valud in the valid area assert (np.all(result[15:, :] == np.min(img[mask]))) +def test_default_values(): + img = (np.random.random((20, 20)) * 255).astype(np.uint8) + mask = np.ones((20, 20), dtype=np.uint8) + result1 = median_filter(img, mask, radius=1, percent=50) + result2 = median_filter(img) + assert_array_equal(result1, result2) + if __name__ == "__main__": run_module_suite()