Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

ENH: ndimage: gaussian filter truncation #2767

Merged
merged 3 commits into from

4 participants

Warren Weckesser Ralf Gommers Thouis (Ray) Jones Pauli Virtanen
Warren Weckesser
Collaborator

This is an extension of #239
I added a commit that strengthens the existing test, and adds tests for more of the affected functions.

There are two API enhancements in this PR:

  • Add the truncate argument to gaussian_filter and gaussian_filter1d. This controls the size of the filter, measured in terms of the standard deviations of the gaussian.
  • Add **kwargs to the signature of gaussian_gradient_magnitude and gaussian_laplace. Any additional keyword arguments passed to these functions are passed on to gaussian_filter. This allows these functions to use the truncate argument.

This API looks reasonable to me. If there are no objections, I'd like to get this into 0.13.

Ralf Gommers
Owner
  • can you rebase?
  • a bit late for 0.13.x, I'd rather leave it till 0.14
  • @thouis can you review the last commit?
thouis and others added some commits
Thouis (Ray) Jones thouis ENH: expose control truncation of ndimage.gaussian_filter().
This change gives the user control over the size at which the Gaussian filter is truncated,
with default behavior to truncate at 4 standard deviations (the previous fixed value).
19eff1c
Thouis (Ray) Jones thouis ENH: Pass extra keyword arguments to gaussian_laplace() and gaussian_…
…gradient_magnitude() to gaussian_filter()

This change allows control over the truncation radius of the gaussian filter used in
gaussian_laplace() and gaussian_gradient_magnitude().
f6c8d9d
Warren Weckesser WarrenWeckesser TST: ndimage: add more tests in test_gaussian_truncate() cf3aa17
Warren Weckesser
Collaborator

Rebased.

Warren Weckesser
Collaborator

@roderikk is probably interested in this too, since he created the original patch.

Pauli Virtanen pv referenced this pull request
Closed

Gaussian filter truncation #239

Thouis (Ray) Jones

Looks good to me.

Pauli Virtanen pv merged commit 56db4ed into from
Pauli Virtanen
Owner
pv commented

LGTM too, merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Aug 28, 2013
  1. Thouis (Ray) Jones Warren Weckesser

    ENH: expose control truncation of ndimage.gaussian_filter().

    thouis authored WarrenWeckesser committed
    This change gives the user control over the size at which the Gaussian filter is truncated,
    with default behavior to truncate at 4 standard deviations (the previous fixed value).
  2. Thouis (Ray) Jones Warren Weckesser

    ENH: Pass extra keyword arguments to gaussian_laplace() and gaussian_…

    thouis authored WarrenWeckesser committed
    …gradient_magnitude() to gaussian_filter()
    
    This change allows control over the truncation radius of the gaussian filter used in
    gaussian_laplace() and gaussian_gradient_magnitude().
  3. Warren Weckesser
This page is out of date. Refresh to see the latest.
Showing with 68 additions and 14 deletions.
  1. +27 −14 scipy/ndimage/filters.py
  2. +41 −0 scipy/ndimage/tests/test_filters.py
