Transforms module

The Fourier and other transforms.

Contents

Classes

template<typename T>
class dip::DFT
An object that encapsulates the Discrete Fourier Transform (DFT).
template<typename T>
class dip::RDFT
An object that encapsulates the real-valued Discrete Fourier Transform (DFT).

Aliases

using dip::Option::DFTOptions = dip::detail::Options
Determines working mode for dip::DFT and dip::RDFT. Combines multiple dip::Option::DFTOption values,.

Enums

enum class dip::Option::DFTOption: uint8{ InPlace, TrashInput, Aligned }
Determines working mode for dip::DFT and dip::RDFT.

Functions

auto dip::GetOptimalDFTSize(dip::uint size0, bool larger = true) -> dip::uint
Returns a size equal or larger to size0 that is efficient for the DFT implementation.
void dip::FourierTransform(dip::Image const& in, dip::Image& out, dip::StringSet const& options = {}, dip::BooleanArray process = {})
Computes the forward and inverse Fourier Transform
void dip::InverseFourierTransform(dip::Image const& in, dip::Image& out, dip::StringSet options = {}, dip::BooleanArray process = {})
Inverse Fourier Transform. Convenience function that calls dip::FourierTransform after adding “inverse” to options.
auto dip::OptimalFourierTransformSize(dip::uint size, dip::String const& which = "larger") -> dip::uint
Returns the next larger (or smaller) multiple of {2, 3, 5}, an image of this size is more efficient for FFT computations.
void dip::RieszTransform(dip::Image const& in, dip::Image& out, dip::String const& inRepresentation = S::SPATIAL, dip::String const& outRepresentation = S::SPATIAL, dip::BooleanArray process = {})
Computes the Riesz transform of a scalar image.
void dip::StationaryWaveletTransform(dip::Image const& in, dip::Image& out, dip::uint nLevels = 4, dip::StringArray const& boundaryCondition = {}, dip::BooleanArray const& process = {})
Computes a stationary wavelet transform (also called à-trous wavelet decomposition).
void dip::HaarWaveletTransform(dip::Image const& in, dip::Image& out, dip::uint nLevels = 4, dip::String const& direction = S::FORWARD, dip::BooleanArray process = {})
Computes the Haar wavelet transform or its inverse.

Variables

dip::uint const dip::maximumDFTSize
The largest size supported by dip::DFT and dip::FourierTransform. Is equal to 231-1 when using FFTW, or 264-1 when using PocketFFT.
bool const dip::usingFFTW
Is true if dip::DFT and dip::RDFT use the FFTW library, or false if they use PocketFFT.

Alias documentation

using dip::Option::DFTOptions = dip::detail::Options

Determines working mode for dip::DFT and dip::RDFT. Combines multiple dip::Option::DFTOption values,.

Enum documentation

enum class dip::Option::DFTOption: uint8

Determines working mode for dip::DFT and dip::RDFT.

Implicitly casts to dip::Option::DFTOptions. Combine constants together with the + operator.

Enumerators
InPlace = 0 Work in place, the input and output buffers are the same.
TrashInput = 1 Allowed to trash the input buffer, we don’t need to preserve it.
Aligned = 2 Both buffers are aligned to 16-byte boundaries.

Function documentation

dip::uint dip::GetOptimalDFTSize(dip::uint size0, bool larger = true)

Returns a size equal or larger to size0 that is efficient for the DFT implementation.

Set larger to false to return a size equal or smaller instead.

Returns 0 if size0 is too large for the DFT implementation.

Prefer to use dip::OptimalFourierTransformSize in your applications, it will throw an error if the transform size is too large.

void dip::FourierTransform(dip::Image const& in, dip::Image& out, dip::StringSet const& options = {}, dip::BooleanArray process = {})

Computes the forward and inverse Fourier Transform

The Fourier transform as implemented here places the origin (frequency 0) in the middle of the image. If the image has N pixels along a dimension, then the origin will be at pixel N/2 along that dimension, where N/2 is the integer division, and hence truncates the result for odd values of N. For example, an image of 256 pixels wide will have the origin at pixel 128 (right of the center), whereas an image of 255 pixels will have the origin at pixel 127 (dead in the middle). The same is true for the spatial domain, which is only obvious when computing the Fourier transform of a convolution kernel.

As it is commonly defined, the Fourier transform is not normalized, and the inverse transform is normalized by 1/size for each dimension. This normalization is necessary for the sequence of forward and inverse transform to be idempotent. However, it is possible to change where the normalization is applied. For example, DIPlib 2 used identical normalization for each of the two transforms. The advantage of using the common definition without normalization in the forward transform is that it is straightforward to transform an image and a convolution kernel, multiply them, and apply the inverse transform, as an efficient way to compute the convolution. With any other normalization, this process would require an extra multiplication by a constant to undo the normalization in the forward transform of the convolution kernel.

This function will compute the Fourier Transform along the dimensions indicated by process. If process is an empty array, all dimensions will be processed (normal multi-dimensional transform).

options is a set of strings that indicate how the transform is applied:

  • “inverse”: compute the inverse transform; not providing this string causes the the forward transform to be computed.
  • “real”: assumes that the (complex) input is conjugate symmetric, and returns a real-valued result. Can only be used together with “inverse”.
  • “fast”: pads the input to a “nice” size, multiple of 2, 3 and 5, which can be processed faster.
  • “corner”: sets the origin to the top-left corner of the image (both in the spatial and the frequency domain). This yields a standard DFT (Discrete Fourier Transform).
  • “symmetric”: the normalization is made symmetric, where both forward and inverse transforms are normalized by the same amount. Each transform is multiplied by 1/sqrt(size) for each dimension. This makes the transform identical to how it was in DIPlib 2.

