|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import numpy as np |
|
from scipy._lib._util import normalize_axis_index |
|
from . import _ni_support |
|
from . import _nd_image |
|
|
|
__all__ = ['fourier_gaussian', 'fourier_uniform', 'fourier_ellipsoid', |
|
'fourier_shift'] |
|
|
|
|
|
def _get_output_fourier(output, input): |
|
if output is None: |
|
if input.dtype.type in [np.complex64, np.complex128, np.float32]: |
|
output = np.zeros(input.shape, dtype=input.dtype) |
|
else: |
|
output = np.zeros(input.shape, dtype=np.float64) |
|
elif type(output) is type: |
|
if output not in [np.complex64, np.complex128, |
|
np.float32, np.float64]: |
|
raise RuntimeError("output type not supported") |
|
output = np.zeros(input.shape, dtype=output) |
|
elif output.shape != input.shape: |
|
raise RuntimeError("output shape not correct") |
|
return output |
|
|
|
|
|
def _get_output_fourier_complex(output, input): |
|
if output is None: |
|
if input.dtype.type in [np.complex64, np.complex128]: |
|
output = np.zeros(input.shape, dtype=input.dtype) |
|
else: |
|
output = np.zeros(input.shape, dtype=np.complex128) |
|
elif type(output) is type: |
|
if output not in [np.complex64, np.complex128]: |
|
raise RuntimeError("output type not supported") |
|
output = np.zeros(input.shape, dtype=output) |
|
elif output.shape != input.shape: |
|
raise RuntimeError("output shape not correct") |
|
return output |
|
|
|
|
|
def fourier_gaussian(input, sigma, n=-1, axis=-1, output=None): |
|
""" |
|
Multidimensional Gaussian fourier filter. |
|
|
|
The array is multiplied with the fourier transform of a Gaussian |
|
kernel. |
|
|
|
Parameters |
|
---------- |
|
input : array_like |
|
The input array. |
|
sigma : float or sequence |
|
The sigma of the Gaussian kernel. If a float, `sigma` is the same for |
|
all axes. If a sequence, `sigma` has to contain one value for each |
|
axis. |
|
n : int, optional |
|
If `n` is negative (default), then the input is assumed to be the |
|
result of a complex fft. |
|
If `n` is larger than or equal to zero, the input is assumed to be the |
|
result of a real fft, and `n` gives the length of the array before |
|
transformation along the real transform direction. |
|
axis : int, optional |
|
The axis of the real transform. |
|
output : ndarray, optional |
|
If given, the result of filtering the input is placed in this array. |
|
|
|
Returns |
|
------- |
|
fourier_gaussian : ndarray |
|
The filtered input. |
|
|
|
Examples |
|
-------- |
|
>>> from scipy import ndimage, datasets |
|
>>> import numpy.fft |
|
>>> import matplotlib.pyplot as plt |
|
>>> fig, (ax1, ax2) = plt.subplots(1, 2) |
|
>>> plt.gray() # show the filtered result in grayscale |
|
>>> ascent = datasets.ascent() |
|
>>> input_ = numpy.fft.fft2(ascent) |
|
>>> result = ndimage.fourier_gaussian(input_, sigma=4) |
|
>>> result = numpy.fft.ifft2(result) |
|
>>> ax1.imshow(ascent) |
|
>>> ax2.imshow(result.real) # the imaginary part is an artifact |
|
>>> plt.show() |
|
""" |
|
input = np.asarray(input) |
|
output = _get_output_fourier(output, input) |
|
axis = normalize_axis_index(axis, input.ndim) |
|
sigmas = _ni_support._normalize_sequence(sigma, input.ndim) |
|
sigmas = np.asarray(sigmas, dtype=np.float64) |
|
if not sigmas.flags.contiguous: |
|
sigmas = sigmas.copy() |
|
|
|
_nd_image.fourier_filter(input, sigmas, n, axis, output, 0) |
|
return output |
|
|
|
|
|
def fourier_uniform(input, size, n=-1, axis=-1, output=None): |
|
""" |
|
Multidimensional uniform fourier filter. |
|
|
|
The array is multiplied with the Fourier transform of a box of given |
|
size. |
|
|
|
Parameters |
|
---------- |
|
input : array_like |
|
The input array. |
|
size : float or sequence |
|
The size of the box used for filtering. |
|
If a float, `size` is the same for all axes. If a sequence, `size` has |
|
to contain one value for each axis. |
|
n : int, optional |
|
If `n` is negative (default), then the input is assumed to be the |
|
result of a complex fft. |
|
If `n` is larger than or equal to zero, the input is assumed to be the |
|
result of a real fft, and `n` gives the length of the array before |
|
transformation along the real transform direction. |
|
axis : int, optional |
|
The axis of the real transform. |
|
output : ndarray, optional |
|
If given, the result of filtering the input is placed in this array. |
|
|
|
Returns |
|
------- |
|
fourier_uniform : ndarray |
|
The filtered input. |
|
|
|
Examples |
|
-------- |
|
>>> from scipy import ndimage, datasets |
|
>>> import numpy.fft |
|
>>> import matplotlib.pyplot as plt |
|
>>> fig, (ax1, ax2) = plt.subplots(1, 2) |
|
>>> plt.gray() # show the filtered result in grayscale |
|
>>> ascent = datasets.ascent() |
|
>>> input_ = numpy.fft.fft2(ascent) |
|
>>> result = ndimage.fourier_uniform(input_, size=20) |
|
>>> result = numpy.fft.ifft2(result) |
|
>>> ax1.imshow(ascent) |
|
>>> ax2.imshow(result.real) # the imaginary part is an artifact |
|
>>> plt.show() |
|
""" |
|
input = np.asarray(input) |
|
output = _get_output_fourier(output, input) |
|
axis = normalize_axis_index(axis, input.ndim) |
|
sizes = _ni_support._normalize_sequence(size, input.ndim) |
|
sizes = np.asarray(sizes, dtype=np.float64) |
|
if not sizes.flags.contiguous: |
|
sizes = sizes.copy() |
|
_nd_image.fourier_filter(input, sizes, n, axis, output, 1) |
|
return output |
|
|
|
|
|
def fourier_ellipsoid(input, size, n=-1, axis=-1, output=None): |
|
""" |
|
Multidimensional ellipsoid Fourier filter. |
|
|
|
The array is multiplied with the fourier transform of an ellipsoid of |
|
given sizes. |
|
|
|
Parameters |
|
---------- |
|
input : array_like |
|
The input array. |
|
size : float or sequence |
|
The size of the box used for filtering. |
|
If a float, `size` is the same for all axes. If a sequence, `size` has |
|
to contain one value for each axis. |
|
n : int, optional |
|
If `n` is negative (default), then the input is assumed to be the |
|
result of a complex fft. |
|
If `n` is larger than or equal to zero, the input is assumed to be the |
|
result of a real fft, and `n` gives the length of the array before |
|
transformation along the real transform direction. |
|
axis : int, optional |
|
The axis of the real transform. |
|
output : ndarray, optional |
|
If given, the result of filtering the input is placed in this array. |
|
|
|
Returns |
|
------- |
|
fourier_ellipsoid : ndarray |
|
The filtered input. |
|
|
|
Notes |
|
----- |
|
This function is implemented for arrays of rank 1, 2, or 3. |
|
|
|
Examples |
|
-------- |
|
>>> from scipy import ndimage, datasets |
|
>>> import numpy.fft |
|
>>> import matplotlib.pyplot as plt |
|
>>> fig, (ax1, ax2) = plt.subplots(1, 2) |
|
>>> plt.gray() # show the filtered result in grayscale |
|
>>> ascent = datasets.ascent() |
|
>>> input_ = numpy.fft.fft2(ascent) |
|
>>> result = ndimage.fourier_ellipsoid(input_, size=20) |
|
>>> result = numpy.fft.ifft2(result) |
|
>>> ax1.imshow(ascent) |
|
>>> ax2.imshow(result.real) # the imaginary part is an artifact |
|
>>> plt.show() |
|
""" |
|
input = np.asarray(input) |
|
if input.ndim > 3: |
|
raise NotImplementedError("Only 1d, 2d and 3d inputs are supported") |
|
output = _get_output_fourier(output, input) |
|
if output.size == 0: |
|
|
|
|
|
return output |
|
axis = normalize_axis_index(axis, input.ndim) |
|
sizes = _ni_support._normalize_sequence(size, input.ndim) |
|
sizes = np.asarray(sizes, dtype=np.float64) |
|
if not sizes.flags.contiguous: |
|
sizes = sizes.copy() |
|
_nd_image.fourier_filter(input, sizes, n, axis, output, 2) |
|
return output |
|
|
|
|
|
def fourier_shift(input, shift, n=-1, axis=-1, output=None): |
|
""" |
|
Multidimensional Fourier shift filter. |
|
|
|
The array is multiplied with the Fourier transform of a shift operation. |
|
|
|
Parameters |
|
---------- |
|
input : array_like |
|
The input array. |
|
shift : float or sequence |
|
The size of the box used for filtering. |
|
If a float, `shift` is the same for all axes. If a sequence, `shift` |
|
has to contain one value for each axis. |
|
n : int, optional |
|
If `n` is negative (default), then the input is assumed to be the |
|
result of a complex fft. |
|
If `n` is larger than or equal to zero, the input is assumed to be the |
|
result of a real fft, and `n` gives the length of the array before |
|
transformation along the real transform direction. |
|
axis : int, optional |
|
The axis of the real transform. |
|
output : ndarray, optional |
|
If given, the result of shifting the input is placed in this array. |
|
|
|
Returns |
|
------- |
|
fourier_shift : ndarray |
|
The shifted input. |
|
|
|
Examples |
|
-------- |
|
>>> from scipy import ndimage, datasets |
|
>>> import matplotlib.pyplot as plt |
|
>>> import numpy.fft |
|
>>> fig, (ax1, ax2) = plt.subplots(1, 2) |
|
>>> plt.gray() # show the filtered result in grayscale |
|
>>> ascent = datasets.ascent() |
|
>>> input_ = numpy.fft.fft2(ascent) |
|
>>> result = ndimage.fourier_shift(input_, shift=200) |
|
>>> result = numpy.fft.ifft2(result) |
|
>>> ax1.imshow(ascent) |
|
>>> ax2.imshow(result.real) # the imaginary part is an artifact |
|
>>> plt.show() |
|
""" |
|
input = np.asarray(input) |
|
output = _get_output_fourier_complex(output, input) |
|
axis = normalize_axis_index(axis, input.ndim) |
|
shifts = _ni_support._normalize_sequence(shift, input.ndim) |
|
shifts = np.asarray(shifts, dtype=np.float64) |
|
if not shifts.flags.contiguous: |
|
shifts = shifts.copy() |
|
_nd_image.fourier_shift(input, shifts, n, axis, output) |
|
return output |
|
|