[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

| Convolution filters for multi-dimensional arrays. |

## Functions
template<... >
void | convolveFFT (...)
| Convolve an array with a kernel by means of the Fourier transform.
template<... >
void | convolveFFTComplex (...)
| Convolve a complex-valued array by means of the Fourier transform.
template<... >
void | convolveFFTComplexMany (...)
| Convolve a complex-valued array with a sequence of kernels by means of the Fourier transform.
template<... >
void | convolveFFTMany (...)
| Convolve a real-valued array with a sequence of kernels by means of the Fourier transform.
template<... >
void | convolveMultiArrayOneDimension (...)
| Convolution along a single dimension of a multi-dimensional arrays.
template<... >
void | gaussianGradientMultiArray (...)
| Calculate Gaussian gradient of a multi-dimensional arrays.
template<... >
void | gaussianSmoothMultiArray (...)
| Isotropic Gaussian smoothing of a multi-dimensional arrays.
template<... >
void | hessianOfGaussianMultiArray (...)
| Calculate Hessian matrix of a N-dimensional arrays using Gaussian derivative filters.
template<... >
void | laplacianOfGaussianMultiArray (...)
| Calculate Laplacian of a N-dimensional arrays using Gaussian derivative filters.
template<... >
void | separableConvolveMultiArray (...)
| Separated convolution on multi-dimensional arrays.
template<... >
void | structureTensorMultiArray (...)
| Calculate th structure tensor of a multi-dimensional arrays.
template<... >
void | symmetricGradientMultiArray (...)
| Calculate gradient of a multi-dimensional arrays using symmetric difference filters.

## Detailed Description

These functions realize a separable convolution on an arbitrary dimensional array that is specified by iterators (compatible to Multi-dimensional Array Iterators) and shape objects. It can therefore be applied to a wide range of data structures (vigra::MultiArrayView, vigra::MultiArray etc.).

## Function Documentation

void vigra::separableConvolveMultiArray | ( |  | ... | ) |

Separated convolution on multi-dimensional arrays.

This function computes a separated convolution on all dimensions of the given multi-dimensional array. Both source and destination arrays are represented by iterators, shape objects and accessors. The destination array is required to already have the correct size.

There are two variants of this functions: one takes a single kernel of type vigra::Kernel1D which is then applied to all dimensions, whereas the other requires an iterator referencing a sequence of vigra::Kernel1D objects, one for every dimension of the data. Then the first kernel in this sequence is applied to the innermost dimension (e.g. the x-dimension of an image), while the last is applied to the outermost dimension (e.g. the z-dimension in a 3D image).

This function may work in-place, which means that `siter == diter` is allowed. A full-sized internal array is only allocated if working on the destination array directly would cause round-off errors (i.e. if `typeid(typename NumericTraits<typename DestAccessor::value_type>::RealPromote) != typeid(typename DestAccessor::value_type)`.

If `start` and `stop` have non-default values, they must represent a valid subarray of the input array. The convolution is then restricted to that subarray, and it is assumed that the output array only refers to the subarray (i.e. `diter` points to the element corresponding to `start`).

Declarations:

pass arguments explicitly:

        namespace vigra {
            // apply the same kernel to all dimensions
            template <class SrcIterator, class SrcShape, class SrcAccessor,
                      class DestIterator, class DestAccessor, class T>
            void
            separableConvolveMultiArray(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
                                        DestIterator diter, DestAccessor dest,
                                        Kernel1D<T> const & kernel,
                                        SrcShape const & start = SrcShape(),
                                        SrcShape const & stop = SrcShape());

            // apply each kernel from the sequence 'kernels' in turn
            template <class SrcIterator, class SrcShape, class SrcAccessor,
                      class DestIterator, class DestAccessor, class KernelIterator>
            void
            separableConvolveMultiArray(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
                                        DestIterator diter, DestAccessor dest,
                                        KernelIterator kernels,
                                        SrcShape const & start = SrcShape(),
                                        SrcShape const & stop = SrcShape());
        }

use argument objects in conjunction with Argument Object Factories :

        namespace vigra {
            // apply the same kernel to all dimensions
            template <class SrcIterator, class SrcShape, class SrcAccessor,
                      class DestIterator, class DestAccessor, class T>
            void
            separableConvolveMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
                                        pair<DestIterator, DestAccessor> const & dest,
                                        Kernel1D<T> const & kernel,
                                        SrcShape const & start = SrcShape(),
                                        SrcShape const & stop = SrcShape());

            // apply each kernel from the sequence 'kernels' in turn
            template <class SrcIterator, class SrcShape, class SrcAccessor,
                      class DestIterator, class DestAccessor, class KernelIterator>
            void
            separableConvolveMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
                                        pair<DestIterator, DestAccessor> const & dest,
                                        KernelIterator kernels,
                                        SrcShape const & start = SrcShape(),
                                        SrcShape const & stop = SrcShape());
        }