For tensor images, each plane is transformed independently.

With the “fast” mode, the input might be padded. This padding causes the output to be interpolated. This is not always a problem when computing convolutions or correlations, but could introduce e.g. edge effects in the result of the convolution. The normalization applied relates to the output sizes, not the input sizes. Padding is applied as follows:

  • Forward transform: If "corner" is given, the padding is to the right of each image line. Otherwise it is split evenly on both sides, in such a way that the origin remains in the middle pixel. Added pixels replicate the border pixel (the “zero order” boundary condition, see dip::BoundaryCondition). Its effect is similar to padding with zeros, but with reduced edge effects.
  • Inverse transform: Padding is with zeros (“add zeros” boundary condition), and naturally add higher-frequency components. If "corner" is given, the padding is thus in the middle of each image line. Otherwise, the padding is symmetrically on both ends of the line.

void dip::InverseFourierTransform(dip::Image const& in, dip::Image& out, dip::StringSet options = {}, dip::BooleanArray process = {})

Inverse Fourier Transform. Convenience function that calls dip::FourierTransform after adding “inverse” to options.

dip::uint dip::OptimalFourierTransformSize(dip::uint size, dip::String const& which = "larger")

Returns the next larger (or smaller) multiple of {2, 3, 5}, an image of this size is more efficient for FFT computations.

The largest value that can be returned is 2125764000 (smaller than 231-1, the largest possible value of an int on most platforms).

By default, which is "larger", in which case it returns the next larger value. Set it to "smaller" to obtain the next smaller value instead.

Pad an image with zeros to the next larger size or crop the image to the next smaller size to improve FFT performance.

void dip::RieszTransform(dip::Image const& in, dip::Image& out, dip::String const& inRepresentation = S::SPATIAL, dip::String const& outRepresentation = S::SPATIAL, dip::BooleanArray process = {})

Computes the Riesz transform of a scalar image.

The Riesz transform is the multi-dimensional generalization of the Hilbert transform, and identical to it for one-dimensional images. It is computed through the Fourier domain by

\[ R_j f = \mathcal{F}^{-1} \left\{ -i\frac{x_j}{|x|}(\mathcal{F}f) \right\} \; , \]

where \(f\) is the input image and \(x\) is the coordinate vector.

out is a vector image with one element per image dimension. If process is given, it specifies which dimensions to include in the output vector image. in must be scalar.

inRepresentation and outRepresentation can be "spatial" or "frequency", and indicate in which domain the input image is, and in which domain the output image should be. If inRepresentation is "frequency", the input image must already be in the frequency domain, and will not be transformed again. Likewise, if outRepresentation is "frequency", the output image will not be transformed to the spatial domain. Use these flags to prevent redundant back-and-forth transformations if other processing in the frequency domain is necessary.

void dip::StationaryWaveletTransform(dip::Image const& in, dip::Image& out, dip::uint nLevels = 4, dip::StringArray const& boundaryCondition = {}, dip::BooleanArray const& process = {})

Computes a stationary wavelet transform (also called à-trous wavelet decomposition).

For an n-dimensional input image, creates an (n+1)-dimensional output image where each slice corresponds to one level of the wavelet transform. The first slice is the lowest level (finest detail), and subsequent slices correspond to increasingly coarser levels. The last slice corresponds to the residue. There are nLevels + 1 slices in total.

The filter used to smooth the image for the first level is [1/16, 1/4, 3/8, 1/4, 1/16], applied to each dimension in sequence through dip::SeparableConvolution. For subsequent levels, zeros are inserted into this filter.

boundaryCondition is passed to dip::SeparableConvolution to determine how to extend the input image past its boundary. process can be used to exclude some dimensions from the filtering.

in can have any number of dimensions, any number of tensor elements, and any data type. out will have the smallest signed data type that can hold all values of in (see dip::DataType::SuggestSigned). Note that the first nLevels slices will contain negative values, even if in is purely positive, as these levels are the difference between two differently smoothed images.

Summing the output image along its last dimension will yield the input image:

dip::Image img = ...;
dip::Image swt = StationaryWaveletTransform( img );
dip::BooleanArray process( swt.Dimensionality(), false );
process.back() = true;
img == Sum( swt, {}, process ).Squeeze();

void dip::HaarWaveletTransform(dip::Image const& in, dip::Image& out, dip::uint nLevels = 4, dip::String const& direction = S::FORWARD, dip::BooleanArray process = {})

Computes the Haar wavelet transform or its inverse.

Recursively splits the image into low-frequency and high-frequency components. Each step splits an n-dimensional image into 2n smaller blocks, the one in the top-left corner containing the low-frequency components. The low-frequency block is the one recursively split in the next step. The output image has the same sizes as the input image, but is of a floating-point type.

However, the input must have sizes multiple of 2nLevels. The image will be padded with zeros for the forward transform if this is not the case. For the inverse transform, an exception will the thrown if the sizes are not as expected.

direction can be "forward" or "inverse". Applying a forward transform to any image, and an inverse transform to the result, will yield an image identical to the input image, up to rounding errors, and potentially with some padding to the right and bottom.

process can be used to exclude some dimensions from the filtering.

Variable documentation

dip::uint const dip::maximumDFTSize

The largest size supported by dip::DFT and dip::FourierTransform. Is equal to 231-1 when using FFTW, or 264-1 when using PocketFFT.

bool const dip::usingFFTW

Is true if dip::DFT and dip::RDFT use the FFTW library, or false if they use PocketFFT.