ENH: Execute median filter without mask array by default.

This commit is contained in:
Stefan van der Walt
2011-03-13 16:25:56 +02:00
parent 2f11eea665
commit 10dd45d01d
3 changed files with 47 additions and 29 deletions
+5 -11
View File
@@ -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:
+35 -18
View File
@@ -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
+7
View File
@@ -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()