Usage:

#include <vigra/multi_convolution.hxx>

        MultiArray<3, unsigned char>::size_type shape(width, height, depth);
        MultiArray<3, unsigned char> source(shape);
        MultiArray<3, float> dest(shape);
        ...
        Kernel1D<float> gauss;
        gauss.initGaussian(sigma);
        // create 3 Gauss kernels, one for each dimension
        ArrayVector<Kernel1D<float> > kernels(3, gauss);

        // perform Gaussian smoothing on all dimensions
        separableConvolveMultiArray(srcMultiArrayRange(source), destMultiArray(dest),
                                    kernels.begin());

Required Interface:

see separableConvolveMultiArray(), in addition:

        int dimension = 0;
        VectorElementAccessor<DestAccessor> elementAccessor(0, dest);

See also:
  vigra::Kernel1D, convolveLine()

void vigra::convolveMultiArrayOneDimension | ( |  | ... | ) |

Convolution along a single dimension of a multi-dimensional arrays.

This function computes a convolution along one dimension (specified by the parameter `dim` of the given multi-dimensional array with the given `kernel`. Both source and destination arrays are represented by iterators, shape objects and accessors. The destination array is required to already have the correct size.

If `start` and `stop` have non-default values, they must represent a valid subarray of the input array. The convolution is then restricted to that subarray, and it is assumed that the output array only refers to the subarray (i.e. `diter` points to the element corresponding to `start`).

This function may work in-place, which means that `siter == diter` is allowed.

Declarations:

pass arguments explicitly:

        namespace vigra {
            template <class SrcIterator, class SrcShape, class SrcAccessor,
                      class DestIterator, class DestAccessor, class T>
            void
            convolveMultiArrayOneDimension(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
                                           DestIterator diter, DestAccessor dest,
                                           unsigned int dim, vigra::Kernel1D<T> const & kernel,
                                           SrcShape const & start = SrcShape(),
                                           SrcShape const & stop = SrcShape());
        }

use argument objects in conjunction with Argument Object Factories :

        namespace vigra {
            template <class SrcIterator, class SrcShape, class SrcAccessor,
                      class DestIterator, class DestAccessor, class T>
            void
            convolveMultiArrayOneDimension(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
                                           pair<DestIterator, DestAccessor> const & dest,
                                           unsigned int dim, vigra::Kernel1D<T> const & kernel,
                                           SrcShape const & start = SrcShape(),
                                           SrcShape const & stop = SrcShape());
        }

Usage:

#include <vigra/multi_convolution.hxx>

        MultiArray<3, unsigned char>::size_type shape(width, height, depth);
        MultiArray<3, unsigned char> source(shape);
        MultiArray<3, float> dest(shape);
        ...
        Kernel1D<float> gauss;
        gauss.initGaussian(sigma);

        // perform Gaussian smoothing along dimensions 1 (height)
        convolveMultiArrayOneDimension(srcMultiArrayRange(source), destMultiArray(dest), 1, gauss);

See also:
  separableConvolveMultiArray()

void vigra::gaussianSmoothMultiArray | ( |  | ... | ) |

Isotropic Gaussian smoothing of a multi-dimensional arrays.

This function computes an isotropic convolution of the given N-dimensional array with a Gaussian filter at the given standard deviation `sigma`. Both source and destination arrays are represented by iterators, shape objects and accessors. The destination array is required to already have the correct size. This function may work in-place, which means that `siter == diter` is allowed. It is implemented by a call to separableConvolveMultiArray() with the appropriate kernel.

Anisotropic data should be passed with appropriate ConvolutionOptions, the parameter `opt` is otherwise optional unless the parameter `sigma` is left out.

Declarations:

pass arguments explicitly:

        namespace vigra {
            template <class SrcIterator, class SrcShape, class SrcAccessor,
                      class DestIterator, class DestAccessor>
            void
            gaussianSmoothMultiArray(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
                                     DestIterator diter, DestAccessor dest,
                                     double sigma, const ConvolutionOptions<N> & opt);
        }

use argument objects in conjunction with Argument Object Factories :

        namespace vigra {
            template <class SrcIterator, class SrcShape, class SrcAccessor,
                      class DestIterator, class DestAccessor>
            void
            gaussianSmoothMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
                                     pair<DestIterator, DestAccessor> const & dest,
                                     double sigma, const ConvolutionOptions<N> & opt);
        }