41 scipy/ndimage/filters.py
View
@@ -178,7 +178,7 @@ def convolve1d(input, weights, axis=-1, output=None, mode="reflect",
@docfiller
def gaussian_filter1d(input, sigma, axis=-1, order=0, output=None,
- mode="reflect", cval=0.0):
+ mode="reflect", cval=0.0, truncate=4.0):
"""One-dimensional Gaussian filter.
Parameters
@@ -195,6 +195,9 @@ def gaussian_filter1d(input, sigma, axis=-1, order=0, output=None,
%(output)s
%(mode)s
%(cval)s
+ truncate : float
+ Truncate the filter at this many standard deviations.
+ Default is 4.0.
Returns
-------
@@ -204,9 +207,8 @@ def gaussian_filter1d(input, sigma, axis=-1, order=0, output=None,
if order not in range(4):
raise ValueError('Order outside 0..3 not implemented')
sd = float(sigma)
- # make the length of the filter equal to 4 times the standard
- # deviations:
- lw = int(4.0 * sd + 0.5)
+ # make the radius of the filter equal to truncate standard deviations
+ lw = int(truncate * sd + 0.5)
weights = [0.0] * (2 * lw + 1)
weights[lw] = 1.0
sum = 1.0
@@ -247,7 +249,7 @@ def gaussian_filter1d(input, sigma, axis=-1, order=0, output=None,
@docfiller
def gaussian_filter(input, sigma, order=0, output=None,
- mode="reflect", cval=0.0):
+ mode="reflect", cval=0.0, truncate=4.0):
"""Multidimensional Gaussian filter.
Parameters
@@ -268,6 +270,9 @@ def gaussian_filter(input, sigma, order=0, output=None,
%(output)s
%(mode)s
%(cval)s
+ truncate : float
+ Truncate the filter at this many standard deviations.
+ Default is 4.0.
Returns
-------
@@ -296,7 +301,7 @@ def gaussian_filter(input, sigma, order=0, output=None,
if len(axes) > 0:
for axis, sigma, order in axes:
gaussian_filter1d(input, sigma, axis, order, output,
- mode, cval)
+ mode, cval, truncate)
input = output
else:
output[...] = input[...]
@@ -405,7 +410,7 @@ def derivative2(input, axis, output, mode, cval):
@docfiller
def gaussian_laplace(input, sigma, output=None, mode="reflect",
- cval=0.0):
+ cval=0.0, **kwargs):
"""Multidimensional Laplace filter using gaussian second derivatives.
Parameters
@@ -418,15 +423,19 @@ def gaussian_laplace(input, sigma, output=None, mode="reflect",
%(output)s
%(mode)s
%(cval)s
+ Extra keyword arguments will be passed to gaussian_filter().
"""
input = numpy.asarray(input)
- def derivative2(input, axis, output, mode, cval, sigma):
+ def derivative2(input, axis, output, mode, cval, sigma, **kwargs):
order = [0] * input.ndim
order[axis] = 2
- return gaussian_filter(input, sigma, order, output, mode, cval)
+ return gaussian_filter(input, sigma, order, output, mode, cval,
+ **kwargs)
+
return generic_laplace(input, derivative2, output, mode, cval,
- extra_arguments=(sigma,))
+ extra_arguments=(sigma,),
+ extra_keywords=kwargs)
@docfiller
@@ -480,7 +489,7 @@ def generic_gradient_magnitude(input, derivative, output=None,
@docfiller
def gaussian_gradient_magnitude(input, sigma, output=None,
- mode="reflect", cval=0.0):
+ mode="reflect", cval=0.0, **kwargs):
"""Multidimensional gradient magnitude using Gaussian derivatives.
Parameters
@@ -493,15 +502,19 @@ def gaussian_gradient_magnitude(input, sigma, output=None,
%(output)s
%(mode)s
%(cval)s
+ Extra keyword arguments will be passed to gaussian_filter().
"""
input = numpy.asarray(input)
- def derivative(input, axis, output, mode, cval, sigma):
+ def derivative(input, axis, output, mode, cval, sigma, **kwargs):
order = [0] * input.ndim
order[axis] = 1
- return gaussian_filter(input, sigma, order, output, mode, cval)
+ return gaussian_filter(input, sigma, order, output, mode,
+ cval, **kwargs)
+
return generic_gradient_magnitude(input, derivative, output, mode,
- cval, extra_arguments=(sigma,))
+ cval, extra_arguments=(sigma,),
+ extra_keywords=kwargs)
def _correlate_or_convolve(input, weights, output, mode, cval, origin,
41 scipy/ndimage/tests/test_filters.py
View
@@ -53,3 +53,44 @@ def test_valid_origins():
# Just check this raises an error instead of silently accepting or
# segfaulting.
assert_raises(ValueError, filter, data, 3, origin=2)
+
+
+def test_gaussian_truncate():
+ # Test that Gaussian filters can be truncated at different widths.
+ # These tests only check that the result has the expected number
+ # of nonzero elements.
+ arr = np.zeros((100, 100), np.float)
+ arr[50, 50] = 1
+ num_nonzeros_2 = (sndi.gaussian_filter(arr, 5, truncate=2) > 0).sum()
+ assert_equal(num_nonzeros_2, 21**2)
+ num_nonzeros_5 = (sndi.gaussian_filter(arr, 5, truncate=5) > 0).sum()
+ assert_equal(num_nonzeros_5, 51**2)
+
+ # Test truncate when sigma is a sequence.
+ f = sndi.gaussian_filter(arr, [0.5, 2.5], truncate=3.5)
+ fpos = f > 0
+ n0 = fpos.any(axis=0).sum()
+ # n0 should be 2*int(2.5*3.5 + 0.5) + 1
+ assert_equal(n0, 19)
+ n1 = fpos.any(axis=1).sum()
+ # n1 should be 2*int(0.5*3.5 + 0.5) + 1
+ assert_equal(n1, 5)
+
+ # Test gaussian_filter1d.
+ x = np.zeros(51)
+ x[25] = 1
+ f = sndi.gaussian_filter1d(x, sigma=2, truncate=3.5)
+ n = (f > 0).sum()
+ assert_equal(n, 15)
+
+ # Test gaussian_laplace
+ y = sndi.gaussian_laplace(x, sigma=2, truncate=3.5)
+ nonzero_indices = np.where(y != 0)[0]
+ n = nonzero_indices.ptp() + 1
+ assert_equal(n, 15)
+
+ # Test gaussian_gradient_magnitude
+ y = sndi.gaussian_gradient_magnitude(x, sigma=2, truncate=3.5)
+ nonzero_indices = np.where(y != 0)[0]
+ n = nonzero_indices.ptp() + 1
+ assert_equal(n, 15)
Something went wrong with that request. Please try again.