Usage:

#include <vigra/multi_convolution.hxx>

        MultiArray<3, unsigned char>::size_type shape(width, height, depth);
        MultiArray<3, unsigned char> source(shape);
        MultiArray<3, float> dest(shape);
        ...
        // perform isotropic Gaussian smoothing at scale 'sigma'
        gaussianSmoothMultiArray(srcMultiArrayRange(source), destMultiArray(dest), sigma);

Usage with anisotropic data:

#include <vigra/multi_convolution.hxx>

        MultiArray<3, unsigned char>::size_type shape(width, height, depth);
        MultiArray<3, unsigned char> source(shape);
        MultiArray<3, float> dest(shape);
        TinyVector<float, 3> step_size;
        TinyVector<float, 3> resolution_sigmas;
        ...
        // perform anisotropic Gaussian smoothing at scale 'sigma'
        gaussianSmoothMultiArray(srcMultiArrayRange(source), destMultiArray(dest), sigma,
                                 ConvolutionOptions<3>().stepSize(step_size).resolutionStdDev(resolution_sigmas));

See also:
  separableConvolveMultiArray()

void vigra::gaussianGradientMultiArray | ( |  | ... | ) |

Calculate Gaussian gradient of a multi-dimensional arrays.

This function computes the Gaussian gradient of the given N-dimensional array with a sequence of first-derivative-of-Gaussian filters at the given standard deviation `sigma` (differentiation is applied to each dimension in turn, starting with the innermost dimension). Both source and destination arrays are represented by iterators, shape objects and accessors. The destination array is required to have a vector valued pixel type with as many elements as the number of dimensions. This function is implemented by calls to separableConvolveMultiArray() with the appropriate kernels.

Anisotropic data should be passed with appropriate ConvolutionOptions, the parameter `opt` is otherwise optional unless the parameter `sigma` is left out.

Declarations:

pass arguments explicitly:

        namespace vigra {
            template <class SrcIterator, class SrcShape, class SrcAccessor,
                      class DestIterator, class DestAccessor>
            void
            gaussianGradientMultiArray(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
                                       DestIterator diter, DestAccessor dest,
                                       double sigma, const ConvolutionOptions<N> & opt);
        }

use argument objects in conjunction with Argument Object Factories :

        namespace vigra {
            template <class SrcIterator, class SrcShape, class SrcAccessor,
                      class DestIterator, class DestAccessor>
            void
            gaussianGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
                                       pair<DestIterator, DestAccessor> const & dest,
                                       double sigma, const ConvolutionOptions<N> & opt);
        }

Usage:

#include <vigra/multi_convolution.hxx>

        MultiArray<3, unsigned char>::size_type shape(width, height, depth);
        MultiArray<3, unsigned char> source(shape);
        MultiArray<3, TinyVector<float, 3> > dest(shape);
        ...
        // compute Gaussian gradient at scale sigma
        gaussianGradientMultiArray(srcMultiArrayRange(source), destMultiArray(dest), sigma);

Usage with anisotropic data:

#include <vigra/multi_convolution.hxx>

        MultiArray<3, unsigned char>::size_type shape(width, height, depth);
        MultiArray<3, unsigned char> source(shape);
        MultiArray<3, TinyVector<float, 3> > dest(shape);
        TinyVector<float, 3> step_size;
        TinyVector<float, 3> resolution_sigmas;
        ...
        // compute Gaussian gradient at scale sigma
        gaussianGradientMultiArray(srcMultiArrayRange(source), destMultiArray(dest), sigma,
                                   ConvolutionOptions<3>().stepSize(step_size).resolutionStdDev(resolution_sigmas));

Required Interface:

see separableConvolveMultiArray(), in addition:

        int dimension = 0;
        VectorElementAccessor<DestAccessor> elementAccessor(0, dest);

See also:
  separableConvolveMultiArray()

void vigra::symmetricGradientMultiArray | ( |  | ... | ) |

Calculate gradient of a multi-dimensional arrays using symmetric difference filters.

This function computes the gradient of the given N-dimensional array with a sequence of symmetric difference filters a (differentiation is applied to each dimension in turn, starting with the innermost dimension). Both source and destination arrays are represented by iterators, shape objects and accessors. The destination array is required to have a vector valued pixel type with as many elements as the number of dimensions. This function is implemented by calls to convolveMultiArrayOneDimension() with the symmetric difference kernel.

Anisotropic data should be passed with appropriate ConvolutionOptions, the parameter `opt` is optional otherwise.

Declarations:

pass arguments explicitly:

        namespace vigra {
            template <class SrcIterator, class SrcShape, class SrcAccessor,
                      class DestIterator, class DestAccessor>
            void
            symmetricGradientMultiArray(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
                                        DestIterator diter, DestAccessor dest,
                                        const ConvolutionOptions<N> & opt);
        }

use argument objects in conjunction with Argument Object Factories :

        namespace vigra {
            template <class SrcIterator, class SrcShape, class SrcAccessor,
                      class DestIterator, class DestAccessor>
            void
            symmetricGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
                                        pair<DestIterator, DestAccessor> const & dest,
                                        const ConvolutionOptions<N> & opt);
        }

Usage:

#include <vigra/multi_convolution.hxx>

        MultiArray<3, unsigned char>::size_type shape(width, height, depth);
        MultiArray<3, unsigned char> source(shape);
        MultiArray<3, TinyVector<float, 3> > dest(shape);
        ...
        // compute gradient
        symmetricGradientMultiArray(srcMultiArrayRange(source), destMultiArray(dest));

Usage with anisotropic data:

#include <vigra/multi_convolution.hxx>

        MultiArray<3, unsigned char>::size_type shape(width, height, depth);
        MultiArray<3, unsigned char> source(shape);
        MultiArray<3, TinyVector<float, 3> > dest(shape);
        TinyVector<float, 3> step_size;
        ...
        // compute gradient
        symmetricGradientMultiArray(srcMultiArrayRange(source), destMultiArray(dest),
                                    ConvolutionOptions<3>().stepSize(step_size));

Required Interface:

see convolveMultiArrayOneDimension(), in addition:

        int dimension = 0;
        VectorElementAccessor<DestAccessor> elementAccessor(0, dest);

See also:
  convolveMultiArrayOneDimension()

void vigra::laplacianOfGaussianMultiArray | ( |  | ... | ) |

Calculate Laplacian of a N-dimensional arrays using Gaussian derivative filters.

This function computes the Laplacian the given N-dimensional array with a sequence of second-derivative-of-Gaussian filters at the given standard deviation `sigma`. Both source and destination arrays are represented by iterators, shape objects and accessors. Both source and destination arrays must have scalar value_type. This function is implemented by calls to separableConvolveMultiArray() with the appropriate kernels, followed by summation.

Anisotropic data should be passed with appropriate ConvolutionOptions, the parameter `opt` is otherwise optional unless the parameter `sigma` is left out.

Declarations:

pass arguments explicitly:

        namespace vigra {
            template <class SrcIterator, class SrcShape, class SrcAccessor,
                      class DestIterator, class DestAccessor>
            void
            laplacianOfGaussianMultiArray(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
                                          DestIterator diter, DestAccessor dest,
                                          double sigma, const ConvolutionOptions<N> & opt);
        }

use argument objects in conjunction with Argument Object Factories :

        namespace vigra {
            template <class SrcIterator, class SrcShape, class SrcAccessor,
                      class DestIterator, class DestAccessor>
            void
            laplacianOfGaussianMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
                                          pair<DestIterator, DestAccessor> const & dest,
                                          double sigma, const ConvolutionOptions<N> & opt);
        }

Usage:

#include <vigra/multi_convolution.hxx>

        MultiArray<3, float> source(shape);
        MultiArray<3, float> laplacian(shape);
        ...
        // compute Laplacian at scale sigma
        laplacianOfGaussianMultiArray(srcMultiArrayRange(source), destMultiArray(laplacian), sigma);

Usage with anisotropic data:

#include <vigra/multi_convolution.hxx>

        MultiArray<3, float> source(shape);
        MultiArray<3, float> laplacian(shape);
        TinyVector<float, 3> step_size;
        TinyVector<float, 3> resolution_sigmas;
        ...
        // compute Laplacian at scale sigma
        laplacianOfGaussianMultiArray(srcMultiArrayRange(source), destMultiArray(laplacian), sigma,
                                      ConvolutionOptions<3>().stepSize(step_size).resolutionStdDev(resolution_sigmas));

Required Interface:

see separableConvolveMultiArray(), in addition:

        int dimension = 0;
        VectorElementAccessor<DestAccessor> elementAccessor(0, dest);

See also:
  separableConvolveMultiArray()

void vigra::hessianOfGaussianMultiArray | ( |  | ... | ) |

Calculate Hessian matrix of a N-dimensional arrays using Gaussian derivative filters.

This function computes the Hessian matrix the given scalar N-dimensional array with a sequence of second-derivative-of-Gaussian filters at the given standard deviation `sigma`. Both source and destination arrays are represented by iterators, shape objects and accessors. The destination array must have a vector valued element type with N*(N+1)/2 elements (it represents the upper triangular part of the symmetric Hessian matrix). This function is implemented by calls to separableConvolveMultiArray() with the appropriate kernels.

Anisotropic data should be passed with appropriate ConvolutionOptions, the parameter `opt` is otherwise optional unless the parameter `sigma` is left out.

Declarations:

pass arguments explicitly:

        namespace vigra {
            template <class SrcIterator, class SrcShape, class SrcAccessor,
                      class DestIterator, class DestAccessor>
            void
            hessianOfGaussianMultiArray(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
                                        DestIterator diter, DestAccessor dest,
                                        double sigma, const ConvolutionOptions<N> & opt);
        }

use argument objects in conjunction with Argument Object Factories :

        namespace vigra {
            template <class SrcIterator, class SrcShape, class SrcAccessor,
                      class DestIterator, class DestAccessor>
            void
            hessianOfGaussianMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
                                        pair<DestIterator, DestAccessor> const & dest,
                                        double sigma, const ConvolutionOptions<N> & opt);
        }

Usage:

#include <vigra/multi_convolution.hxx>

        MultiArray<3, float> source(shape);
        MultiArray<3, TinyVector<float, 6> > dest(shape);
        ...
        // compute Hessian at scale sigma
        hessianOfGaussianMultiArray(srcMultiArrayRange(source), destMultiArray(dest), sigma);

Usage with anisotropic data:

#include <vigra/multi_convolution.hxx>

        MultiArray<3, float> source(shape);
        MultiArray<3, TinyVector<float, 6> > dest(shape);
        TinyVector<float, 3> step_size;
        TinyVector<float, 3> resolution_sigmas;
        ...
        // compute Hessian at scale sigma
        hessianOfGaussianMultiArray(srcMultiArrayRange(source), destMultiArray(dest), sigma,
                                    ConvolutionOptions<3>().stepSize(step_size).resolutionStdDev(resolution_sigmas));

Required Interface:

see separableConvolveMultiArray(), in addition:

        int dimension = 0;
        VectorElementAccessor<DestAccessor> elementAccessor(0, dest);

See also:
  separableConvolveMultiArray(), vectorToTensorMultiArray()

void vigra::structureTensorMultiArray | ( |  | ... | ) |

Calculate th structure tensor of a multi-dimensional arrays.

This function computes the gradient (outer product) tensor for each element of the given N-dimensional array with first-derivative-of-Gaussian filters at the given `innerScale`, followed by Gaussian smoothing at `outerScale`. Both source and destination arrays are represented by iterators, shape objects and accessors. The destination array must have a vector valued pixel type with N*(N+1)/2 elements (it represents the upper triangular part of the symmetric structure tensor matrix). If the source array is also vector valued, the resulting structure tensor is the sum of the individual tensors for each channel. This function is implemented by calls to separableConvolveMultiArray() with the appropriate kernels.

Anisotropic data should be passed with appropriate ConvolutionOptions, the parameter `opt` is otherwise optional unless the parameters `innerScale` and `outerScale` are both left out.

Declarations:

pass arguments explicitly:

        namespace vigra {
            template <class SrcIterator, class SrcShape, class SrcAccessor,
                      class DestIterator, class DestAccessor>
            void
            structureTensorMultiArray(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
                                      DestIterator diter, DestAccessor dest,
                                      double innerScale, double outerScale,
                                      const ConvolutionOptions<N> & opt);
        }

use argument objects in conjunction with Argument Object Factories :

        namespace vigra {
            template <class SrcIterator, class SrcShape, class SrcAccessor,
                      class DestIterator, class DestAccessor>
            void
            structureTensorMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
                                      pair<DestIterator, DestAccessor> const & dest,
                                      double innerScale, double outerScale,
                                      const ConvolutionOptions<N> & opt);
        }

Usage:

#include <vigra/multi_convolution.hxx>

        MultiArray<3, RGBValue<float> > source(shape);
        MultiArray<3, TinyVector<float, 6> > dest(shape);
        ...
        // compute structure tensor at scales innerScale and outerScale
        structureTensorMultiArray(srcMultiArrayRange(source), destMultiArray(dest), innerScale, outerScale);

Usage with anisotropic data:

#include <vigra/multi_convolution.hxx>

        MultiArray<3, RGBValue<float> > source(shape);
        MultiArray<3, TinyVector<float, 6> > dest(shape);
        TinyVector<float, 3> step_size;
        TinyVector<float, 3> resolution_sigmas;
        ...
        // compute structure tensor at scales innerScale and outerScale
        structureTensorMultiArray(srcMultiArrayRange(source), destMultiArray(dest), innerScale, outerScale,
                                  ConvolutionOptions<3>().stepSize(step_size).resolutionStdDev(resolution_sigmas));

Required Interface:

see separableConvolveMultiArray(), in addition:

        int dimension = 0;
        VectorElementAccessor<DestAccessor> elementAccessor(0, dest);

See also:
  separableConvolveMultiArray(), vectorToTensorMultiArray()

void vigra::convolveFFT | ( |  | ... | ) |

Convolve an array with a kernel by means of the Fourier transform.

Thanks to the convolution theorem of Fourier theory, a convolution in the spatial domain is equivalent to a multiplication in the frequency domain. Thus, for certain kernels (especially large, non-separable ones), it is advantageous to perform the convolution by first transforming both array and kernel to the frequency domain, multiplying the frequency representations, and transforming the result back into the spatial domain. Some kernels have a much simpler definition in the frequency domain, so that they are readily computed there directly, avoiding Fourier transformation of those kernels.

The following functions implement various variants of FFT-based convolution:

convolveFFT
  Convolve a real-valued input array with a kernel such that the result is also real-valued. That is, the kernel is either provided as a real-valued array in the spatial domain, or as a complex-valued array in the Fourier domain, using the half-space format of the R2C Fourier transform (see below).
convolveFFTMany
  Like `convolveFFT`, but you may provide many kernels at once (using an iterator pair specifying the kernel sequence). This has the advantage that the forward transform of the input array needs to be executed only once.
convolveFFTComplex
  Convolve a complex-valued input array with a complex-valued kernel, resulting in a complex-valued output array. An additional flag is used to specify whether the kernel is defined in the spatial or frequency domain.
convolveFFTComplexMany
  Like `convolveFFTComplex`, but you may provide many kernels at once (using an iterator pair specifying the kernel sequence). This has the advantage that the forward transform of the input array needs to be executed only once.

The output arrays must have the same shape as the input arrays. In the "Many" variants of the convolution functions, the kernels must all have the same shape.

The origin of the kernel is always assumed to be in the center of the kernel array (precisely, at the point `floor(kernel.shape() / 2.0)`, except when the half-space format is used, see below). The function moveDCToUpperLeft() will be called internally to align the kernel with the transformed input as appropriate.

If a real input is combined with a real kernel, the kernel is automatically assumed to be defined in the spatial domain. If a real input is combined with a complex kernel, the kernel is assumed to be defined in the Fourier domain in half-space format. If the input array is complex, a flag `fourierDomainKernel` determines where the kernel is defined.

When the kernel is defined in the spatial domain, the convolution functions will automatically pad (enlarge) the input array by at least the kernel radius in each direction. The newly added space is filled according to reflective boundary conditions in order to minimize border artifacts during convolution. It is thus ensured that convolution in the Fourier domain yields the same results as convolution in the spatial domain (e.g. when separableConvolveMultiArray() is called with the same kernel). A little further padding may be added to make sure that the padded array shape uses integers which have only small prime factors, because FFTW is then able to use the fastest possible algorithms. Any padding is automatically removed from the result arrays before the function returns.

When the kernel is defined in the frequency domain, it must be complex-valued, and its shape determines the shape of the Fourier representation (i.e. the input is padded according to the shape of the kernel). If we are going to perform a complex-valued convolution, the kernel must be defined for the entire frequency domain, and its shape directly determines the size of the FFT.

In contrast, a frequency domain kernel for a real-valued convolution must have symmetry properties that allow to drop half of the kernel coefficients, as in the R2C transform. That is, the kernel must have the half-space format, that is the shape returned by `fftwCorrespondingShapeR2C(fourier_shape)`, where `fourier_shape` is the desired logical shape of the frequency representation (and thus the size of the padded input). The origin of the kernel must be at the point `(0, floor(fourier_shape[0] / 2.0), ..., floor(fourier_shape[N-1] / 2.0))` (i.e. as in a regular kernel except for the first dimension).

The `Real` type in the declarations can be `double`, `float`, and `long double`. Your program must always link against `libfftw3`. If you use `float` or `long double` arrays, you must additionally link against `libfftw3f` and `libfftw3l` respectively.

The Fourier transform functions internally create FFTW plans which control the algorithm details. The plans are creates with the flag `FFTW_ESTIMATE`, i.e. optimal settings are guessed or read from saved "wisdom" files. If you need more control over planning, you can use the class FFTWConvolvePlan.

See also applyFourierFilter() for corresponding functionality on the basis of the old image iterator interface.

Declarations:

Real-valued convolution with kernel in the spatial domain:

        namespace vigra {
            template <unsigned int N, class Real, class C1, class C2, class C3>
            void
            convolveFFT(MultiArrayView<N, Real, C1> in,
                        MultiArrayView<N, Real, C2> kernel,
                        MultiArrayView<N, Real, C3> out);
        }

Real-valued convolution with kernel in the Fourier domain (half-space format):

        namespace vigra {
            template <unsigned int N, class Real, class C1, class C2, class C3>
            void
            convolveFFT(MultiArrayView<N, Real, C1> in,
                        MultiArrayView<N, FFTWComplex<Real>, C2> kernel,
                        MultiArrayView<N, Real, C3> out);
        }

Series of real-valued convolutions with kernels in the spatial or Fourier domain (the kernel and out sequences must have the same length):

        namespace vigra {
            template <unsigned int N, class Real, class C1,
                      class KernelIterator, class OutIterator>
            void
            convolveFFTMany(MultiArrayView<N, Real, C1> in,
                            KernelIterator kernels, KernelIterator kernelsEnd,
                            OutIterator outs);
        }

Complex-valued convolution (parameter `fourierDomainKernel` determines if the kernel is defined in the spatial or Fourier domain):

        namespace vigra {
            template <unsigned int N, class Real, class C1, class C2, class C3>
            void
            convolveFFTComplex(MultiArrayView<N, FFTWComplex<Real>, C1> in,
                               MultiArrayView<N, FFTWComplex<Real>, C2> kernel,
                               MultiArrayView<N, FFTWComplex<Real>, C3> out,
                               bool fourierDomainKernel);
        }

Series of complex-valued convolutions (parameter `fourierDomainKernel` determines if the kernels are defined in the spatial or Fourier domain, the kernel and out sequences must have the same length):

        namespace vigra {
            template <unsigned int N, class Real, class C1,
                      class KernelIterator, class OutIterator>
            void
            convolveFFTComplexMany(MultiArrayView<N, FFTWComplex<Real>, C1> in,
                                   KernelIterator kernels, KernelIterator kernelsEnd,
                                   OutIterator outs,
                                   bool fourierDomainKernel);
        }

Usage:

#include <vigra/multi_fft.hxx>
Namespace: vigra

        // convolve real array with a Gaussian (sigma=1) defined in the spatial domain
        // (implicitly uses padding by at least 4 pixels)
        MultiArray<2, double> src(Shape2(w, h)), dest(Shape2(w,h));

        MultiArray<2, double> spatial_kernel(Shape2(9, 9));
        Gaussian<double> gauss(1.0);

        for(int y=0; y<9; ++y)
            for(int x=0; x<9; ++x)
                spatial_kernel(x, y) = gauss(x-4.0)*gauss(y-4.0);

        convolveFFT(src, spatial_kernel, dest);

        // convolve real array with a Gaussian (sigma=1) defined in the Fourier domain
        // (uses no padding, because the kernel size corresponds to the input size)
        MultiArray<2, FFTWComplex<double> > fourier_kernel(fftwCorrespondingShapeR2C(src.shape()));
        int y0 = h / 2;

        for(int y=0; y<fourier_kernel.shape(1); ++y)
            for(int x=0; x<fourier_kernel.shape(0); ++x)
                fourier_kernel(x, y) = exp(-0.5*sq(x / double(w))) * exp(-0.5*sq((y-y0)/double(h)));

        convolveFFT(src, fourier_kernel, dest);

void vigra::convolveFFTComplex | ( |  | ... | ) |

Convolve a complex-valued array by means of the Fourier transform.

See convolveFFT() for details.

void vigra::convolveFFTMany | ( |  | ... | ) |

Convolve a real-valued array with a sequence of kernels by means of the Fourier transform.

See convolveFFT() for details.

void vigra::convolveFFTComplexMany | ( |  | ... | ) |

Convolve a complex-valued array with a sequence of kernels by means of the Fourier transform.

See convolveFFT() for details.

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python vigra 1.9.0 (Tue Nov 6 2012)