Logo Search packages:      
Sourcecode: gamera version File versions  Download package

vigra::doxygen_overloaded_function ( template<...> void  gradientBasedTransform  ) 

Estimate the optical flow between two images according to a translation model.

Calculate a function of the image gradient.

Apply unary point transformation to each pixel within the ROI (i.e., where the mask is non-zero).

Apply unary point transformation to each pixel.

Create a 3-band TiffImage from the given RGB image.

Create a single-band TiffImage from the given scalar image.

Create a TiffImage from the given iterator range.

Convert RGB (3-band or color-mapped) TiffImage to RGB image.

Convert single-band TiffImage to scalar image.

Convert given TiffImage into image specified by iterator range.

Decompose a symmetric 2x2 tensor into its edge and corner parts.

Calculate the trace of a 2x2 tensor.

Calculate eigen representation of a symmetric 2x2 tensor.

Calculate the tensor (outer) product of a 2D vector with itself.

Find centers of radial symmetry in an image.

Deprecated name of 2-dimensional normalized convolution, i.e. convolution with a mask image.

Performs a 2-dimensional normalized convolution, i.e. convolution with a mask image.

Determine the magnitude transfer function of the camera.

Performs a 1 dimensional convolution in y direction.

Performs a 1 dimensional convolution in x direction.

Performs a 1-dimensional convolution of the source signal using the given kernel.

Three-dimensional Region Segmentation by means of Seeded Region Growing.

Region Segmentation by means of Seeded Region Growing.

Resize image using the Coscot interpolation function.

Resize image using the Catmull/Rom interpolation function.

Resize image using B-spline interpolation.

Resize image using linear interpolation.

Resize image by repeating the nearest pixel values.

Two-fold up-sampling for image pyramid reconstruction.

Two-fold down-sampling for image pyramid construction.

Apply two separable resampling filters successively, the first in x-direction, the second in y-direction.

Apply a resampling filter in the y-direction.

Apply a resampling filter in the x-direction.

Performs a 1-dimensional resampling convolution of the source signal using the given set of kernels.

Recursively calculates the 1 dimensional second derivative in y direction.

Recursively calculates the 1 dimensional second derivative in x direction.

Recursively calculates the 1 dimensional first derivative in y direction.

Recursively calculates the 1 dimensional first derivative in x direction.

Performs 1 dimensional recursive smoothing in y direction.

Performs 1 dimensional recursive filtering (1st and 2nd order) in y direction.

Performs 1 dimensional recursive smoothing in x direction.

Performs 1 dimensional recursive filtering (1st and 2nd order) in x direction.

Performs a 1 dimensional recursive convolution of the source signal.

Convolves the image with a 1-dimensional exponential filter.

Performs a 1-dimensional recursive convolution of the source signal.

Anisotropic tensor smoothing with the hourglass filter.

Perform edge-preserving smoothing at the given scale.

Noise normalization by means of a given linear noise model.

Noise normalization by means of a given quadratic noise model.

Determine the noise variance as a function of the image intensity and cluster the results.

Determine the noise variance as a function of the image intensity.

Resize MultiArray using B-spline interpolation.

Call an analyzing functor at all corresponding elements of two multi-dimensional arrays.

Call an analyzing functor at every element of a multi-dimensional array.

Combine three multi-dimensional arrays into one using a ternary function or functor.

Combine two multi-dimensional arrays into one using a binary function or functor.

Transform a multi-dimensional array with a unary function or functor.

Copy a multi-dimensional array.

Write a value to every pixel in a multi-dimensional array.

Parabolic grayscale dilation on multi-dimensional arrays.

Parabolic grayscale erosion on multi-dimensional arrays.

Binary dilation on multi-dimensional arrays.

Binary erosion on multi-dimensional arrays.

Euclidean distance on multi-dimensional arrays.

Euclidean distance squared on multi-dimensional arrays.

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

Calculate Gaussian gradient of a multi-dimensional arrays.

Isotropic Gaussian smoothing of a multi-dimensional arrays.

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

Separated convolution on multi-dimensional arrays.

Find local maximal regions in an image.

Find local minimal regions in an image.

Find local maxima in an image.

Find local minima in an image.

Transform a labeled image into an edge image.

Transform a labeled image into a crack edge image.

Apply read-only functor to those pixels of both images where the mask image is non-zero.

Apply read-only functor to every pixel of both images.

Apply read-only functor to every pixel in the ROI.

Apply read-only functor to every pixel in the image.

Write value to the specified border pixels in the image.

Write value to pixel in the image if mask is true.

Write the result of a functor call to every pixel in an image or rectangular ROI.

Write a value to every pixel in an image or rectangular ROI.

Write an image, given an vigra::ImageExportInfo object.

Deprecated.

Read the image specified by the given vigra::ImageImportInfo object.

used for reading images of scalar type, such as integer and float grayscale.

used for reading images of vector type, such as integer of float rgb.

Calculate the gradient energy tensor for a scalar valued image.

Create a gabor filter in frequency space.

Apply median filter with disc of given radius to image using a mask.

Apply dilation (maximum) filter with disc of given radius to image using a mask.

Apply erosion (minimum) filter with disc of given radius to image using a mask.

Apply rank order filter with disc structuring function to the image using a mask.

Apply median filter with disc of given radius to image.

Apply dilation (maximum) filter with disc of given radius to image.

Apply erosion (minimum) filter with disc of given radius to image.

Apply rank order filter with disc structuring function to the image.

Real Fourier transforms for even and odd boundary conditions (aka. cosine and sine transforms).

Apply an array of filters (defined in the frequency domain) to an image.

Apply a filter (defined in the frequency domain) to an image.

Compute forward and inverse Fourier transforms.

Rearrange the quadrants of a Fourier image so that the origin is in the image's upper left.

Rearrange the quadrants of a Fourier image so that the origin is in the image center.

Improved implementation of Canny's edge detector.

Detect and mark edges in an edge image using Canny's algorithm.

Simple implementation of Canny's edge detector.

Beautify crack edge image for visualization.

Close one-pixel wide gaps in a cell grid edge image.

Remove short edges from an edge image.

Detect and mark edges in a crack edge image using the Shen/Castan zero-crossing detector.

Detect and mark edges in an edge image using the Shen/Castan zero-crossing detector.

Find corners in an image (4).

Find corners in an image (3).

Find corners in an image (2).

Find corners in an image (1).

Copy source ROI into destination image.

Copy source image into destination image.

Calculate the Structure Tensor for each pixel of and image, using Gaussian (derivative) filters.

Filter image with the 2nd derivatives of the Gaussian at the given scale to get the Hessian matrix.

Filter image with the Laplacian of Gaussian operator at the given scale.

Calculate the gradient magnitude by means of a 1st derivatives of Gaussian filter.

Calculate the gradient vector by means of a 1st derivatives of Gaussian filter.

Perform isotropic Gaussian convolution.

Perform sharpening function with gaussian filter.

Perform simple sharpening function.

Combine three source images into destination image.

Combine ROI of two source images into destination image.

Combine two source images into destination image.

Boundary tensor variant.

Calculate the boundary tensor for a scalar valued image.

Calculate Riesz transforms of the Laplacian of Gaussian.

Resample image by a given factor.

Transpose an image over the major or minor diagonal.

Reflect image horizontally or vertically.

Rotate image by a multiple of 90 degrees.

Warp an image according to an affine transformation.

Rotate image by an arbitrary angle.

Estimate the optical flow between two images according to an affine transform model (e.g. translation, rotation, non-uniform scaling, and shearing).

Estimate the optical flow between two images according to a similarity transform model (e.g. translation, rotation, and uniform scaling).

Sorry, no detailedDocumentation() available yet.

Declarations:

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

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  int SPLINEORDER = 2>
        void
        estimateTranslation(SrcIterator sul, SrcIterator slr, SrcAccessor src,
                            DestIterator dul, DestIterator dlr, DestAccessor dest,
                            Matrix<double> & affineMatrix,
                            AffineMotionEstimationOptions<SPLINEORDER> const & options = 
                                                        AffineMotionEstimationOptions<>())
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  int SPLINEORDER = 2>
        void
        estimateTranslation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                            triple<DestIterator, DestIterator, DestAccessor> dest,
                            Matrix<double> & affineMatrix,
                            AffineMotionEstimationOptions<SPLINEORDER> const & options =
                                                        AffineMotionEstimationOptions<>())
    }

Sorry, no detailedDocumentation() available yet.

Declarations:

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

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  int SPLINEORDER = 2>
        void
        estimateSimilarityTransform(SrcIterator sul, SrcIterator slr, SrcAccessor src,
                            DestIterator dul, DestIterator dlr, DestAccessor dest,
                            Matrix<double> & affineMatrix,
                            AffineMotionEstimationOptions<SPLINEORDER> const & options = 
                                                        AffineMotionEstimationOptions<>())
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  int SPLINEORDER = 2>
        void
        estimateSimilarityTransform(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                            triple<DestIterator, DestIterator, DestAccessor> dest,
                            Matrix<double> & affineMatrix,
                            AffineMotionEstimationOptions<SPLINEORDER> const & options =
                                                        AffineMotionEstimationOptions<>())
    }

Sorry, no detailedDocumentation() available yet.

Declarations:

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

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  int SPLINEORDER = 2>
        void
        estimateAffineTransform(SrcIterator sul, SrcIterator slr, SrcAccessor src,
                            DestIterator dul, DestIterator dlr, DestAccessor dest,
                            Matrix<double> & affineMatrix,
                            AffineMotionEstimationOptions<SPLINEORDER> const & options = 
                                                        AffineMotionEstimationOptions<>())
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  int SPLINEORDER = 2>
        void
        estimateAffineTransform(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                            triple<DestIterator, DestIterator, DestAccessor> dest,
                            Matrix<double> & affineMatrix,
                            AffineMotionEstimationOptions<SPLINEORDER> const & options =
                                                        AffineMotionEstimationOptions<>())
    }

The algorithm performs a rotation about the given center point (the image center by default) using the given SplineImageView for interpolation. The destination image must have the same size as the source SplineImageView. The rotation is counter-clockwise, and the angle must be given in degrees.

Declarations:

pass arguments explicitly:

    namespace vigra {
        // rotate about given center point
        template <int ORDER, class T, 
                  class DestIterator, class DestAccessor>
        void rotateImage(SplineImageView<ORDER, T> const & src,
                         DestIterator id, DestAccessor dest, 
                         double angleInDegree, TinyVector<double, 2> const & center);
                         
        // rotate about image center
        template <int ORDER, class T, 
                  class DestIterator, class DestAccessor>
        void 
        rotateImage(SplineImageView<ORDER, T> const & src,
                    DestIterator id, DestAccessor dest, 
                    double angleInDegree)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        // rotate about given center point
        template <int ORDER, class T, 
                  class DestIterator, class DestAccessor>
        void 
        rotateImage(SplineImageView<ORDER, T> const & src,
                    pair<DestImageIterator, DestAccessor> dest, 
                    double angleInDegree, TinyVector<double, 2> const & center);

        // rotate about image center
        template <int ORDER, class T, 
                  class DestIterator, class DestAccessor>
        void 
        rotateImage(SplineImageView<ORDER, T> const & src,
                    pair<DestImageIterator, DestAccessor> dest, 
                    double angleInDegree);
    }

Usage:

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

    Image src(width, height);
    vigra::SplineImageView<3, Image::value_type> spline(srcImageRange(src));
    
    Image dest(width, height);
    
    vigra::rotateImage(spline, destImage(dest), 38.5);

Required Interface:

    DestImageIterator dest_upperleft;
    
    double x = ..., y = ...;
    
    if (spline.isInside(x,y))
        dest_accessor.set(spline(x, y), dest_upperleft);

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <int ORDER, class T, 
                class DestIterator, class DestAccessor,
                class C>
        void affineWarpImage(SplineImageView<ORDER, T> const & src,
                            DestIterator dul, DestIterator dlr, DestAccessor dest, 
                            MultiArrayView<2, double, C> const & affineMatrix);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <int ORDER, class T, 
                class DestIterator, class DestAccessor,
                class C>
        void affineWarpImage(SplineImageView<ORDER, T> const & src,
                            triple<DestIterator, DestIterator, DestAccessor> dest, 
                            MultiArrayView<2, double, C> const & affineMatrix);
    }

The algorithm applies the given affineMatrix to the destination coordinates and copies the image value from the resulting source coordinates, using the given SplineImageView src for interpolation. If the resulting coordinate is outside the source image, nothing will be writen at that destination point.

        for all dest pixels:
            currentSrcCoordinate = affineMatrix * currentDestCoordinate;
            if src.isInside(currentSrcCoordinate):
                dest[currentDestCoordinate] = src[currentSrcCoordinate]; // copy an interpolated value

The matrix represent a 2-dimensional affine transform by means of homogeneous coordinates, i.e. it must be a 3x3 matrix whose last row is (0,0,1).

Usage:

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

    Image src(width, height);
    vigra::SplineImageView<3, Image::value_type> spline(srcImageRange(src));
    
    Image dest1(width, height);
    
    // equivalent (up to round-off errors) with 
    //     rotateImage(spline, destImage(dest1), 45.0);
    TinyVector<double, 2> center((width-1.0)/2.0, (height-1.0)/2.0);
    affineWarpImage(spline, destImageRange(dest1), rotationMatrix2DDegrees(45.0, center));
    
    Image dest2(2*width-1, 2*height-1);
    
    // equivalent (up to round-off errors) with 
    //     resizeImageSplineInterpolation(srcImageRange(img), destImageRange(dest2));
    // note that scaleFactor = 0.5, because we must pass the transformation from destination to source
    affineWarpImage(spline, destImageRange(dest2), scalingMatrix2D(0.5));

Required Interface:

    DestImageIterator dest_upperleft;
    
    double x = ..., y = ...;
    
    if (spline.isInside(x,y))
        dest_accessor.set(spline(x, y), dest_upperleft);

See also: Functions to specify affine transformation: translationMatrix2D(), scalingMatrix2D(), shearMatrix2D(), rotationMatrix2DRadians(), rotationMatrix2DDegrees()

This algorithm just copies the pixels in the appropriate new order. It expects the destination image to have the correct shape for the desired rotation.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void 
        rotateImage(SrcIterator is, SrcIterator end, SrcAccessor as,
                    DestIterator id, DestAccessor ad, int rotation);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
              class DestImageIterator, class DestAccessor>
        inline void 
        rotateImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
                    pair<DestImageIterator, DestAccessor> dest, int rotation);
    }

Usage:

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

    Image dest(src.height(), src.width()); // note that width and height are exchanged
    
    vigra::rotateImage(srcImageRange(src), destImage(dest), 90);

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator dest_upperleft;
    
    SrcAccessor src_accessor;
    
    dest_accessor.set(src_accessor(src_upperleft), dest_upperleft);

Preconditions:

    src_lowerright.x - src_upperleft.x > 1
    src_lowerright.y - src_upperleft.y > 1

The reflection direction refers to the reflection axis, i.e. horizontal reflection turns the image upside down, vertical reflection changes left for right. The directions are selected by the enum values vigra::horizontal and vigra::vertical. The two directions can also be "or"ed together to perform both reflections simultaneously (see example below) -- this is the same as a 180 degree rotation.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void 
        reflectImage(SrcIterator is, SrcIterator end, SrcAccessor as,
                     DestIterator id, DestAccessor ad, Reflect axis);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
              class DestImageIterator, class DestAccessor>
        inline void 
        reflectImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
                     pair<DestImageIterator, DestAccessor> dest, Reflect axis);
    }

Usage:

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

    Image dest(src.width(), src.height());
    
    vigra::reflectImage(srcImageRange(src), destImage(dest), vigra::horizontal | vigra::vertical);

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator dest_upperleft;
    
    SrcAccessor src_accessor;
    
    dest_accessor.set(src_accessor(src_upperleft), dest_upperleft);

Preconditions:

    src_lowerright.x - src_upperleft.x > 1
    src_lowerright.y - src_upperleft.y > 1

The transposition direction refers to the axis, i.e. major transposition turns the upper right corner into the lower left one, whereas minor transposition changes the upper left corner into the lower right one. The directions are selected by the enum values vigra::major and vigra::minor. The two directions can also be "or"ed together to perform both reflections simultaneously (see example below) -- this is the same as a 180 degree rotation.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void 
        transposeImage(SrcIterator is, SrcIterator end, SrcAccessor as,
                       DestIterator id, DestAccessor ad, Transpose axis);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
              class DestImageIterator, class DestAccessor>
        inline void 
        transposeImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
                       pair<DestImageIterator, DestAccessor> dest, Transpose axis);
    }

Usage:

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

    Image dest(src.width(), src.height());
    
    vigra::transposeImage(srcImageRange(src), destImage(dest), vigra::major | vigra::minor);

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator dest_upperleft;
    
    SrcAccessor src_accessor;
    
    dest_accessor.set(src_accessor(src_upperleft), dest_upperleft);

Preconditions:

    src_lowerright.x - src_upperleft.x > 1
    src_lowerright.y - src_upperleft.y > 1

This algorithm is very fast and does not require any arithmetic on the pixel types. The input image must have a size of at least 2x2. Destiniation pixels are directly copied from the appropriate source pixels. The size of the result image is the product of factor and the original size, where we round up if factor < 1.0 and down otherwise. This size calculation is the main difference to the convention used in the similar function resizeImageNoInterpolation(): there, the result size is calculated as n*(old_width-1)+1 and n*(old_height-1)+1. This is because resizeImageNoInterpolation() does not replicate the last pixel in every row/column in order to make it compatible with the other functions of the resizeImage... family.

The function can be called with different resampling factors for x and y, or with a single factor to be used for both directions.

It should also be noted that resampleImage() is implemented so that an enlargement followed by the corresponding shrinking reproduces the original image. The function uses accessors.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void 
        resampleImage(SrcIterator is, SrcIterator iend, SrcAccessor sa,
                      DestIterator id, DestAccessor ad, double factor);
                      
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void 
        resampleImage(SrcIterator is, SrcIterator iend, SrcAccessor sa,
                      DestIterator id, DestAccessor ad, double xfactor, double yfactor);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
              class DestImageIterator, class DestAccessor>
        inline void 
        resampleImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
                      pair<DestImageIterator, DestAccessor> dest, double factor);
                      
        template <class SrcImageIterator, class SrcAccessor,
              class DestImageIterator, class DestAccessor>
        inline void 
        resampleImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
                      pair<DestImageIterator, DestAccessor> dest, double xfactor, double yfactor);
    }

Usage:

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

    double factor = 2.0;
    Image dest((int)(factor*src.width()), (int)(factor*src.height()));
    
    vigra::resampleImage(srcImageRange(src), destImage(dest), factor);

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator dest_upperleft;
    
    SrcAccessor src_accessor;
    
    dest_accessor.set(src_accessor(src_upperleft), dest_upperleft);

Preconditions:

    src_lowerright.x - src_upperleft.x > 1
    src_lowerright.y - src_upperleft.y > 1

The Riesz transforms of the Laplacian of Gaussian have the following transfer functions (defined in a polar coordinate representation of the frequency domain):

\[ F_{\sigma}(r, \phi)=(i \cos \phi)^n (i \sin \phi)^m r^2 e^{-r^2 \sigma^2 / 2} \]

where n = xorder and m = yorder determine th e order of the transform, and sigma > 0 is the scale of the Laplacian of Gaussian. This function computes a good spatial domain approximation of these transforms for xorder + yorder <= 2. The filter responses may be used to calculate the monogenic signal or the boundary tensor.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                class DestIterator, class DestAccessor>
        void rieszTransformOfLOG(SrcIterator supperleft, SrcIterator slowerright, SrcAccessor src,
                                 DestIterator dupperleft, DestAccessor dest,
                                 double scale, unsigned int xorder, unsigned int yorder);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                class DestIterator, class DestAccessor>
        void rieszTransformOfLOG(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                                 pair<DestIterator, DestAccessor> dest,
                                 double scale, unsigned int xorder, unsigned int yorder);
    }

Usage:

#include <vigra/boundarytensor.hxx>

    FImage impulse(17,17), res(17, 17);
    impulse(8,8) = 1.0;

    // calculate the impulse response of the first order Riesz transform in x-direction
    rieszTransformOfLOG(srcImageRange(impulse), destImage(res), 2.0, 1, 0);

These functions calculate a spatial domain approximation of the boundary tensor as described in

U. Köthe: "Integrated Edge and Junction Detection with the Boundary Tensor", in: ICCV 03, Proc. of 9th Intl. Conf. on Computer Vision, Nice 2003, vol. 1, pp. 424-431, Los Alamitos: IEEE Computer Society, 2003

with the Laplacian of Gaussian as the underlying bandpass filter (see rieszTransformOfLOG()). The output image must have 3 bands which will hold the tensor components in the order t11, t12 (== t21), t22. The function boundaryTensor1() with the same interface implements a variant of the boundary tensor where the 0th-order Riesz transform has been dropped, so that the tensor is no longer sensitive to blobs.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void boundaryTensor(SrcIterator supperleft, SrcIterator slowerright, SrcAccessor src,
                            DestIterator dupperleft, DestAccessor dest,
                            double scale);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void boundaryTensor(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                            pair<DestIterator, DestAccessor> dest,
                            double scale);
    }

Usage:

#include <vigra/boundarytensor.hxx>

    FImage img(w,h);
    FVector3Image bt(w,h);
    ...
    boundaryTensor(srcImageRange(img), destImage(bt), 2.0);

This function implements a variant of the boundary tensor where the 0th-order Riesz transform has been dropped, so that the tensor is no longer sensitive to blobs. See boundaryTensor() for more detailed documentation.

Declarations:

#include <vigra/boundarytensor.hxx>

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void boundaryTensor1(SrcIterator supperleft, SrcIterator slowerright, SrcAccessor src,
                             DestIterator dupperleft, DestAccessor dest,
                             double scale);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void boundaryTensor1(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                             pair<DestIterator, DestAccessor> dest,
                             double scale);
    }

The transformation given by the functor is applied to the source pixels and the result written into the corresponding destination pixel. This is typically used for operations like add and subtract. The function uses accessors to access the pixel data. Note that the binary functors of the STL can be used in addition to the functors specifically defined in Functors to Combine Images. Creation of new functors is easiest by using Functor Expressions.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator1, class SrcAccessor1,
              class SrcImageIterator2, class SrcAccessor2,
              class DestImageIterator, class DestAccessor,
              class Functor>
        void
        combineTwoImages(SrcImageIterator1 src1_upperleft, 
                 SrcImageIterator1 src1_lowerright, SrcAccessor1 sa1,
                 SrcImageIterator2 src2_upperleft, SrcAccessor2 sa2,
                 DestImageIterator dest_upperleft, DestAccessor da,
                 Functor const & f)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator1, class SrcAccessor1,
              class SrcImageIterator2, class SrcAccessor2,
              class DestImageIterator, class DestAccessor,
              class Functor>
        void
        combineTwoImages(triple<SrcImageIterator1, SrcImageIterator1, SrcAccessor1> src1,
                 pair<SrcImageIterator2, SrcAccessor2> src2,
                 pair<DestImageIterator, DestAccessor> dest,
                 Functor const & f)
    }

Usage:

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

    #include <functional>     // for plus

    vigra::combineTwoImages(
                srcIterRange(src1.upperLeft(), src1.lowerRight()), 
                srcIter(src2.upperLeft()), 
                destIter(dest.upperLeft()),  
                std::plus<SrcValueType>());

Note that SrcValueType must be replaced with the appropriate type (e.g. the promote type of the input images' pixel type, see also Numeric and Promotion Traits)

Required Interface:

    SrcImageIterator1 src1_upperleft, src1_lowerright;
    SrcImageIterator2 src2_upperleft;
    DestImageIterator dest_upperleft;
    SrcImageIterator1::row_iterator sx1 = src1_upperleft.rowIterator();
    SrcImageIterator2::row_iterator sx2 = src2_upperleft.rowIterator();
    DestImageIterator::row_iterator dx = dest_upperleft.rowIterator();
    
    SrcAccessor1 src1_accessor;
    SrcAccessor2 src2_accessor;
    DestAccessor dest_accessor;
    
    Functor functor;

    dest_accessor.set(
          functor(src1_accessor(sx1), src2_accessor(sx2)), 
          dx);

The transformation given by the functor is applied to all source pixels in the ROI (i.e. whenever the return value of the mask's accessor is not zero) and the result written into the corresponding destination pixel. This is typically used for operations like add and subtract. The function uses accessors to access the pixel data. Note that the binary functors of the STL can be used in addition to the functors specifically defined in Functors to Combine Images. Creation of new functors is easiest by using Functor Expressions.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator1, class SrcAccessor1,
              class SrcImageIterator2, class SrcAccessor2,
              class MaskImageIterator, class MaskAccessor,
              class DestImageIterator, clas DestAccessor,
              class Functor>
        void
        combineTwoImagesIf(SrcImageIterator1 src1_upperleft, 
                   SrcImageIterator1 src1_lowerright, SrcAccessor1 sa1,
                   SrcImageIterator2 src2_upperleft, SrcAccessor2 sa2,
                   MaskImageIterator mask_upperleft, MaskAccessor ma,
                   DestImageIterator dest_upperleft, DestAccessor da,
                   Functor const & f)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator1, class SrcAccessor1,
              class SrcImageIterator2, class SrcAccessor2,
              class MaskImageIterator, class MaskAccessor,
              class DestImageIterator, clas DestAccessor,
              class Functor>
        void
        combineTwoImagesIf(triple<SrcImageIterator1, SrcImageIterator1, SrcAccessor1> src1,
                   pair<SrcImageIterator2, SrcAccessor2> src2,
                   pair<MaskImageIterator, MaskAccessor> mask,
                   pair<DestImageIterator, DestAccessor> dest,
                   Functor const & f)
    }

Usage:

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

    #include <functional>     // for plus

    vigra::combineTwoImagesIf(
                srcIterRange(src1.upperLeft(), src1.lowerRight()), 
                srcIter(src2.upperLeft()), 
                maskIter(mask.upperLeft()), 
                destIter(dest.upperLeft()),
                std::plus<SrcValueType>());

Note that SrcValueType must be replaced with the appropriate type (e.g. the promote type of the input images' pixel type, see also Numeric and Promotion Traits)

Required Interface:

    SrcImageIterator1 src1_upperleft, src1_lowerright;
    SrcImageIterator2 src2_upperleft;
    MaskImageIterator mask_upperleft;
    DestImageIterator dest_upperleft;
    SrcImageIterator1::row_iterator sx1 = src1_upperleft.rowIterator();
    SrcImageIterator2::row_iterator sx2 = src2_upperleft.rowIterator();
    MaskImageIterator::row_iterator mx = mask_upperleft.rowIterator();
    DestImageIterator::row_iterator dx = dest_upperleft.rowIterator();
    
    
    SrcAccessor1 src1_accessor;
    SrcAccessor2 src2_accessor;
    MaskAccessor mask_accessor;
    DestAccessor dest_accessor;
    
    Functor functor;
    
    if(mask_accessor(mx))
       dest_accessor.set(
          functor(src1_accessor(sx1), src2_accessor(sx2)), 
          dx);

The transformation given by the functor is applied to the source pixels and the result written into the corresponding destination pixel. The function uses accessors to access the pixel data. Creation of new functors is easiest by using Functor Expressions.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator1, class SrcAccessor1,
              class SrcImageIterator2, class SrcAccessor2,
              class SrcImageIterator3, class SrcAccessor3,
              class DestImageIterator, class DestAccessor,
              class Functor>
        void
        combineThreeImages(SrcImageIterator1 src1_upperleft, 
                   SrcImageIterator1 src1_lowerright, SrcAccessor1 sa1,
                   SrcImageIterator2 src2_upperleft, SrcAccessor2 sa2,
                   SrcImageIterator3 src2_upperleft, SrcAccessor3 sa3,
                   DestImageIterator dest_upperleft, DestAccessor da,
                   Functor const & f)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator1, class SrcAccessor1,
              class SrcImageIterator2, class SrcAccessor2,
              class SrcImageIterator3, class SrcAccessor3,
              class DestImageIterator, class DestAccessor,
              class Functor>
        void
        combineThreeImages(triple<SrcImageIterator1, SrcImageIterator1, SrcAccessor1> src1,
                 pair<SrcImageIterator2, SrcAccessor2> src2,
                 pair<SrcImageIterator3, SrcAccessor3> src3,
                 pair<DestImageIterator, DestAccessor> dest,
                 Functor const & f)
    }

Usage:

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

    vigra::combineThreeImages(
                srcIterRange(src1.upperLeft(), src1.lowerRight()), 
                srcIter(src2.upperLeft()), 
                srcIter(src3.upperLeft()), 
                destIter(dest.upperLeft()),  
                SomeThreeArgumentFunctor());

Required Interface:

    SrcImageIterator1 src1_upperleft, src1_lowerright;
    SrcImageIterator2 src2_upperleft;
    SrcImageIterator3 src3_upperleft;
    DestImageIterator dest_upperleft;
    SrcImageIterator1::row_iterator sx1 = src1_upperleft.rowIterator();
    SrcImageIterator2::row_iterator sx2 = src2_upperleft.rowIterator();
    SrcImageIterator3::row_iterator sx3 = src3_upperleft.rowIterator();
    DestImageIterator::row_iterator dx = dest_upperleft.rowIterator();
    
    SrcAccessor1 src1_accessor;
    SrcAccessor2 src2_accessor;
    SrcAccessor3 src3_accessor;
    DestAccessor dest_accessor;
    
    Functor functor;

    dest_accessor.set(
          functor(src1_accessor(sx1), 
                  src2_accessor(sx2), 
                  src3_accessor(sx3)), 
          dx);

This function use convolveImage() with following filter:

    -sharpening_factor/16.0,    -sharpening_factor/8.0,    -sharpening_factor/16.0,
    -sharpening_factor/8.0,   1.0+sharpening_factor*0.75,  -sharpening_factor/8.0,
    -sharpening_factor/16.0,    -sharpening_factor/8.0,    -sharpening_factor/16.0;    

and use BORDER_TREATMENT_REFLECT as border treatment mode.

Preconditions:

    1. sharpening_factor >= 0
    2. scale >= 0

Declarations:

Declarations:

pass arguments explicitly:

    namespace vigra {
      template <class SrcIterator, class SrcAccessor,
                class DestIterator, class DestAccessor>
      void simpleSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc,
                            DestIterator dest_ul, DestAccessor dest_acc, double sharpening_factor)

    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
      template <class SrcIterator, class SrcAccessor, 
                class DestIterator, class DestAccessor>
      inline
      void simpleSharpening(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                                    pair<DestIterator, DestAccessor> dest, double sharpening_factor)
      {
          simpleSharpening(src.first, src.second, src.third,
                             dest.first, dest.second, sharpening_factor);
      }

    }

Usage:

#include <vigra/convolution.hxx>

    vigra::FImage src(w,h), dest(w,h);
    ...

    // sharpening with sharpening_factor = 0.1
    vigra::simpleSharpening(srcImageRange(src), destImage(dest), 0.1);

This function use the gaussianSmoothing() at first and scale the source image (

 src 
) with the
 scale 
factor in an temporary image (
 tmp 
). At second the new pixel in the destination image will be with following formel calculate:
    dest = (1 + sharpening_factor)*src - sharpening_factor*tmp

Preconditions:

    1. sharpening_factor >= 0
    2. scale >= 0

Declarations:

pass arguments explicitly:

    namespace vigra {
      template <class SrcIterator, class SrcAccessor,
                class DestIterator, class DestAccessor>
      void gaussianSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc,
                                DestIterator dest_ul, DestAccessor dest_acc, double sharpening_factor, 
                              double scale)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
      template <class SrcIterator, class SrcAccessor,
                class DestIterator, class DestAccessor>
      void gaussianSharpening(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                               pair<DestIterator, DestAccessor> dest, double sharpening_factor, 
                              double scale)
    }

Usage:

#include <vigra/convolution.hxx>

    vigra::FImage src(w,h), dest(w,h);
    ...

    // sharpening with sharpening_factor = 3.0
    // smoothing with scale = 0.5
    vigra::gaussianSmoothing(srcImageRange(src), destImage(dest), 3.0, 0.5);

This function is a shorthand for the concatenation of a call to separableConvolveX() and separableConvolveY() with a Gaussian kernel of the given scale. The function uses BORDER_TREATMENT_REFLECT.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void gaussianSmoothing(SrcIterator supperleft,
                                SrcIterator slowerright, SrcAccessor sa,
                                DestIterator dupperleft, DestAccessor da,
                                double scale);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        inline void
        gaussianSmoothing(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                          pair<DestIterator, DestAccessor> dest,
                          double scale);
    }

Usage:

#include <vigra/convolution.hxx>

    vigra::FImage src(w,h), dest(w,h);
    ...

    // smooth with scale = 3.0
    vigra::gaussianSmoothing(srcImageRange(src), destImage(dest), 3.0);

This function is a shorthand for the concatenation of a call to separableConvolveX() and separableConvolveY() with the appropriate kernels at the given scale. Note that this function can either produce two separate result images for the x- and y-components of the gradient, or write into a vector valued image (with at least two components).

Declarations:

pass arguments explicitly:

    namespace vigra {
        // write x and y component of the gradient into separate images
        template <class SrcIterator, class SrcAccessor,
                  class DestIteratorX, class DestAccessorX,
                  class DestIteratorY, class DestAccessorY>
        void gaussianGradient(SrcIterator supperleft,
                              SrcIterator slowerright, SrcAccessor sa,
                              DestIteratorX dupperleftx, DestAccessorX dax,
                              DestIteratorY dupperlefty, DestAccessorY day,
                              double scale);

        // write x and y component of the gradient into a vector-valued image
        template <class SrcIterator, class SrcAccessor,
                 class DestIterator, class DestAccessor>
        void gaussianGradient(SrcIterator supperleft,
                              SrcIterator slowerright, SrcAccessor src,
                              DestIterator dupperleft, DestAccessor dest,
                              double scale);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        // write x and y component of the gradient into separate images
        template <class SrcIterator, class SrcAccessor,
                  class DestIteratorX, class DestAccessorX,
                  class DestIteratorY, class DestAccessorY>
        void
        gaussianGradient(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                         pair<DestIteratorX, DestAccessorX> destx,
                         pair<DestIteratorY, DestAccessorY> desty,
                         double scale);

        // write x and y component of the gradient into a vector-valued image
        template <class SrcIterator, class SrcAccessor,
                 class DestIterator, class DestAccessor>
        void
        gaussianGradient(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                         pair<DestIterator, DestAccessor> dest,
                         double scale);
    }

Usage:

#include <vigra/convolution.hxx>

    vigra::FImage src(w,h), gradx(w,h), grady(w,h);
    ...

    // calculate gradient vector at scale = 3.0
    vigra::gaussianGradient(srcImageRange(src),
                             destImage(gradx), destImage(grady), 3.0);

This function calls gaussianGradient() and returns the pixel-wise magnitude of the resulting gradient vectors. If the original image has multiple bands, the squared gradient magnitude is computed for each band separately, and the return value is the square root of the sum of these sqaured magnitudes.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void gaussianGradientMagnitude(SrcIterator sul,
                                       SrcIterator slr, SrcAccessor src,
                                       DestIterator dupperleft, DestAccessor dest,
                                       double scale);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        gaussianGradientMagnitude(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                                  pair<DestIterator, DestAccessor> dest,
                                  double scale);
    }

Usage:

#include <vigra/convolution.hxx>

    vigra::FImage src(w,h), grad(w,h);
    ...

    // calculate gradient magnitude at scale = 3.0
    vigra::gaussianGradientMagnitude(srcImageRange(src), destImage(grad), 3.0);

This function calls separableConvolveX() and separableConvolveY() with the appropriate 2nd derivative of Gaussian kernels in x- and y-direction and then sums the results to get the Laplacian.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void laplacianOfGaussian(SrcIterator supperleft,
                                SrcIterator slowerright, SrcAccessor sa,
                                DestIterator dupperleft, DestAccessor da,
                                double scale);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        inline void
        laplacianOfGaussian(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                          pair<DestIterator, DestAccessor> dest,
                          double scale);
    }

Usage:

#include <vigra/convolution.hxx>

    vigra::FImage src(w,h), dest(w,h);
    ...

    // calculate Laplacian of Gaussian at scale = 3.0
    vigra::laplacianOfGaussian(srcImageRange(src), destImage(dest), 3.0);

The Hessian matrix is a symmetric matrix defined as:

\[ \mbox{\rm Hessian}(I) = \left( \begin{array}{cc} G_{xx} \ast I & G_{xy} \ast I \\ G_{xy} \ast I & G_{yy} \ast I \end{array} \right) \]

where $G_{xx}, G_{xy}, G_{yy}$ denote 2nd derivatives of Gaussians at the given scale, and $\ast$ is the convolution symbol. This function calls separableConvolveX() and separableConvolveY() with the appropriate 2nd derivative of Gaussian kernels and puts the results in the three destination images. The first destination image will contain the second derivative in x-direction, the second one the mixed derivative, and the third one holds the derivative in y-direction.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIteratorX, class DestAccessorX,
                  class DestIteratorXY, class DestAccessorXY,
                  class DestIteratorY, class DestAccessorY>
        void hessianMatrixOfGaussian(SrcIterator supperleft,
                                SrcIterator slowerright, SrcAccessor sa,
                                DestIteratorX dupperleftx, DestAccessorX dax,
                                DestIteratorXY dupperleftxy, DestAccessorXY daxy,
                                DestIteratorY dupperlefty, DestAccessorY day,
                                double scale);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIteratorX, class DestAccessorX,
                  class DestIteratorXY, class DestAccessorXY,
                  class DestIteratorY, class DestAccessorY>
        inline void
        hessianMatrixOfGaussian(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                          pair<DestIteratorX, DestAccessorX> destx,
                          pair<DestIteratorXY, DestAccessorXY> destxy,
                          pair<DestIteratorY, DestAccessorY> desty,
                          double scale);
    }

Usage:

#include <vigra/convolution.hxx>

    vigra::FImage src(w,h), hxx(w,h), hxy(w,h), hyy(w,h);
    ...

    // calculate Hessian of Gaussian at scale = 3.0
    vigra::hessianMatrixOfGaussian(srcImageRange(src),
        destImage(hxx), destImage(hxy), destImage(hyy), 3.0);

The Structure Tensor is is a smoothed version of the Euclidean product of the gradient vector with itself. I.e. it's a symmetric matrix defined as:

\[ \mbox{\rm StructurTensor}(I) = \left( \begin{array}{cc} G \ast (I_x I_x) & G \ast (I_x I_y) \\ G \ast (I_x I_y) & G \ast (I_y I_y) \end{array} \right) = \left( \begin{array}{cc} A & C \\ C & B \end{array} \right) \]

where $G$ denotes Gaussian smoothing at the outer scale, $I_x, I_y$ are the gradient components taken at the inner scale, $\ast$ is the convolution symbol, and $I_x I_x$ etc. are pixelwise products of the 1st derivative images. This function calls separableConvolveX() and separableConvolveY() with the appropriate Gaussian kernels and puts the results in the three separate destination images (where the first one will contain $G \ast (I_x I_x)$, the second one $G \ast (I_x I_y)$, and the third one holds $G \ast (I_y I_y)$), or into a single 3-band image (where the bands hold the result in the same order as above). The latter form is also applicable when the source image is a multi-band image (e.g. RGB). In this case, tensors are first computed for each band separately, and then summed up to get a single result tensor.

Declarations:

pass arguments explicitly:

    namespace vigra {
        // create three separate destination images
        template <class SrcIterator, class SrcAccessor,
                  class DestIteratorX, class DestAccessorX,
                  class DestIteratorXY, class DestAccessorXY,
                  class DestIteratorY, class DestAccessorY>
        void structureTensor(SrcIterator supperleft,
                                SrcIterator slowerright, SrcAccessor sa,
                                DestIteratorX dupperleftx, DestAccessorX dax,
                                DestIteratorXY dupperleftxy, DestAccessorXY daxy,
                                DestIteratorY dupperlefty, DestAccessorY day,
                                double inner_scale, double outer_scale);

        // create a single 3-band destination image
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void structureTensor(SrcIterator supperleft,
                                SrcIterator slowerright, SrcAccessor sa,
                                DestIterator dupperleft, DestAccessor da,
                                double inner_scale, double outer_scale);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        // create three separate destination images
        template <class SrcIterator, class SrcAccessor,
                  class DestIteratorX, class DestAccessorX,
                  class DestIteratorXY, class DestAccessorXY,
                  class DestIteratorY, class DestAccessorY>
        void
        structureTensor(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                          pair<DestIteratorX, DestAccessorX> destx,
                          pair<DestIteratorXY, DestAccessorXY> destxy,
                          pair<DestIteratorY, DestAccessorY> desty,
                          double nner_scale, double outer_scale);

        // create a single 3-band destination image
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        structureTensor(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                          pair<DestIterator, DestAccessor> dest,
                          double nner_scale, double outer_scale);
    }

Usage:

#include <vigra/convolution.hxx>

    vigra::FImage src(w,h), stxx(w,h), stxy(w,h), styy(w,h);
    vigra::BasicImage<TinyVector<float, 3> > st(w,h);
    ...

    // calculate Structure Tensor at inner scale = 1.0 and outer scale = 3.0
    vigra::structureTensor(srcImageRange(src),
        destImage(stxx), destImage(stxy), destImage(styy), 1.0, 3.0);

    // dto. with a single 3-band destination image
    vigra::structureTensor(srcImageRange(src), destImage(st), 1.0, 3.0);

If necessary, type conversion takes place. The function uses accessors to access the pixel data.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
              class DestImageIterator, class DestAccessor>
        void
        copyImage(SrcImageIterator src_upperleft, 
              SrcImageIterator src_lowerright, SrcAccessor sa,
              DestImageIterator dest_upperleft, DestAccessor da)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
              class DestImageIterator, class DestAccessor>
        void
        copyImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
              pair<DestImageIterator, DestAccessor> dest)
    }

Usage:

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

    vigra::copyImage(srcImageRange(src), destImage(dest));

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator      dest_upperleft;
    SrcImageIterator::row_iterator sx = src_upperleft.rowIterator();
    DestImageIterator::row_iterator dx = dest_upperleft.rowIterator();
    
    SrcAccessor src_accessor;
    DestAccessor dest_accessor;

    dest_accessor.set(src_accessor(sx), dx);

Pixel values are copied whenever the return value of the mask's accessor is not zero. If necessary, type conversion takes place. The function uses accessors to access the pixel data.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
              class MaskImageIterator, class MaskAccessor,
              class DestImageIterator, clas DestAccessor>
        void
        copyImageIf(SrcImageIterator src_upperleft, 
            SrcImageIterator src_lowerright, SrcAccessor sa,
            MaskImageIterator mask_upperleft, MaskAccessor ma,
            DestImageIterator dest_upperleft, DestAccessor da)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
              class MaskImageIterator, class MaskAccessor,
              class DestImageIterator, clas DestAccessor>
        void
        copyImageIf(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
            pair<MaskImageIterator, MaskAccessor> mask,
            pair<DestImageIterator, DestAccessor> dest)
    }

Usage:

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

    vigra::copyImageIf(srcImageRange(src), maskImage(mask), destImage(dest));

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator dest_upperleft;
    MaskImageIterator mask_upperleft;
    SrcImageIterator::row_iterator sx = src_upperleft.rowIterator();
    MaskImageIterator::row_iterator mx = mask_upperleft.rowIterator();
    DestImageIterator::row_iterator dx = dest_upperleft.rowIterator();
    
    SrcAccessor src_accessor;
    DestAccessor dest_accessor;
    MaskAccessor mask_accessor;
    Functor functor;
    
    if(mask_accessor(mx))
        dest_accessor.set(src_accessor(sx), dx);

This algorithm implements the so called 'corner response function' to measure the 'cornerness' of each pixel in the image, according to [C.G. Harris and M.J. Stevens: "A Combined Corner and Edge Detector", Proc. of 4th Alvey Vision Conference, 1988]. Several studies have found this to be a very robust corner detector, although it moves the corners somewhat into one region, depending on the scale.

The algorithm first determines the structure tensor at each pixel by calling structureTensor(). Then the entries of the structure tensor are combined as

\[ \mbox{\rm CornerResponse} = \mbox{\rm det(StructureTensor)} - 0.04 \mbox{\rm tr(StructureTensor)}^2 = A B - C^2 - 0.04 (A + B)^2 \]

The local maxima of the corner response denote the corners in the gray level image.

The source value type must be a linaer algebra, i.e. addition, subtraction, and multiplication with itself, multiplication with doubles and NumericTraits must be defined.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        cornerResponseFunction(SrcIterator sul, SrcIterator slr, SrcAccessor as,
                               DestIterator dul, DestAccessor ad,
                               double scale)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        inline 
        void cornerResponseFunction(
                   triple<SrcIterator, SrcIterator, SrcAccessor> src,
                   pair<DestIterator, DestAccessor> dest,
                   double scale)
    }

Usage:

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

    vigra::BImage src(w,h), corners(w,h);
    vigra::FImage corner_response(w,h);
    
    // empty corner image
    corners.init(0.0);
    ...
    
    // find corner response at scale 1.0
    vigra::cornerResponseFunction(srcImageRange(src), destImage(corner_response), 
                           1.0);
    
    // find local maxima of corner response, mark with 1
    vigra::localMaxima(srcImageRange(corner_response), destImage(corners));
    
    // threshold corner response to keep only strong corners (above 400.0)
    transformImage(srcImageRange(corner_response), destImage(corner_response),
          vigra::Threshold<double, double>(
               400.0, std::numeric_limits<double>::max(), 0.0, 1.0)); 

    // combine thresholding and local maxima
    vigra::combineTwoImages(srcImageRange(corners), srcImage(corner_response),
                     destImage(corners), std::multiplies<float>());

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator dest_upperleft;
    
    SrcAccessor src_accessor;
    DestAccessor dest_accessor;
    
    SrcAccessor::value_type u = src_accessor(src_upperleft);
    double d;
    
    u = u + u
    u = u - u
    u = u * u
    u = d * u
    
    dest_accessor.set(u, dest_upperleft);

This algorithm implements the so called 'Foerstner Corner Detector' to measure the 'cornerness' of each pixel in the image, according to [W. Förstner: "A feature based correspondence algorithms for image matching", Intl. Arch. Photogrammetry and Remote Sensing, vol. 24, pp 160-166, 1986]. It is also known as the "Plessey Detector" by Harris. However, it should not be confused with the "\link cornerResponseFunction Corner Response Function\endlink ", another detector invented by Harris.

The algorithm first determines the structure tensor at each pixel by calling structureTensor(). Then the entries of the structure tensor are combined as

\[ \mbox{\rm FoerstnerCornerStrength} = \frac{\mbox{\rm det(StructureTensor)}}{\mbox{\rm tr(StructureTensor)}} = \frac{A B - C^2}{A + B} \]

The local maxima of the corner strength denote the corners in the gray level image. Its performance is similar to the cornerResponseFunction().

The source value type must be a division algebra, i.e. addition, subtraction, multiplication, and division with itself, multiplication with doubles and NumericTraits must be defined.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        foerstnerCornerDetector(SrcIterator sul, SrcIterator slr, SrcAccessor as,
                               DestIterator dul, DestAccessor ad,
                               double scale)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        inline 
        void foerstnerCornerDetector(
                   triple<SrcIterator, SrcIterator, SrcAccessor> src,
                   pair<DestIterator, DestAccessor> dest,
                   double scale)
    }

Usage:

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

    vigra::BImage src(w,h), corners(w,h);
    vigra::FImage foerstner_corner_strength(w,h);
    
    // empty corner image
    corners.init(0.0);
    ...
    
    // find corner response at scale 1.0
    vigra::foerstnerCornerDetector(srcImageRange(src), destImage(foerstner_corner_strength), 
                                   1.0);
    
    // find local maxima of corner response, mark with 1
    vigra::localMaxima(srcImageRange(foerstner_corner_strength), destImage(corners));

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator dest_upperleft;
    
    SrcAccessor src_accessor;
    DestAccessor dest_accessor;
    
    SrcAccessor::value_type u = src_accessor(src_upperleft);
    double d;
    
    u = u + u
    u = u - u
    u = u * u
    u = u / u
    u = d * u
    
    dest_accessor.set(u, dest_upperleft);

This algorithm implements yet another structure tensor-based corner detector, according to [K. Rohr: "Untersuchung von grauwertabhängigen Transformationen zur Ermittlung der optischen Flusses in Bildfolgen", Diploma thesis, Inst. für Nachrichtensysteme, Univ. Karlsruhe, 1987, see also K. Rohr: "Modelling and Identification of Characteristic Intensity Variations", Image and Vision Computing 10:2 (1992) 66-76 and K. Rohr: "Localization Properties of Direct Corner Detectors", J. of Mathematical Imaging and Vision 4:2 (1994) 139-150].

The algorithm first determines the structure tensor at each pixel by calling structureTensor(). Then the entries of the structure tensor are combined as

\[ \mbox{\rm RohrCornerStrength} = \mbox{\rm det(StructureTensor)} = A B - C^2 \]

The local maxima of the corner strength denote the corners in the gray level image. Its performance is similar to the cornerResponseFunction().

The source value type must be a linear algebra, i.e. addition, subtraction, and multiplication with itself, multiplication with doubles and NumericTraits must be defined.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        rohrCornerDetector(SrcIterator sul, SrcIterator slr, SrcAccessor as,
                           DestIterator dul, DestAccessor ad,
                           double scale)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        inline 
        void rohrCornerDetector(
                   triple<SrcIterator, SrcIterator, SrcAccessor> src,
                   pair<DestIterator, DestAccessor> dest,
                   double scale)
    }

Usage:

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

    vigra::BImage src(w,h), corners(w,h);
    vigra::FImage rohr_corner_strength(w,h);
    
    // empty corner image
    corners.init(0.0);
    ...
    
    // find corner response at scale 1.0
    vigra::rohrCornerDetector(srcImageRange(src), destImage(rohr_corner_strength), 
                              1.0);
    
    // find local maxima of corner response, mark with 1
    vigra::localMaxima(srcImageRange(rohr_corner_strength), destImage(corners));

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator dest_upperleft;
    
    SrcAccessor src_accessor;
    DestAccessor dest_accessor;
    
    SrcAccessor::value_type u = src_accessor(src_upperleft);
    double d;
    
    u = u + u
    u = u - u
    u = u * u
    u = d * u
    
    dest_accessor.set(u, dest_upperleft);

This algorithm implements a corner detector according to [P.R. Beaudet: "Rotationally Invariant Image Operators", Proc. Intl. Joint Conf. on Pattern Recognition, Kyoto, Japan, 1978, pp. 579-583].

The algorithm calculates the corner strength as the negative determinant of the Hessian Matrix. The local maxima of the corner strength denote the corners in the gray level image.

The source value type must be a linear algebra, i.e. addition, subtraction, and multiplication with itself, multiplication with doubles and NumericTraits must be defined.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        beaudetCornerDetector(SrcIterator sul, SrcIterator slr, SrcAccessor as,
                           DestIterator dul, DestAccessor ad,
                           double scale)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        inline 
        void beaudetCornerDetector(
                   triple<SrcIterator, SrcIterator, SrcAccessor> src,
                   pair<DestIterator, DestAccessor> dest,
                   double scale)
    }

Usage:

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

    vigra::BImage src(w,h), corners(w,h);
    vigra::FImage beaudet_corner_strength(w,h);
    
    // empty corner image
    corners.init(0.0);
    ...
    
    // find corner response at scale 1.0
    vigra::beaudetCornerDetector(srcImageRange(src), destImage(beaudet_corner_strength), 
                              1.0);
    
    // find local maxima of corner response, mark with 1
    vigra::localMaxima(srcImageRange(beaudet_corner_strength), destImage(corners));

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator dest_upperleft;
    
    SrcAccessor src_accessor;
    DestAccessor dest_accessor;
    
    SrcAccessor::value_type u = src_accessor(src_upperleft);
    double d;
    
    u = u + u
    u = u - u
    u = u * u
    u = d * u
    
    dest_accessor.set(u, dest_upperleft);

For all background pixels, calculate the distance to the nearest object or contour. The label of the pixels to be considered background in the source image is passed in the parameter 'background'. Source pixels with other labels will be considered objects. In the destination image, all pixels corresponding to background will be assigned the their distance value, all pixels corresponding to objects will be assigned 0.

The parameter 'norm' gives the distance norm to be used:

  • norm == 0: use chessboard distance (L-infinity norm)
  • norm == 1: use Manhattan distance (L1 norm)
  • norm == 2: use Euclidean distance (L2 norm)

If you use the L2 norm, the destination pixels must be real valued to give correct results.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
                           class DestImageIterator, class DestAccessor,
                           class ValueType>
        void distanceTransform(SrcImageIterator src_upperleft, 
                        SrcImageIterator src_lowerright, SrcAccessor sa,
                        DestImageIterator dest_upperleft, DestAccessor da,
                        ValueType background, int norm)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
                           class DestImageIterator, class DestAccessor,
                           class ValueType>
        void distanceTransform(
            triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
            pair<DestImageIterator, DestAccessor> dest,
            ValueType background, int norm)
    }

Usage:

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

    vigra::BImage src(w,h), edges(w,h);
    vigra::FImage distance(w, h);

    // empty edge image
    edges = 0;
    ...

    // detect edges in src image (edges will be marked 1, background 0)
    vigra::differenceOfExponentialEdgeImage(srcImageRange(src), destImage(edges), 
                                     0.8, 4.0);
     
    // find distance of all pixels from nearest edge
    vigra::distanceTransform(srcImageRange(edges), destImage(distance),
                             0,                   2);
    //                       ^ background label   ^ norm (Euclidean)

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator dest_upperleft;
    
    SrcAccessor sa;
    DestAccessor da;
    
    ValueType background;
    float distance;
    
    sa(src_upperleft) != background;
    da(dest_upperleft) < distance;
    da.set(distance, dest_upperleft);

This operator applies an exponential filter to the source image at the given scale and subtracts the result from the original image. Zero crossings are detected in the resulting difference image. Whenever the gradient at a zero crossing is greater than the given gradient_threshold, an edge point is marked (using edge_marker) in the destination image on the darker side of the zero crossing (note that zero crossings occur between pixels). For example:

    sign of difference image     resulting edge points (*)

        + - -                          * * .
        + + -               =>         . * *
        + + +                          . . .

Non-edge pixels (.) remain untouched in the destination image. The result can be improved by the post-processing operation removeShortEdges(). A more accurate edge placement can be achieved with the function differenceOfExponentialCrackEdgeImage().

The source value type (SrcAccessor::value_type) must be a linear algebra, i.e. addition, subtraction and multiplication of the type with itself, and multiplication with double and NumericTraits must be defined. In addition, this type must be less-comparable.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
              class DestIterator, class DestAccessor,
              class GradValue,
              class DestValue = DestAccessor::value_type>
        void differenceOfExponentialEdgeImage(
               SrcIterator sul, SrcIterator slr, SrcAccessor sa,
               DestIterator dul, DestAccessor da,
               double scale, GradValue gradient_threshold,
               DestValue edge_marker = NumericTraits<DestValue>::one())
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
              class DestIterator, class DestAccessor,
              class GradValue,
              class DestValue = DestAccessor::value_type>
        void differenceOfExponentialEdgeImage(
               triple<SrcIterator, SrcIterator, SrcAccessor> src,
               pair<DestIterator, DestAccessor> dest,
               double scale, GradValue gradient_threshold,
               DestValue edge_marker = NumericTraits<DestValue>::one())
    }

Usage:

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

    vigra::BImage src(w,h), edges(w,h);

    // empty edge image
    edges = 0;
    ...

    // find edges at scale 0.8 with gradient larger than 4.0, mark with 1
    vigra::differenceOfExponentialEdgeImage(srcImageRange(src), destImage(edges),
                                     0.8, 4.0, 1);

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator dest_upperleft;

    SrcAccessor src_accessor;
    DestAccessor dest_accessor;

    SrcAccessor::value_type u = src_accessor(src_upperleft);
    double d;
    GradValue gradient_threshold;

    u = u + u
    u = u - u
    u = u * u
    u = d * u
    u < gradient_threshold

    DestValue edge_marker;
    dest_accessor.set(edge_marker, dest_upperleft);

Preconditions:

    scale > 0
    gradient_threshold > 0

This operator applies an exponential filter to the source image at the given scale and subtracts the result from the original image. Zero crossings are detected in the resulting difference image. Whenever the gradient at a zero crossing is greater than the given gradient_threshold, an edge point is marked (using edge_marker) in the destination image between the corresponding original pixels. Topologically, this means we must insert additional pixels between the original ones to represent the boundaries between the pixels (the so called zero- and one-cells, with the original pixels being two-cells). Within VIGRA, such an image is called Crack Edge Image. To allow insertion of the zero- and one-cells, the destination image must have twice the size of the original (precisely, (2*w-1) by (2*h-1) pixels). Then the algorithm proceeds as follows:

sign of difference image     insert zero- and one-cells     resulting edge points (*)

                                     + . - . -                   . * . . .
      + - -                          . . . . .                   . * * * .
      + + -               =>         + . + . -           =>      . . . * .
      + + +                          . . . . .                   . . . * *
                                     + . + . +                   . . . . .

Thus the edge points are marked where they actually are - in between the pixels. An important property of the resulting edge image is that it conforms to the notion of well-composedness as defined by Latecki et al., i.e. connected regions and edges obtained by a subsequent Connected Components Labeling do not depend on whether 4- or 8-connectivity is used. The non-edge pixels (.) in the destination image remain unchanged. The result conformes to the requirements of a Crack Edge Image. It can be further improved by the post-processing operations removeShortEdges() and closeGapsInCrackEdgeImage().

The source value type (SrcAccessor::value_type) must be a linear algebra, i.e. addition, subtraction and multiplication of the type with itself, and multiplication with double and NumericTraits must be defined. In addition, this type must be less-comparable.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
              class DestIterator, class DestAccessor,
              class GradValue,
              class DestValue = DestAccessor::value_type>
        void differenceOfExponentialCrackEdgeImage(
               SrcIterator sul, SrcIterator slr, SrcAccessor sa,
               DestIterator dul, DestAccessor da,
               double scale, GradValue gradient_threshold,
               DestValue edge_marker = NumericTraits<DestValue>::one())
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
              class DestIterator, class DestAccessor,
              class GradValue,
              class DestValue = DestAccessor::value_type>
        void differenceOfExponentialCrackEdgeImage(
               triple<SrcIterator, SrcIterator, SrcAccessor> src,
               pair<DestIterator, DestAccessor> dest,
               double scale, GradValue gradient_threshold,
               DestValue edge_marker = NumericTraits<DestValue>::one())
    }

Usage:

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

    vigra::BImage src(w,h), edges(2*w-1,2*h-1);

    // empty edge image
    edges = 0;
    ...

    // find edges at scale 0.8 with gradient larger than 4.0, mark with 1
    vigra::differenceOfExponentialCrackEdgeImage(srcImageRange(src), destImage(edges),
                                     0.8, 4.0, 1);

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator dest_upperleft;

    SrcAccessor src_accessor;
    DestAccessor dest_accessor;

    SrcAccessor::value_type u = src_accessor(src_upperleft);
    double d;
    GradValue gradient_threshold;

    u = u + u
    u = u - u
    u = u * u
    u = d * u
    u < gradient_threshold

    DestValue edge_marker;
    dest_accessor.set(edge_marker, dest_upperleft);

Preconditions:

    scale > 0
    gradient_threshold > 0

The destination image must have twice the size of the source:

    w_dest = 2 * w_src - 1
    h_dest = 2 * h_src - 1

This algorithm can be applied as a post-processing operation of differenceOfExponentialEdgeImage() and differenceOfExponentialCrackEdgeImage(). It removes all edges that are shorter than min_edge_length. The corresponding pixels are set to the non_edge_marker. The idea behind this algorithms is that very short edges are probably caused by noise and don't represent interesting image structure. Technically, the algorithms executes a connected components labeling, so the image's value type must be equality comparable.

If the source image fulfills the requirements of a Crack Edge Image, it will still do so after application of this algorithm.

Note that this algorithm, unlike most other algorithms in VIGRA, operates in-place, i.e. on only one image. Also, the algorithm assumes that all non-edges pixels are already marked with the given non_edge_marker value.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class Iterator, class Accessor, class SrcValue>
        void removeShortEdges(
               Iterator sul, Iterator slr, Accessor sa,
               int min_edge_length, SrcValue non_edge_marker)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class Iterator, class Accessor, class SrcValue>
        void removeShortEdges(
               triple<Iterator, Iterator, Accessor> src,
               int min_edge_length, SrcValue non_edge_marker)
    }

Usage:

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

    vigra::BImage src(w,h), edges(w,h);

    // empty edge image
    edges = 0;
    ...

    // find edges at scale 0.8 with gradient larger than 4.0, mark with 1
    vigra::differenceOfExponentialEdgeImage(srcImageRange(src), destImage(edges),
                                     0.8, 4.0, 1);

    // zero edges shorter than 10 pixels
    vigra::removeShortEdges(srcImageRange(edges), 10, 0);

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator dest_upperleft;

    SrcAccessor src_accessor;
    DestAccessor dest_accessor;

    SrcAccessor::value_type u = src_accessor(src_upperleft);

    u == u

    SrcValue non_edge_marker;
    src_accessor.set(non_edge_marker, src_upperleft);

This algorithm is typically applied as a post-processing operation of differenceOfExponentialCrackEdgeImage(). The source image must fulfill the requirements of a Crack Edge Image, and will still do so after application of this algorithm.

It closes one pixel wide gaps in the edges resulting from this algorithm. Since these gaps are usually caused by zero crossing slightly below the gradient threshold used in edge detection, this algorithms acts like a weak hysteresis thresholding. The newly found edge pixels are marked with the given edge_marker. The image's value type must be equality comparable.

Note that this algorithm, unlike most other algorithms in VIGRA, operates in-place, i.e. on only one image.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor, class SrcValue>
        void closeGapsInCrackEdgeImage(
               SrcIterator sul, SrcIterator slr, SrcAccessor sa,
               SrcValue edge_marker)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor, class SrcValue>
        void closeGapsInCrackEdgeImage(
               triple<SrcIterator, SrcIterator, SrcAccessor> src,
               SrcValue edge_marker)
    }

Usage:

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

    vigra::BImage src(w,h), edges(2*w-1, 2*h-1);

    // empty edge image
    edges = 0;
    ...

    // find edges at scale 0.8 with gradient larger than 4.0, mark with 1
    vigra::differenceOfExponentialCrackEdgeImage(srcImageRange(src), destImage(edges),
                                         0.8, 4.0, 1);

    // close gaps, mark with 1
    vigra::closeGapsInCrackEdgeImage(srcImageRange(edges), 1);

    // zero edges shorter than 20 pixels
    vigra::removeShortEdges(srcImageRange(edges), 10, 0);

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;

    SrcAccessor src_accessor;
    DestAccessor dest_accessor;

    SrcAccessor::value_type u = src_accessor(src_upperleft);

    u == u
    u != u

    SrcValue edge_marker;
    src_accessor.set(edge_marker, src_upperleft);

This algorithm is applied as a post-processing operation of differenceOfExponentialCrackEdgeImage(). The source image must fulfill the requirements of a Crack Edge Image, but will not do so after application of this algorithm. In particular, the algorithm removes zero-cells marked as edges to avoid staircase effects on diagonal lines like this:

    original edge points (*)     resulting edge points

          . * . . .                   . * . . .
          . * * * .                   . . * . .
          . . . * .           =>      . . . * .
          . . . * *                   . . . . *
          . . . . .                   . . . . .

Therfore, this algorithm should only be applied as a vizualization aid, i.e. for human inspection. The algorithm assumes that edges are marked with edge_marker, and background pixels with background_marker. The image's value type must be equality comparable.

Note that this algorithm, unlike most other algorithms in VIGRA, operates in-place, i.e. on only one image.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor, class SrcValue>
        void beautifyCrackEdgeImage(
               SrcIterator sul, SrcIterator slr, SrcAccessor sa,
               SrcValue edge_marker, SrcValue background_marker)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor, class SrcValue>
        void beautifyCrackEdgeImage(
                   triple<SrcIterator, SrcIterator, SrcAccessor> src,
               SrcValue edge_marker, SrcValue background_marker)
    }

Usage:

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

    vigra::BImage src(w,h), edges(2*w-1, 2*h-1);

    // empty edge image
    edges = 0;
    ...

    // find edges at scale 0.8 with gradient larger than 4.0, mark with 1
    vigra::differenceOfExponentialCrackEdgeImage(srcImageRange(src), destImage(edges),
                                         0.8, 4.0, 1);

    // beautify edge image for visualization
    vigra::beautifyCrackEdgeImage(destImageRange(edges), 1, 0);

    // show to the user
    window.open(edges);

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;

    SrcAccessor src_accessor;
    DestAccessor dest_accessor;

    SrcAccessor::value_type u = src_accessor(src_upperleft);

    u == u
    u != u

    SrcValue background_marker;
    src_accessor.set(background_marker, src_upperleft);

This operator first calculates the gradient vector for each pixel of the image using first derivatives of a Gaussian at the given scale. Then a very simple non-maxima supression is performed: for each 3x3 neighborhood, it is determined whether the center pixel has larger gradient magnitude than its two neighbors in gradient direction (where the direction is rounded into octands). If this is the case, a new Edgel is appended to the given vector of edgels. The subpixel edgel position is determined by fitting a parabola to the three gradient magnitude values mentioned above. The sub-pixel location of the parabola's tip and the gradient magnitude and direction (from the pixel center) are written in the newly created edgel.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor, class BackInsertable>
        void cannyEdgelList(SrcIterator ul, SrcIterator lr, SrcAccessor src,
                            BackInsertable & edgels, double scale);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor, class BackInsertable>
        void
        cannyEdgelList(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                       BackInsertable & edgels, double scale);
    }

Usage:

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

    vigra::BImage src(w,h);

    // empty edgel list
    std::vector<vigra::Edgel> edgels;
    ...

    // find edgels at scale 0.8
    vigra::cannyEdgelList(srcImageRange(src), edgels, 0.8);

Required Interface:

    SrcImageIterator src_upperleft;
    SrcAccessor src_accessor;

    src_accessor(src_upperleft);

    BackInsertable edgels;
    edgels.push_back(Edgel());

SrcAccessor::value_type must be a type convertible to float

Preconditions:

    scale > 0

This operator first calls cannyEdgelList() to generate an edgel list for the given image. Then it scans this list and selects edgels whose strength is above the given gradient_threshold. For each of these edgels, the edgel's location is rounded to the nearest pixel, and that pixel marked with the given edge_marker.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  class GradValue, class DestValue>
        void cannyEdgeImage(
                   SrcIterator sul, SrcIterator slr, SrcAccessor sa,
                   DestIterator dul, DestAccessor da,
                   double scale, GradValue gradient_threshold, DestValue edge_marker);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  class GradValue, class DestValue>
        void cannyEdgeImage(
                   triple<SrcIterator, SrcIterator, SrcAccessor> src,
                   pair<DestIterator, DestAccessor> dest,
                   double scale, GradValue gradient_threshold, DestValue edge_marker);
    }

Usage:

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

    vigra::BImage src(w,h), edges(w,h);

    // empty edge image
    edges = 0;
    ...

    // find edges at scale 0.8 with gradient larger than 4.0, mark with 1
    vigra::cannyEdgeImage(srcImageRange(src), destImage(edges),
                                     0.8, 4.0, 1);

Required Interface:

see also: cannyEdgelList().

    DestImageIterator dest_upperleft;
    DestAccessor dest_accessor;
    DestValue edge_marker;

    dest_accessor.set(edge_marker, dest_upperleft, vigra::Diff2D(1,1));

Preconditions:

    scale > 0
    gradient_threshold > 0

The input pixels of this algorithms must be vectors of length 2 (see Required Interface below). It first searches for all pixels whose gradient magnitude is larger than the given gradient_threshold and larger than the magnitude of its two neighbors in gradient direction (where these neighbors are determined by nearest neighbor interpolation, i.e. according to the octant where the gradient points into). The resulting edge pixel candidates are then subjected to topological thinning so that the remaining edge pixels can be linked into edgel chains with a provable, non-heuristic algorithm. Thinning is performed so that the pixels with highest gradient magnitude survive. Optionally, the outermost pixels are marked as edge pixels as well when addBorder is true. The remaining pixels will be marked in the destination image with the value of edge_marker (all non-edge pixels remain untouched).

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  class GradValue, class DestValue>
        void cannyEdgeImageFromGradWithThinning(
                   SrcIterator sul, SrcIterator slr, SrcAccessor sa,
                   DestIterator dul, DestAccessor da,
                   GradValue gradient_threshold,
                   DestValue edge_marker, bool addBorder = true);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  class GradValue, class DestValue>
        void cannyEdgeImageFromGradWithThinning(
                   triple<SrcIterator, SrcIterator, SrcAccessor> src,
                   pair<DestIterator, DestAccessor> dest,
                   GradValue gradient_threshold,
                   DestValue edge_marker, bool addBorder = true);
    }

Usage:

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

    vigra::BImage src(w,h), edges(w,h);

    vigra::FVector2Image grad(w,h);
    // compute the image gradient at scale 0.8
    vigra::gaussianGradient(srcImageRange(src), destImage(grad), 0.8);

    // empty edge image
    edges = 0;
    // find edges gradient larger than 4.0, mark with 1, and add border
    vigra::cannyEdgeImageFromGradWithThinning(srcImageRange(grad), destImage(edges),
                                              4.0, 1, true);

Required Interface:

    // the input pixel type must be a vector with two elements
    SrcImageIterator src_upperleft;
    SrcAccessor src_accessor;
    typedef SrcAccessor::value_type SrcPixel;
    typedef NormTraits<SrcPixel>::SquaredNormType SrcSquaredNormType;

    SrcPixel g = src_accessor(src_upperleft);
    SrcPixel::value_type g0 = g[0];
    SrcSquaredNormType gn = squaredNorm(g);

    DestImageIterator dest_upperleft;
    DestAccessor dest_accessor;
    DestValue edge_marker;

    dest_accessor.set(edge_marker, dest_upperleft, vigra::Diff2D(1,1));

Preconditions:

    gradient_threshold > 0

This operator first calls gaussianGradient() to compute the gradient of the input image, ad then cannyEdgeImageFromGradWithThinning() to generate an edge image. See there for more detailed documentation.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  class GradValue, class DestValue>
        void cannyEdgeImageWithThinning(
                   SrcIterator sul, SrcIterator slr, SrcAccessor sa,
                   DestIterator dul, DestAccessor da,
                   double scale, GradValue gradient_threshold,
                   DestValue edge_marker, bool addBorder = true);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  class GradValue, class DestValue>
        void cannyEdgeImageWithThinning(
                   triple<SrcIterator, SrcIterator, SrcAccessor> src,
                   pair<DestIterator, DestAccessor> dest,
                   double scale, GradValue gradient_threshold,
                   DestValue edge_marker, bool addBorder = true);
    }

Usage:

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

    vigra::BImage src(w,h), edges(w,h);

    // empty edge image
    edges = 0;
    ...

    // find edges at scale 0.8 with gradient larger than 4.0, mark with 1, annd add border
    vigra::cannyEdgeImageWithThinning(srcImageRange(src), destImage(edges),
                                     0.8, 4.0, 1, true);

Required Interface:

see also: cannyEdgelList().

    DestImageIterator dest_upperleft;
    DestAccessor dest_accessor;
    DestValue edge_marker;

    dest_accessor.set(edge_marker, dest_upperleft, vigra::Diff2D(1,1));

Preconditions:

    scale > 0
    gradient_threshold > 0

This operator first computes pixels which are crossed by the edge using cannyEdgeImageWithThinning(). The gradient magnitude in the 3x3 neighborhood of these pixels are then projected onto the normal of the edge (as determined by the gradient direction). The edgel's subpixel location is found by fitting a parabola through the 9 gradient values and determining the parabola's tip. A new Edgel is appended to the given vector of edgels. Since the parabola is fitted to 9 points rather than 3 points as in cannyEdgelList(), the accuracy is higher.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor, class BackInsertable>
        void cannyEdgelList3x3(SrcIterator ul, SrcIterator lr, SrcAccessor src,
                               BackInsertable & edgels, double scale);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor, class BackInsertable>
        void
        cannyEdgelList3x3(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                          BackInsertable & edgels, double scale);
    }

Usage:

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

    vigra::BImage src(w,h);

    // empty edgel list
    std::vector<vigra::Edgel> edgels;
    ...

    // find edgels at scale 0.8
    vigra::cannyEdgelList3x3(srcImageRange(src), edgels, 0.8);

Required Interface:

    SrcImageIterator src_upperleft;
    SrcAccessor src_accessor;

    src_accessor(src_upperleft);

    BackInsertable edgels;
    edgels.push_back(Edgel());

SrcAccessor::value_type must be a type convertible to float

Preconditions:

    scale > 0

FFTW produces fourier images where the DC component (origin of fourier space) is located in the upper left corner of the image. The quadrants are placed like this (using a 4x4 image for example):

            DC 4 3 3
             4 4 3 3
             1 1 2 2
             1 1 2 2

After applying the function, the quadrants are at their usual places:

            2 2  1 1
            2 2  1 1
            3 3 DC 4
            3 3  4 4

This transformation can be reversed by moveDCToUpperLeft(). Note that the transformation must not be executed in place - input and output images must be different.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
          class DestImageIterator, class DestAccessor>
        void moveDCToCenter(SrcImageIterator src_upperleft,
                               SrcImageIterator src_lowerright, SrcAccessor sa,
                               DestImageIterator dest_upperleft, DestAccessor da);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
                  class DestImageIterator, class DestAccessor>
        void moveDCToCenter(
            triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
            pair<DestImageIterator, DestAccessor> dest);
    }

Usage:

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

    vigra::FFTWComplexImage spatial(width,height), fourier(width,height);
    ... // fill image with data

    // create a plan with estimated performance optimization
    fftw_plan forwardPlan = fftw_plan_dft_2d(height, width,
                                (fftw_complex *)spatial.begin(), (fftw_complex *)fourier.begin(),
                                FFTW_FORWARD, FFTW_ESTIMATE );
    // calculate FFT
    fftw_execute(forwardPlan);

    vigra::FFTWComplexImage rearrangedFourier(width, height);
    moveDCToCenter(srcImageRange(fourier), destImage(rearrangedFourier));

    // delete the plan
    fftw_destroy_plan(forwardPlan);

This function is the inversion of moveDCToCenter(). See there for declarations and a usage example.

Declarations:

pass arguments explicitly:

        namespace vigra {
            template <class SrcImageIterator, class SrcAccessor,
                      class DestImageIterator, class DestAccessor>
            void moveDCToUpperLeft(SrcImageIterator src_upperleft,
                                   SrcImageIterator src_lowerright, SrcAccessor sa,
                                   DestImageIterator dest_upperleft, DestAccessor da);
        }

use argument objects in conjunction with Argument Object Factories :

        namespace vigra {
            template <class SrcImageIterator, class SrcAccessor,
                      class DestImageIterator, class DestAccessor>
            void moveDCToUpperLeft(
                triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
                pair<DestImageIterator, DestAccessor> dest);
        }

In the forward direction, the input image may be scalar or complex, and the output image is always complex. In the inverse direction, both input and output must be complex.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor>
        void fourierTransform(SrcImageIterator srcUpperLeft,
                              SrcImageIterator srcLowerRight, SrcAccessor src,
                              FFTWComplexImage::traverser destUpperLeft, FFTWComplexImage::Accessor dest);

        void
        fourierTransformInverse(FFTWComplexImage::const_traverser sul,
                                FFTWComplexImage::const_traverser slr, FFTWComplexImage::ConstAccessor src,
                                FFTWComplexImage::traverser dul, FFTWComplexImage::Accessor dest)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor>
        void fourierTransform(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
                              pair<FFTWComplexImage::traverser, FFTWComplexImage::Accessor> dest);

        void
        fourierTransformInverse(triple<FFTWComplexImage::const_traverser,
                                       FFTWComplexImage::const_traverser, FFTWComplexImage::ConstAccessor> src,
                                pair<FFTWComplexImage::traverser, FFTWComplexImage::Accessor> dest);
    }

Usage:

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

    // compute complex Fourier transform of a real image
    vigra::DImage src(w, h);
    vigra::FFTWComplexImage fourier(w, h);

    fourierTransform(srcImageRange(src), destImage(fourier));

    // compute inverse Fourier transform
    // note that both source and destination image must be of type vigra::FFTWComplexImage
    vigra::FFTWComplexImage inverseFourier(w, h);

    fourierTransform(srcImageRange(fourier), destImage(inverseFourier));

After transferring the image into the frequency domain, it is multiplied pixel-wise with the filter and transformed back. The result is put into the given destination image which must have the right size. The result will be normalized to compensate for the two FFTs.

If the destination image is scalar, only the real part of the result image is retained. In this case, you are responsible for choosing a filter image which ensures a zero imaginary part of the result (e.g. use a real, even symmetric filter image, or a purely imaginary, odd symmetric on).

The DC entry of the filter must be in the upper left, which is the position where FFTW expects it (see moveDCToUpperLeft()).

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
                  class FilterImageIterator, class FilterAccessor,
                  class DestImageIterator, class DestAccessor>
        void applyFourierFilter(SrcImageIterator srcUpperLeft,
                                SrcImageIterator srcLowerRight, SrcAccessor sa,
                                FilterImageIterator filterUpperLeft, FilterAccessor fa,
                                DestImageIterator destUpperLeft, DestAccessor da);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
                  class FilterImageIterator, class FilterAccessor,
                  class DestImageIterator, class DestAccessor>
        void applyFourierFilter(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
                                pair<FilterImageIterator, FilterAccessor> filter,
                                pair<DestImageIterator, DestAccessor> dest);
    }

Usage:

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

    // create a Gaussian filter in Fourier space
    vigra::FImage gaussFilter(w, h), filter(w, h);
    for(int y=0; y<h; ++y)
        for(int x=0; x<w; ++x)
        {
            xx = float(x - w / 2) / w;
            yy = float(y - h / 2) / h;

            gaussFilter(x,y) = std::exp(-(xx*xx + yy*yy) / 2.0 * scale);
        }

    // applyFourierFilter() expects the filter's DC in the upper left
    moveDCToUpperLeft(srcImageRange(gaussFilter), destImage(filter));

    vigra::FFTWComplexImage result(w, h);

    vigra::applyFourierFilter(srcImageRange(image), srcImage(filter), result);

For inspection of the result, FFTWMagnitudeAccessor might be useful. If you want to apply the same filter repeatedly, it may be more efficient to use the FFTW functions directly with FFTW plans optimized for good performance.

This provides the same functionality as applyFourierFilter(), but applying several filters at once allows to avoid repeated Fourier transforms of the source image.

Filters and result images must be stored in vigra::ImageArray data structures. In contrast to applyFourierFilter(), this function adjusts the size of the result images and the the length of the array.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor, class FilterType>
        void applyFourierFilterFamily(SrcImageIterator srcUpperLeft,
                                      SrcImageIterator srcLowerRight, SrcAccessor sa,
                                      const ImageArray<FilterType> &filters,
                                      ImageArray<FFTWComplexImage> &results)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor, class FilterType>
        void applyFourierFilterFamily(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
                                      const ImageArray<FilterType> &filters,
                                      ImageArray<FFTWComplexImage> &results)
    }

Usage:

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

    // assuming the presence of a real-valued image named "image" to
    // be filtered in this example

    vigra::ImageArray<vigra::FImage> filters(16, image.size());

    for (int i=0; i<filters.size(); i++)
         // create some meaningful filters here
         createMyFilterOfScale(i, destImage(filters[i]));

    vigra::ImageArray<vigra::FFTWComplexImage> results();

    vigra::applyFourierFilterFamily(srcImageRange(image), filters, results);

If the image is real and has even symmetry, its Fourier transform is also real and has even symmetry. The Fourier transform of a real image with odd symmetry is imaginary and has odd symmetry. In either case, only about a quarter of the pixels need to be stored because the rest can be calculated from the symmetry properties. This is especially useful, if the original image is implicitly assumed to have reflective or anti-reflective boundary conditions. Then the "negative" pixel locations are defined as

    even (reflective boundary conditions):      f[-x] = f[x]     (x = 1,...,N-1)
    odd (anti-reflective boundary conditions):  f[-1] = 0
                                                f[-x] = -f[x-2]  (x = 2,...,N-1)

end similar at the other boundary (see the FFTW documentation for details). This has the advantage that more efficient Fourier transforms that use only real numbers can be implemented. These are also known as cosine and sine transforms respectively.

If you use the odd transform it is important to note that in the Fourier domain, the DC component is always zero and is therefore dropped from the data structure. This means that index 0 in an odd symmetric Fourier domain image refers to the first harmonic. This is especially important if an image is first cosine transformed (even symmetry), then in the Fourier domain multiplied with an odd symmetric filter (e.g. a first derivative) and finally transformed back to the spatial domain with a sine transform (odd symmetric). For this to work properly the image must be shifted left or up by one pixel (depending on whether the x- or y-axis is odd symmetric) before the inverse transform can be applied. (see example below).

The real Fourier transform functions are named fourierTransformReal?? where the questions marks stand for either E or O indicating whether the x- and y-axis is to be transformed using even or odd symmetry. The same functions can be used for both the forward and inverse transforms, only the normalization changes. For signal processing, the following normalization factors are most appropriate:

                          forward             inverse
    ------------------------------------------------------------
    X even, Y even           1.0         4.0 * (w-1) * (h-1)
    X even, Y odd           -1.0        -4.0 * (w-1) * (h+1)
    X odd,  Y even          -1.0        -4.0 * (w+1) * (h-1)
    X odd,  Y odd            1.0         4.0 * (w+1) * (h+1)

where w and h denote the image width and height.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcTraverser, class SrcAccessor,
                  class DestTraverser, class DestAccessor>
        void
        fourierTransformRealEE(SrcTraverser sul, SrcTraverser slr, SrcAccessor src,
                               DestTraverser dul, DestAccessor dest, fftw_real norm);

        fourierTransformRealEO, fourierTransformRealOE, fourierTransformRealOO likewise
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcTraverser, class SrcAccessor,
                  class DestTraverser, class DestAccessor>
        void
        fourierTransformRealEE(triple<SrcTraverser, SrcTraverser, SrcAccessor> src,
                               pair<DestTraverser, DestAccessor> dest, fftw_real norm);

        fourierTransformRealEO, fourierTransformRealOE, fourierTransformRealOO likewise
    }

Usage:

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

    vigra::FImage spatial(width,height), fourier(width,height);
    ... // fill image with data

    // forward cosine transform == reflective boundary conditions
    fourierTransformRealEE(srcImageRange(spatial), destImage(fourier), (fftw_real)1.0);

    // multiply with a first derivative of Gaussian in x-direction
    for(int y = 0; y < height; ++y)
    {
        for(int x = 1; x < width; ++x)
        {
            double dx = x * M_PI / (width - 1);
            double dy = y * M_PI / (height - 1);
            fourier(x-1, y) = fourier(x, y) * dx * std::exp(-(dx*dx + dy*dy) * scale*scale / 2.0);
        }
        fourier(width-1, y) = 0.0;
    }

    // inverse transform -- odd symmetry in x-direction, even in y,
    //                      due to symmetry of the filter
    fourierTransformRealOE(srcImageRange(fourier), destImage(spatial),
                           (fftw_real)-4.0 * (width+1) * (height-1));

The pixel values of the source image must be in the range 0...255. Radius must be >= 0. Rank must be in the range 0.0 <= rank <= 1.0. The filter acts as a minimum filter if rank = 0.0, as a median if rank = 0.5, and as a maximum filter if rank = 1.0. Accessor are used to access the pixel data.

Declarations:

pass arguments explicitely:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        discRankOrderFilter(SrcIterator upperleft1, 
                            SrcIterator lowerright1, SrcAccessor sa,
                            DestIterator upperleft2, DestAccessor da,
                            int radius, float rank)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        discRankOrderFilter(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                            pair<DestIterator, DestAccessor> dest,
                            int radius, float rank)
    }

Usage:

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

    vigra::CImage src, dest;
    
    // do median filtering
    vigra::discRankOrderFilter(srcImageRange(src), destImage(dest), 10, 0.5);

Required Interface:

    SrcIterator src_upperleft;
    DestIterator dest_upperleft;
    int x, y;
    unsigned char value;
    
    SrcAccessor src_accessor;
    DestAccessor dest_accessor;
    
    // value_type of accessor must be convertible to unsigned char
    value = src_accessor(src_upperleft, x, y); 
    
    dest_accessor.set(value, dest_upperleft, x, y);

Preconditions:

    for all source pixels: 0 <= value <= 255
    
    (rank >= 0.0) && (rank <= 1.0)
    radius >= 0

This is an abbreviation vor the rank order filter with rank = 0.0. See discRankOrderFilter() for more information.

Declarations:

pass arguments explicitely:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void 
        discErosion(SrcIterator upperleft1, 
                    SrcIterator lowerright1, SrcAccessor sa,
                    DestIterator upperleft2, DestAccessor da,
                    int radius)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        discErosion(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                    pair<DestIterator, DestAccessor> dest,
                    int radius)
    }

This is an abbreviation vor the rank order filter with rank = 1.0. See discRankOrderFilter() for more information.

Declarations:

pass arguments explicitely:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void 
        discDilation(SrcIterator upperleft1, 
                    SrcIterator lowerright1, SrcAccessor sa,
                    DestIterator upperleft2, DestAccessor da,
                    int radius)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        discDilation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                    pair<DestIterator, DestAccessor> dest,
                    int radius)
    }

This is an abbreviation vor the rank order filter with rank = 0.5. See discRankOrderFilter() for more information.

Declarations:

pass arguments explicitely:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void 
        discMedian(SrcIterator upperleft1, 
                    SrcIterator lowerright1, SrcAccessor sa,
                    DestIterator upperleft2, DestAccessor da,
                    int radius)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        discMedian(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                    pair<DestIterator, DestAccessor> dest,
                    int radius)
    }

The pixel values of the source image must be in the range 0...255. Radius must be >= 0. Rank must be in the range 0.0 <= rank <= 1.0. The filter acts as a minimum filter if rank = 0.0, as a median if rank = 0.5, and as a maximum filter if rank = 1.0. Accessor are used to access the pixel data.

The mask is only applied to th input image, i.e. the function generates an output wherever the current disc contains at least one pixel with mask value 'true'. Source pixels with mask value 'false' are ignored during the calculation of the rank order.

Declarations:

pass arguments explicitely:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class MaskIterator, class MaskAccessor,
                  class DestIterator, class DestAccessor>
        void
        discRankOrderFilterWithMask(SrcIterator upperleft1, 
                                    SrcIterator lowerright1, SrcAccessor sa,
                                    MaskIterator upperleftm, MaskAccessor mask,
                                    DestIterator upperleft2, DestAccessor da,
                                    int radius, float rank)
    }

group arguments (use in conjunction with Argument Object Factories):

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class MaskIterator, class MaskAccessor,
                  class DestIterator, class DestAccessor>
        void
        discRankOrderFilterWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                                    pair<MaskIterator, MaskAccessor> mask,
                                    pair<DestIterator, DestAccessor> dest,
                                    int radius, float rank)
    }

Usage:

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

    vigra::CImage src, dest, mask;
    
    // do median filtering
    vigra::discRankOrderFilterWithMask(srcImageRange(src), 
                                maskImage(mask), destImage(dest), 10, 0.5);

Required Interface:

    SrcIterator src_upperleft;
    DestIterator dest_upperleft;
    MaskIterator mask_upperleft;
    int x, y;
    unsigned char value;
    
    SrcAccessor src_accessor;
    DestAccessor dest_accessor;
    MaskAccessor mask_accessor;
                     
    mask_accessor(mask_upperleft, x, y) // convertible to bool
    
    // value_type of accessor must be convertible to unsigned char
    value = src_accessor(src_upperleft, x, y); 
    
    dest_accessor.set(value, dest_upperleft, x, y);

Preconditions:

    for all source pixels: 0 <= value <= 255
    
    (rank >= 0.0) && (rank <= 1.0)
    radius >= 0

This is an abbreviation vor the masked rank order filter with rank = 0.0. See discRankOrderFilterWithMask() for more information.

Declarations:

pass arguments explicitely:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class MaskIterator, class MaskAccessor,
                  class DestIterator, class DestAccessor>
        void 
        discErosionWithMask(SrcIterator upperleft1, 
                            SrcIterator lowerright1, SrcAccessor sa,
                            MaskIterator upperleftm, MaskAccessor mask,
                            DestIterator upperleft2, DestAccessor da,
                            int radius)
    }

group arguments (use in conjunction with Argument Object Factories):

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class MaskIterator, class MaskAccessor,
                  class DestIterator, class DestAccessor>
        void 
        discErosionWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                            pair<MaskIterator, MaskAccessor> mask,
                            pair<DestIterator, DestAccessor> dest,
                            int radius)
    }

This is an abbreviation vor the masked rank order filter with rank = 1.0. See discRankOrderFilterWithMask() for more information.

Declarations:

pass arguments explicitely:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class MaskIterator, class MaskAccessor,
                  class DestIterator, class DestAccessor>
        void 
        discDilationWithMask(SrcIterator upperleft1, 
                            SrcIterator lowerright1, SrcAccessor sa,
                            MaskIterator upperleftm, MaskAccessor mask,
                            DestIterator upperleft2, DestAccessor da,
                            int radius)
    }

group arguments (use in conjunction with Argument Object Factories):

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class MaskIterator, class MaskAccessor,
                  class DestIterator, class DestAccessor>
        void 
        discDilationWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                            pair<MaskIterator, MaskAccessor> mask,
                            pair<DestIterator, DestAccessor> dest,
                            int radius)
    }

This is an abbreviation vor the masked rank order filter with rank = 0.5. See discRankOrderFilterWithMask() for more information.

Declarations:

pass arguments explicitely:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class MaskIterator, class MaskAccessor,
                  class DestIterator, class DestAccessor>
        void 
        discMedianWithMask(SrcIterator upperleft1, 
                            SrcIterator lowerright1, SrcAccessor sa,
                            MaskIterator upperleftm, MaskAccessor mask,
                            DestIterator upperleft2, DestAccessor da,
                            int radius)
    }

group arguments (use in conjunction with Argument Object Factories):

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class MaskIterator, class MaskAccessor,
                  class DestIterator, class DestAccessor>
        void 
        discMedianWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                            pair<MaskIterator, MaskAccessor> mask,
                            pair<DestIterator, DestAccessor> dest,
                            int radius)
    }

The orientation is given in radians, the other parameters are the center frequency (for example 0.375 or smaller) and the two angular and radial sigmas of the gabor filter. (See angularGaborSigma() for an explanation of possible values.)

The energy of the filter is explicitely normalized to 1.0.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class DestImageIterator, class DestAccessor>
        void createGaborFilter(DestImageIterator destUpperLeft,
                               DestImageIterator destLowerRight,
                               DestAccessor da,
                               double orientation, double centerFrequency,
                               double angularSigma, double radialSigma)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class DestImageIterator, class DestAccessor>
        void createGaborFilter(triple<DestImageIterator,
                                      DestImageIterator,
                                      DestAccessor> dest,
                               double orientation, double centerFrequency,
                               double angularSigma, double radialSigma)
    }

Usage:

#include <vigra/gaborfilter.hxx>

Namespace: vigra

    vigra::FImage gabor(w,h);

    vigra::createGaborFilter(destImageRange(gabor), orient, freq,
                             angularGaborSigma(directionCount, freq)
                             radialGaborSigma(freq));

These function calculates the gradient energy tensor (GET operator) as described in

M. Felsberg, U. Köthe: "GET: The Connection Between Monogenic Scale-Space and Gaussian Derivatives", in: R. Kimmel, N. Sochen, J. Weickert (Eds.): Scale Space and PDE Methods in Computer Vision, Proc. of Scale-Space 2005, Lecture Notes in Computer Science 3459, pp. 192-203, Heidelberg: Springer, 2005.

U. Köthe, M. Felsberg: "Riesz-Transforms Versus Derivatives: On the Relationship Between the Boundary Tensor and the Energy Tensor", in: ditto, pp. 179-191.

with the given filters: The derivative filter derivKernel is applied to the appropriate image dimensions in turn (see the papers above for details), and the other dimension is smoothed with smoothKernel. The kernels can be as small as 3x1, e.g. [0.5, 0, -0.5] and [3.0/16.0, 10.0/16.0, 3.0/16.0] respectively. The output image must have 3 bands which will hold the tensor components in the order t11, t12 (== t21), t22. The signs of the output are adjusted for a right-handed coordinate system. Thus, orientations derived from the tensor will be in counter-clockwise (mathematically positive) order, with the x-axis at zero degrees (this is the standard in all VIGRA functions that deal with orientation).

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void gradientEnergyTensor(SrcIterator supperleft, SrcIterator slowerright, SrcAccessor src,
                                  DestIterator dupperleft, DestAccessor dest,
                                  Kernel1D<double> const & derivKernel, Kernel1D<double> const & smoothKernel);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void gradientEnergyTensor(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                                  pair<DestIterator, DestAccessor> dest,
                                  Kernel1D<double> const & derivKernel, Kernel1D<double> const & smoothKernel);
    }

Usage:

#include <vigra/gradient_energy_tensor.hxx>

    FImage img(w,h);
    FVector3Image get(w,h);
    Kernel1D<double> grad, smooth;
    grad.initGaussianDerivative(0.7, 1);
    smooth.initGaussian(0.7);
    ...
    gradientEnergyTensor(srcImageRange(img), destImage(get), grad, smooth);

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

Declaration:

        namespace vigra {
            template< class ImageIterator, class Accessor >
            void importVectorImage( const ImageImportInfo & info, ImageIterator iter, Accessor a )
        }

Paramters:

ImageIterator
the image iterator type for the destination image
Accessor
the image accessor type for the destination image
info
user supplied image import information
iter
image iterator referencing the upper left pixel of the destination image
a
image accessor for the destination image

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

Declaration:

        namespace vigra {
            template < class ImageIterator, class Accessor >
            void importScalarImage( const ImageImportInfo & info, ImageIterator iter, Accessor a )
        }

Paramters:

ImageIterator
the image iterator type for the destination image
Accessor
the image accessor type for the destination image
info
user supplied image import information
iter
image iterator referencing the upper left pixel of the destination image
a
image accessor for the destination image

Declarations:

pass arguments explicitly:

        namespace vigra {
            template <class ImageIterator, class Accessor>
            void
            importImage(ImageImportInfo const & image, ImageIterator iter, Accessor a)
        }

use argument objects in conjunction with Argument Object Factories :

        namespace vigra {
            template <class ImageIterator, class Accessor>
            inline void
            importImage(ImageImportInfo const & image, pair<ImageIterator, Accessor> dest)
        }

Usage:

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

        vigra::ImageImportInfo info("myimage.gif");

        if(info.isGrayscale())
        {
            // create byte image of appropriate size
            vigra::BImage in(info.width(), info.height());

            vigra::importImage(info, destImage(in)); // read the image
            ...
        }
        else
        {
            // create byte RGB image of appropriate size
            vigra::BRGBImage in(info.width(), info.height());

            vigra::importImage(info, destImage(in)); // read the image
            ...
        }

Preconditions:

  • the image file must be readable
  • the file type must be one of

    "BMP"
    Microsoft Windows bitmap image file.
    "GIF"
    CompuServe graphics interchange format; 8-bit color.
    "JPEG"
    Joint Photographic Experts Group JFIF format; compressed 24-bit color. (only available if libjpeg is installed)
    "PNG"
    Portable Network Graphic. (only available if libpng is installed)
    "PBM"
    Portable bitmap format (black and white).
    "PGM"
    Portable graymap format (gray scale).
    "PNM"
    Portable anymap.
    "PPM"
    Portable pixmap format (color).
    "SUN"
    SUN Rasterfile.
    "TIFF"
    Tagged Image File Format. (only available if libtiff is installed.)
    "VIFF"
    Khoros Visualization image file.

Use exportImage() instead.

Declaration:

        namespace vigra {
            template < class SrcIterator, class SrcAccessor >
            void exportFloatingVectorImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
                                            const ImageExportInfo & info )
        }

Use exportImage() instead.

Declaration:

        namespace vigra {
            template < class SrcIterator, class SrcAccessor >
            void exportIntegralVectorImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
                                            const ImageExportInfo & info )
        }

Use exportImage() instead.

Declaration:

        namespace vigra {
            template < class SrcIterator, class SrcAccessor >
            void exportFloatingScalarImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
                                            const ImageExportInfo & info )
        }

Use exportImage() instead.

Declaration:

        namespace vigra {
            template < class SrcIterator, class SrcAccessor >
            void exportIntegralScalarImage( SrcIterator sul, SrcIterator slr, SrcAccessor sget,
                                            const ImageExportInfo & info )
        }

If the file format to be exported to supports the pixel type of the source image, the pixel type will be kept (e.g. float can be stored as TIFF without conversion, in contrast to most other image export toolkits). Otherwise, the pixel values are transformed to the range 0.255 and converted to unsigned char. Currently, the following file formats are supported. The pixel types given in brackets are those that are written without conversion:

"BMP"
Microsoft Windows bitmap image file (pixel types: UINT8 as gray and RGB).
"GIF"
CompuServe graphics interchange format; 8-bit color (pixel types: UINT8 as gray and RGB).
"JPEG"
Joint Photographic Experts Group JFIF format; compressed 24-bit color (pixel types: UINT8 as gray and RGB). (only available if libjpeg is installed)
"PNG"
Portable Network Graphic (pixel types: UINT8 and UINT16 with up to 4 channels). (only available if libpng is installed)
"PBM"
Portable bitmap format (black and white).
"PGM"
Portable graymap format (pixel types: UINT8, INT16, INT32 as gray scale)).
"PNM"
Portable anymap (pixel types: UINT8, INT16, INT32 as gray and RGB).
"PPM"
Portable pixmap format (pixel types: UINT8, INT16, INT32 as RGB).
"SUN"
SUN Rasterfile (pixel types: UINT8 as gray and RGB).
"TIFF"
Tagged Image File Format (pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with up to 4 channels). (only available if libtiff is installed.)
"VIFF"
Khoros Visualization image file (pixel types: UINT8, INT16, INT32, FLOAT, DOUBLE with arbitrary many channels).

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor>
        void exportImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
                         ImageExportInfo const & info)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor>
        void exportImage(SrcIterator sul, SrcIterator slr, SrcAccessor sget,
                         ImageExportInfo const & info)
    }

Usage:

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

    vigra::BRGBImage out(w, h);
    ...

    // write as JPEG image, using compression quality 80
    vigra::exportImage(srcImageRange(out),
                      vigra::ImageExportInfo("myimage.jpg").setCompression("80"));


    // force it to a particular pixel type (the pixel type must be supported by the
    // desired image file format, otherwise an \ref vigra::PreconditionViolation exception will be thrown)
    vigra::exportImage(srcImageRange(out),
                      vigra::ImageExportInfo("myINT16image.tif").setPixelType("INT16"));

Preconditions:

  • the image file must be writable.
  • the file type must be one of the supported file types.

This function can be used to init the image. It uses an accessor to access the pixel data.

The initial value can either be a constant of appropriate type (compatible with the destination's value_type), or a functor with compatible result_type. These two cases are automatically distinguished when FunctorTraits<FUNCTOR>::isInitializer yields VigraTrueType. Since the functor is passed by const reference, its operator() must be const, and its internal state may need to be mutable.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class ImageIterator, class Accessor, class VALUETYPE>
        void initImage(ImageIterator upperleft, ImageIterator lowerright, 
                       Accessor a, VALUETYPE const & v);

        template <class ImageIterator, class Accessor, class FUNCTOR>
        void initImage(ImageIterator upperleft, ImageIterator lowerright, 
                       Accessor a, FUNCTOR const & v);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class ImageIterator, class Accessor, class VALUETYPE>
        void initImage(triple<ImageIterator, ImageIterator, Accessor> img, VALUETYPE const & v);

        template <class ImageIterator, class Accessor, class FUNCTOR>
        void initImage(triple<ImageIterator, ImageIterator, Accessor> img, FUNCTOR const & v);
    }

Usage:

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

Initialize with a constant:

    vigra::BImage img(100, 100);
    
    // init the image with the value 128
    vigra::initImage(destImageRange(img), 128);

Initialize with a functor:

    struct Counter {
        Counter() : count(0) {}
        
        int operator()() const { return count++; }
    
        mutable int count;
    };
    
    vigra::IImage img(100, 100);
        
    // write the current count in every pixel
    vigra::initImage(destImageRange(img), Counter());

Required Interface:

    ImageIterator upperleft, lowerright;
    ImageIterator::row_iterator ix = upperleft.rowIterator();
    
    Accessor accessor;
    VALUETYPE v;
    
    accessor.set(v, ix); 

This function can be used to init the image by calling the given functor for each pixel. It uses an accessor to access the pixel data. The functor is passed by reference, so that its internal state can be updated in each call.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class ImageIterator, class Accessor, class FUNCTOR>
        void
        initImageWithFunctor(ImageIterator upperleft, ImageIterator lowerright, 
                  Accessor a,  FUNCTOR & f);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class ImageIterator, class Accessor, class FUNCTOR>
        void
        initImageWithFunctor(triple<ImageIterator, ImageIterator, Accessor> img, FUNCTOR & f);
    }

Usage:

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

    struct Counter {
        Counter() : count(0) {}
        
        int operator()() const { return count++; }
    
        mutable int count;
    };
    
    vigra::IImage img(100, 100);
        
    // write the current count in every pixel
    Counter counter;
    vigra::initImageWithFunctor(destImageRange(img), counter);

Required Interface:

    ImageIterator upperleft, lowerright;
    ImageIterator::row_iterator ix = upperleft.rowIterator();
    
    Accessor accessor;
    Functor f;
    
    accessor.set(f(), ix); 

This function can be used to init a region-of-interest of the image. It uses an accessor to access the pixel data.

The initial value can either be a constant of appropriate type (compatible with the destination's value_type), or a functor with compatible result_type. These two cases are automatically distinguished when FunctorTraits<FUNCTOR>::isInitializer yields VigraTrueType. Since the functor is passed by const reference, its operator() must be const, and its internal state may need to be mutable.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class ImageIterator, class Accessor, 
                  class MaskImageIterator, class MaskAccessor,
                  class VALUETYPE>
        void initImageIf(ImageIterator upperleft, ImageIterator lowerright, Accessor a,
                         MaskImageIterator mask_upperleft, MaskAccessor ma,
                         VALUETYPE const & v);

        template <class ImageIterator, class Accessor, 
                  class MaskImageIterator, class MaskAccessor,
                  class FUNCTOR>
        void initImageIf(ImageIterator upperleft, ImageIterator lowerright, Accessor a,
                         MaskImageIterator mask_upperleft, MaskAccessor ma,
                         FUNCTOR const & v);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class ImageIterator, class Accessor, 
                  class MaskImageIterator, class MaskAccessor,
                  class VALUETYPE>
        void initImageIf(triple<ImageIterator, ImageIterator, Accessor> img, 
                         pair<MaskImageIterator, MaskAccessor> mask,
                         VALUETYPE const & v);

        template <class ImageIterator, class Accessor, 
                  class MaskImageIterator, class MaskAccessor,
                  class FUNCTOR>
        void initImageIf(triple<ImageIterator, ImageIterator, Accessor> img, 
                         pair<MaskImageIterator, MaskAccessor> mask,
                         FUNCTOR const & v);
    }

Usage:

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

    vigra::BImage img(100, 100);
    vigra::BImage mask(100, 100);
    
    // zero the ROI
    vigra::initImageIf(destImageRange(img), 
                maskImage(mask),
                vigra::NumericTraits<vigra::BImage::PixelType>::zero());

Required Interface:

    ImageIterator upperleft, lowerright;
    MaskImageIterator mask_upperleft;
    ImageIterator::row_iterator ix = upperleft.rowIterator();
    MaskImageIterator::row_iterator mx = mask_upperleft.rowIterator();
    
    Accessor accessor;
    MaskAccessor mask_accessor;
    VALUETYPE v;
    
    if(mask_accessor(mx)) accessor.set(v, ix); 

A pixel is initialized if its distance to the border is at most 'borderwidth'. It uses an accessor to access the pixel data.

The initial value can either be a constant of appropriate type (compatible with the destination's value_type), or a functor with compatible result_type. These two cases are automatically distinguished when FunctorTraits<FUNCTOR>::isInitializer yields VigraTrueType. Since the functor is passed by const reference, its operator() must be const, and its internal state may need to be mutable.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class ImageIterator, class Accessor, class VALUETYPE>
        void initImageBorder(ImageIterator upperleft, ImageIterator lowerright, Accessor a,
                             int border_width, VALUETYPE const & v);

        template <class ImageIterator, class Accessor, class FUNCTOR>
        void initImageBorder(ImageIterator upperleft, ImageIterator lowerright, Accessor a,
                             int border_width, FUNCTOR const & v);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class ImageIterator, class Accessor, class VALUETYPE>
        void initImageBorder(triple<ImageIterator, ImageIterator, Accessor> img, 
                             int border_width, VALUETYPE const & v);

        template <class ImageIterator, class Accessor, class FUNCTOR>
        void initImageBorder(triple<ImageIterator, ImageIterator, Accessor> img, 
                             int border_width, FUNCTOR const & v);
    }

Usage:

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

    vigra::BImage img(100, 100);
    
    // zero a border of 5 pixel
    vigra::initImageBorder(destImageRange(img),
                    5, vigra::NumericTraits<vigra::BImage::PixelType>::zero());

Required Interface:

see initImage()

This function can be used to collect statistics of the image etc. The results must be stored in the functor, which serves as a return value. The function uses an accessor to access the pixel data.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class ImageIterator, class Accessor, class Functor>
        void
        inspectImage(ImageIterator upperleft, ImageIterator lowerright,
                     Accessor a, Functor & f)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class ImageIterator, class Accessor, class Functor>
        void
        inspectImage(triple<ImageIterator, ImageIterator, Accessor> img,
             Functor & f)
    }

Usage:

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

    // init functor
    vigra::BImage img;

    vigra::FindMinMax<vigra::BImage::PixelType> minmax;

    vigra::inspectImage(srcImageRange(img), minmax);

    cout << "Min: " << minmax.min << " Max: " << minmax.max;

Required Interface:

    ConstImageIterator upperleft, lowerright;
    ConstImageIterator::row_iterator ix = upperleft.rowIterator();

    Accessor accessor;
    Functor functor;

    functor(accessor(ix));         // return not used

This function can be used to collect statistics of the roi etc. The functor is called whenever the return value of the mask's accessor is not zero. The results must be stored in the functor, which serves as a return value. Accessors are used to access the pixel and mask data.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class ImageIterator, class Accessor,
                  class MaskImageIterator, class MaskAccessor, class Functor>
        void
        inspectImageIf(ImageIterator upperleft, ImageIterator lowerright,
               MaskImageIterator mask_upperleft, MaskAccessor ma,
               Functor & f)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class ImageIterator, class Accessor,
              class MaskImageIterator, class MaskAccessor, class Functor>
        void
        inspectImageIf(triple<ImageIterator, ImageIterator, Accessor> img,
               pair<MaskImageIterator, MaskAccessor> mask,
               Functor & f)
    }

Usage:

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

    vigra::BImage img(100, 100);
    vigra::BImage mask(100, 100);

    // init functor
    vigra::FindMinMax<vigra::BImage::PixelType> minmax();

    vigra::inspectImageIf(srcImageRange(img),
                          maskImage(mask), minmax);

    cout << "Min: " << minmax.min << " Max: " << minmax.max;

Required Interface:

    ConstImageIterator upperleft, lowerright;
    MaskImageIterator mask_upperleft;
    ConstImageIterator::row_iterator ix = upperleft.rowIterator();
    MaskImageIterator::row_iterator mx = mask_upperleft.rowIterator();

    Accessor accessor;
    MaskAccessor mask_accessor;

    Functor functor;

    if(mask_accessor(mx)) functor(accessor(ix));

This function can be used to collect statistics for each region of a labeled image, especially in conjunction with the ArrayOfRegionStatistics functor. The results must be stored in the functor which serves as a return value. Accessors are used to access the pixel data.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class ImageIterator1, class Accessor1,
              class ImageIterator2, class Accessor2,
              class Functor>
        void
        inspectTwoImages(ImageIterator1 upperleft1, ImageIterator1 lowerright1, Accessor1 a1,
                 ImageIterator2 upperleft2, Accessor2 a2,
                 Functor & f)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class ImageIterator1, class Accessor1,
              class ImageIterator2, class Accessor2,
              class Functor>
        void
        inspectTwoImages(triple<ImageIterator1, ImageIterator1, Accessor1> img1,
                         pair<ImageIterator2, Accessor2> img2,
                 Functor & f)
    }

Usage:

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

    vigra::BImage image1;
    vigra::BImage image2;

    SomeStatisticsFunctor stats(...);     // init functor

    vigra::inspectTwoImages(srcImageRange(image1), srcImage(image2),
                            stats);

Required Interface:

    ImageIterator1 upperleft1, lowerright1;
    ImageIterator2 upperleft2;
    ImageIterator1::row_iterator ix1 = upperleft1.rowIterator();
    ImageIterator2::row_iterator ix2 = upperleft2.rowIterator();

    Accessor1 accessor1;
    Accessor2 accessor2;

    Functor functor;
    functor(accessor1(ix1), accessor2(ix2));  // return not used

This function can be used to collect statistics for selected regions of a labeled image, especially in conjunction with the ArrayOfRegionStatistics functor. The results must be stored in the functor which serves as a return value. Accessors are used to access the pixel data.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class ImageIterator1, class Accessor1,
                  class ImageIterator2, class Accessor2,
                  class MaskImageIterator, class MaskAccessor,
                  class Functor>
        void
        inspectTwoImagesIf(ImageIterator1 upperleft1, ImageIterator1 lowerright1, Accessor1 a1,
                         ImageIterator2 upperleft2, Accessor2 a2,
                         MaskImageIterator mupperleft, MaskAccessor mask,
                         Functor & f)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class ImageIterator1, class Accessor1,
                  class ImageIterator2, class Accessor2,
                  class MaskImageIterator, class MaskAccessor,
                  class Functor>
        void
        inspectTwoImagesIf(triple<ImageIterator1, ImageIterator1, Accessor1> img1,
                 pair<ImageIterator2, Accessor2> img2,
                 pair<MaskImageIterator, MaskAccessor> mimg,
                 Functor & f)
    }

Usage:

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

    vigra::BImage image1;
    vigra::BImage image2;
    vigra::BImage maskimage;

    SomeStatisticsFunctor stats(...);     // init functor

    vigra::inspectTwoImagesIf(srcImageRange(image1), srcImage(image2),
                              srcImage(maskimage), region_stats);

Required Interface:

    ImageIterator1 upperleft1, lowerright1;
    ImageIterator2 upperleft2;
    MaskImageIterator upperleftm;
    ImageIterator1::row_iterator ix1 = upperleft1.rowIterator();
    ImageIterator2::row_iterator ix2 = upperleft2.rowIterator();
    MaskImageIterator::row_iterator mx = mupperleft.rowIterator();

    Accessor1 accessor1;
    Accessor2 accessor2;
    MaskAccessor mask;

    Functor functor;
    if(mask(mx))
        functor(accessor1(ix1), accessor2(ix2));

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor, class DestValue>
        void regionImageToCrackEdgeImage(
                       SrcIterator sul, SrcIterator slr, SrcAccessor sa,
                       DestIterator dul, DestAccessor da,
                       DestValue edge_marker)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor, class DestValue>
        void regionImageToCrackEdgeImage(
                   triple<SrcIterator, SrcIterator, SrcAccessor> src,
                   pair<DestIterator, DestAccessor> dest,
                   DestValue edge_marker)
    }

This algorithm inserts border pixels (so called "crack edges") between regions in a labeled image like this (a and c are the original labels, and 0 is the value of edge_marker and denotes the inserted edges):

       original image     insert zero- and one-cells

                                         a 0 c c c
          a c c                          a 0 0 0 c
          a a c               =>         a a a 0 c
          a a a                          a a a 0 0
                                         a a a a a

The algorithm assumes that the original labeled image contains no background. Therefore, it is suitable as a post-processing operation of labelImage() or seededRegionGrowing().

The destination image must be twice the size of the original (precisely, (2*w-1) by (2*h-1) pixels). The source value type (SrcAccessor::value-type) must be equality-comparable.

Usage:

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

    vigra::BImage src(w,h);
    vigra::IImage labels(w,h);
    vigra::IImage cellgrid(2*w-1, 2*h-1);

    // threshold at 128
    vigra::transformImage(srcImageRange(src), destImage(src),
       vigra::Threshold<vigra::BImage::PixelType, vigra::BImage::PixelType>(
                                                    128, 256, 0, 255));

    // find 4-connected regions
    vigra::labelImage(srcImageRange(src), destImage(labels), false);

    // create cell grid image, mark edges with 0
    vigra::regionImageToCrackEdgeImage(srcImageRange(labels), destImage(cellgrid), 0);

Required Interface:

    ImageIterator src_upperleft, src_lowerright;
    ImageIterator dest_upperleft;

    SrcAccessor src_accessor;
    DestAccessor dest_accessor;

    SrcAccessor::value_type u = src_accessor(src_upperleft);

    u != u

    DestValue edge_marker;
    dest_accessor.set(edge_marker, dest_upperleft);

Preconditions:

The destination image must have twice the size of the source:

    w_dest = 2 * w_src - 1
    h_dest = 2 * h_src - 1

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor, class DestValue>
        void regionImageToEdgeImage(
                       SrcIterator sul, SrcIterator slr, SrcAccessor sa,
                       DestIterator dul, DestAccessor da,
                       DestValue edge_marker)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor, class DestValue>
        void regionImageToEdgeImage(
                   triple<SrcIterator, SrcIterator, SrcAccessor> src,
                   pair<DestIterator, DestAccessor> dest,
                   DestValue edge_marker)
    }

This algorithm marks all pixels with the given edge_marker which belong to a different region (label) than their right or lower neighbors:

       original image                     edges
                                 (assuming edge_marker == 1)

          a c c                            1 1 *
          a a c               =>           * 1 1
          a a a                            * * *

The non-edge pixels of the destination image will not be touched. The source value type (SrcAccessor::value-type) must be equality-comparable.

Usage:

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

    vigra::BImage src(w,h);
    vigra::IImage labels(w,h);
    vigra::IImage edges(w, h);
    edges = 255;  // init background (non-edge) to 255

    // threshold at 128
    vigra::transformImage(srcImageRange(src), destImage(src),
      vigra::Threshold<vigra::BImage::PixelType, vigra::BImage::PixelType>(
                                                    128, 256, 0, 255));

    // find 4-connected regions
    vigra::labelImage(srcImageRange(src), destImage(labels), false);

    // create edge image, mark edges with 0
    vigra::regionImageToEdgeImage(srcImageRange(labels), destImage(edges), 0);

Required Interface:

    ImageIterator src_upperleft, src_lowerright;
    ImageIterator dest_upperleft;

    SrcAccessor src_accessor;
    DestAccessor dest_accessor;

    SrcAccessor::value_type u = src_accessor(src_upperleft);

    u != u

    DestValue edge_marker;
    dest_accessor.set(edge_marker, dest_upperleft);

The minima are found only when the have a size of one pixel. Use extendedLocalMinima() to find minimal plateaus. Minima are marked in the destination image with the given marker value (default is 1), all other destination pixels remain unchanged. SrcAccessor::value_type must be less-comparable. A pixel at the image border will never be marked as minimum. Pass vigra::EightNeighborCode or vigra::FourNeighborCode to determine the neighborhood where pixel values are compared. The function uses accessors.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  class DestValue = DestAccessor::value_type,
                  class Neighborhood = EightNeighborCode>
        void
        localMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
                    DestIterator dul, DestAccessor da,
                    DestValue marker = NumericTraits<DestValue>::one(),
                    Neighborhood neighborhood = EightNeighborCode())
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  class DestValue = DestAccessor::value_type,
                  class Neighborhood = EightNeighborCode>
        void
        localMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                    pair<DestIterator, DestAccessor> dest,
                    DestValue marker = NumericTraits<DestValue>::one(),
                    Neighborhood neighborhood = EightNeighborCode())
    }

Usage:

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

    vigra::BImage src(w,h), minima(w,h);

    // init destiniation image
    minima = 0;

    vigra::localMinima(srcImageRange(src), destImage(minima));

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator dest_upperleft;

    SrcAccessor src_accessor;
    DestAccessor dest_accessor;

    SrcAccessor::value_type u = src_accessor(src_upperleft);

    u < u

    DestValue marker;
    dest_accessor.set(marker, dest_upperleft);

The maxima are found only when the have a size of one pixel. Use extendedLocalMaxima() to find maximal plateaus. Maxima are marked in the destination image with the given marker value (default is 1), all other destination pixels remain unchanged. SrcAccessor::value_type must be less-comparable. A pixel at the image border will never be marked as maximum. The function uses accessors.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  class DestValue = DestAccessor::value_type,
                  class Neighborhood = EightNeighborCode>
        void
        localMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
                    DestIterator dul, DestAccessor da,
                    DestValue marker = NumericTraits<DestValue>::one(),
                    Neighborhood neighborhood = EightNeighborCode())
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  class DestValue = DestAccessor::value_type,
                  class Neighborhood = EightNeighborCode>
        void
        localMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                    pair<DestIterator, DestAccessor> dest,
                    DestValue marker = NumericTraits<DestValue>::one(),
                    Neighborhood neighborhood = EightNeighborCode())
    }

Usage:

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

    vigra::BImage src(w,h), maxima(w,h);

    // init destiniation image
    maxima = 0;

    vigra::localMaxima(srcImageRange(src), destImage(maxima));

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator dest_upperleft;

    SrcAccessor src_accessor;
    DestAccessor dest_accessor;

    SrcAccessor::value_type u = src_accessor(src_upperleft);

    u < u

    DestValue marker;
    dest_accessor.set(marker, dest_upperleft);

This function finds regions of uniform pixel value whose neighboring regions are all have smaller values (minimal plateaus of arbitrary size). By default, the pixels in a plateau have exactly identical values. By passing an EqualityFunctor with tolerance, one can allow for plateaus that are not quite constant (this is often necessary with float pixel values). Pass vigra::EightNeighborCode or vigra::FourNeighborCode to determine the neighborhood where pixel values are compared.

Minimal regions are marked in the destination image with the given marker value (default is 1), all other destination pixels remain unchanged. SrcAccessor::value_type must be equality-comparable and less-comparable. A pixel or region touching the image border will never be marked as minimum or minimal plateau. The function uses accessors.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  class DestValue = DestAccessor::value_type,
                  class Neighborhood = EightNeighborCode,
                  class EqualityFunctor = std::equal_to<typename SrcAssessor::value_type> >
        void
        extendedLocalMinima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
                            DestIterator dul, DestAccessor da,
                            DestValue marker = NumericTraits<DestValue>::one(),
                            Neighborhood neighborhood = EightNeighborCode(),
                            EqualityFunctor equal = EqualityFunctor())
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  class DestValue = DestAccessor::value_type,
                  class Neighborhood = EightNeighborCode,
                  class EqualityFunctor = std::equal_to<typename SrcAssessor::value_type> >
        void
        extendedLocalMinima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                            pair<DestIterator, DestAccessor> dest,
                            DestValue marker = NumericTraits<DestValue>::one(),
                            Neighborhood neighborhood = EightNeighborCode(),
                            EqualityFunctor equal = EqualityFunctor())
    }

Usage:

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

    // optional: define an equality functor
    template <class T>
    struct EqualWithToleranceFunctor
    {
        EqualWithToleranceFunctor(T tolerance)
        : t(tolerance)
        {}

        bool operator()(T l, T r) const
        {
            return vigra::abs(l-r) <= t;
        }

        T t;
    };

    vigra::BImage src(w,h), minima(w,h);

    // init destiniation image
    minima.init(0);

    vigra::extendedLocalMinima(srcImageRange(src), destImage(minima));

    // allow plateaus with tolerance
    minima.init(0);
    vigra::extendedLocalMinima(srcImageRange(src), destImage(minima), 1.0,
                               EqualWithToleranceFunctor<unsigned char>(1));

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator dest_upperleft;

    SrcAccessor src_accessor;
    DestAccessor dest_accessor;

    SrcAccessor::value_type u = src_accessor(src_upperleft);

    EqualityFunctor equal;
    u == u
    equal(u, u);
    u < u

    DestValue marker;
    dest_accessor.set(marker, dest_upperleft);

This function finds regions of uniform pixel value whose neighboring regions are all have smaller values (maximal plateaus of arbitrary size). By default, the pixels in a plateau have exactly identical values. By passing an EqualityFunctor with tolerance, one can allow for plateaus that are not quite constant (this is often necessary with float pixel values). Pass vigra::EightNeighborCode or vigra::FourNeighborCode to determine the neighborhood where pixel values are compared.

Maximal regions are marked in the destination image with the given marker value (default is 1), all other destination pixels remain unchanged. SrcAccessor::value_type must be equality-comparable and less-comparable. A pixel or region touching the image border will never be marked as maximum or maximal plateau. The function uses accessors.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  class DestValue = DestAccessor::value_type,
                  class Neighborhood = EightNeighborCode,
                  class EqualityFunctor = std::equal_to<typename SrcAssessor::value_type> >
        void
        extendedLocalMaxima(SrcIterator sul, SrcIterator slr, SrcAccessor sa,
                            DestIterator dul, DestAccessor da,
                            DestValue marker = NumericTraits<DestValue>::one(),
                            Neighborhood neighborhood = EightNeighborCode(),
                            EqualityFunctor equal = EqualityFunctor())
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  class DestValue = DestAccessor::value_type,
                  class Neighborhood = EightNeighborCode,
                  class EqualityFunctor = std::equal_to<typename SrcAssessor::value_type> >
        void
        extendedLocalMaxima(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                            pair<DestIterator, DestAccessor> dest,
                            DestValue marker = NumericTraits<DestValue>::one(),
                            Neighborhood neighborhood = EightNeighborCode(),
                            EqualityFunctor equal = EqualityFunctor())
    }

Usage:

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

    // optional: define an equality functor
    template <class T>
    struct EqualWithToleranceFunctor
    {
        EqualWithToleranceFunctor(T tolerance)
        : t(tolerance)
        {}

        bool operator()(T l, T r) const
        {
            return vigra::abs(l-r) <= t;
        }

        T t;
    };

    vigra::BImage src(w,h), maxima(w,h);

    // init destiniation image
    maxima.init(0);

    vigra::extendedLocalMaxima(srcImageRange(src), destImage(maxima));

    // allow plateaus with tolerance
    maxima.init(0);
    vigra::extendedLocalMaxima(srcImageRange(src), destImage(maxima), 1.0,
                               EqualWithToleranceFunctor<unsigned char>(1));

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator dest_upperleft;

    SrcAccessor src_accessor;
    DestAccessor dest_accessor;

    SrcAccessor::value_type u = src_accessor(src_upperleft);

    EqualityFunctor equal;
    u == u
    equal(u, u);
    u < u

    DestValue marker;
    dest_accessor.set(marker, dest_upperleft);

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).

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);

        // 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);
    }

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);

        // 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);
    }

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());

See also:
vigra::Kernel1D, convolveLine()
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.

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);
    }

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);
    }

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()
This function computes an isotropic convolution of the given multi-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. If the data are anisotropic (different pixel size along different dimensions) you should call separableConvolveMultiArray() directly with the appropriate anisotropic Gaussians.

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);
    }

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);
    }

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);

See also:
separableConvolveMultiArray()
This function computes the Gaussian gradient of the given multi-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. If the data are anisotropic (different pixel size along different dimensions) you should call separableConvolveMultiArray() directly with the appropriate anisotropic Gaussian derivatives.

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);
    }

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);
    }

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);

Required Interface:

see convolveImage(), in addition:

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

See also:
separableConvolveMultiArray()
This function computes the gradient of the given multi-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.

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);
    }

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);
    }

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));

Required Interface:

see convolveImage(), in addition:

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

See also:
convolveMultiArrayOneDimension()
Declarations:

pass arguments explicitly:

    namespace vigra {
        // apply the same kernel to all dimensions
        template <class SrcIterator, class SrcShape, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        separableMultiDistSquared(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
                                    DestIterator diter, DestAccessor dest, bool background);

    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcShape, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        separableMultiDistance(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
                                    pair<DestIterator, DestAccessor> const & dest,
                                    bool background);

    }

This function performs a Euclidean distance squared transform on 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.

This function expects a mask as its source, where background pixels are marked as zero, and non-background pixels as non-zero. If the parameter background is true, then the squared distance of all background pixels to the nearest object is calculated. Otherwise, the distance of all object pixels to the nearest background pixel is calculated.

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 overflow errors (i.e. if typeid(typename DestAccessor::value_type) < N * M*M, where M is the size of the largest dimension of the array.

Usage:

#include <vigra/multi_distance.hxx>

    MultiArray<3, unsigned char>::size_type shape(width, height, depth);
    MultiArray<3, unsigned char> source(shape);
    MultiArray<3, unsigned int> dest(shape);
    ...

    // Calculate Euclidean distance squared for all background pixels 
    separableMultiDistSquared(srcMultiArrayRange(source), destMultiArray(dest), true);

See also:
vigra::distanceTransform()
Declarations:

pass arguments explicitly:

    namespace vigra {
        // apply the same kernel to all dimensions
        template <class SrcIterator, class SrcShape, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        separableMultiDistance(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
                                    DestIterator diter, DestAccessor dest, bool background);

    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcShape, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        separableMultiDistance(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
                                    pair<DestIterator, DestAccessor> const & dest,
                                    bool background);

    }

This function performs a Euclidean distance transform on 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.

This function expects a mask as its source, where background pixels are marked as zero, and non-background pixels as non-zero. If the parameter background is true, then the squared distance of all background pixels to the nearest object is calculated. Otherwise, the distance of all object pixels to the nearest background pixel is calculated.

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 overflow errors (i.e. if typeid(typename DestAccessor::value_type) < N * M*M, where M is the size of the largest dimension of the array.

Usage:

#include <vigra/multi_distance.hxx>

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

    // Calculate Euclidean distance squared for all background pixels 
    separableMultiDistance(srcMultiArrayRange(source), destMultiArray(dest), true);

See also:
vigra::distanceTransform()
This function applies a flat circular erosion operator with a given radius. The operation is isotropic. The input is a binary multi-dimensional array where non-zero pixels represent foreground and zero pixels represent background.

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 overflow errors (i.e. if typeid(typename DestAccessor::value_type) < N * M*M, where M is the size of the largest dimension of the array.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcShape, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        multiBinaryErosion(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
                                    DestIterator diter, DestAccessor dest, int radius);

    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcShape, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        multiBinaryErosion(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
                                    pair<DestIterator, DestAccessor> const & dest, 
                                    int radius);

    }

Usage:

#include <vigra/multi_morphology.hxx>

    MultiArray<3, unsigned char>::size_type shape(width, height, depth);
    MultiArray<3, unsigned char> source(shape);
    MultiArray<3, unsigned char> dest(shape);
    ...

    // perform isotropic binary erosion
    multiBinaryErosion(srcMultiArrayRange(source), destMultiArray(dest), 3);

See also:
vigra::discErosion()
This function applies a flat circular dilation operator with a given radius. The operation is isotropic. The input is a binary multi-dimensional array where non-zero pixels represent foreground and zero pixels represent background.

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 overflow errors (i.e. if typeid(typename DestAccessor::value_type) < N * M*M, where M is the size of the largest dimension of the array.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcShape, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        multiBinaryDilation(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
                                    DestIterator diter, DestAccessor dest, int radius);

    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcShape, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        multiBinaryDilation(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
                                    pair<DestIterator, DestAccessor> const & dest, 
                                    int radius);

    }

Usage:

#include <vigra/multi_morphology.hxx>

    MultiArray<3, unsigned char>::size_type shape(width, height, depth);
    MultiArray<3, unsigned char> source(shape);
    MultiArray<3, unsigned char> dest(shape);
    ...

    // perform isotropic binary erosion
    multiBinaryDilation(srcMultiArrayRange(source), destMultiArray(dest), 3);

See also:
vigra::discDilation()
This function applies a parabolic erosion operator with a given spread (sigma) on a grayscale array. The operation is isotropic. The input is a grayscale multi-dimensional array.

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 overflow errors (i.e. if typeid(typename DestAccessor::value_type) < N * M*M, where M is the size of the largest dimension of the array.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcShape, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        multiGrayscaleErosion(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
                                    DestIterator diter, DestAccessor dest, float sigma);

    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcShape, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        multiGrayscaleErosion(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
                                    pair<DestIterator, DestAccessor> const & dest, 
                                    float sigma);

    }

Usage:

#include <vigra/multi_morphology.hxx>

    MultiArray<3, unsigned char>::size_type shape(width, height, depth);
    MultiArray<3, unsigned char> source(shape);
    MultiArray<3, unsigned char> dest(shape);
    ...

    // perform isotropic grayscale erosion
    multiGrayscaleErosion(srcMultiArrayRange(source), destMultiArray(dest), 3.0);

See also:
vigra::discErosion()
This function applies a parabolic dilation operator with a given spread (sigma) on a grayscale array. The operation is isotropic. The input is a grayscale multi-dimensional array.

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 overflow errors (i.e. if typeid(typename DestAccessor::value_type) < N * M*M, where M is the size of the largest dimension of the array.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcShape, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        multiGrayscaleDilation(SrcIterator siter, SrcShape const & shape, SrcAccessor src,
                                    DestIterator diter, DestAccessor dest, float sigma);

    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcShape, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        multiGrayscaleDilation(triple<SrcIterator, SrcShape, SrcAccessor> const & source,
                                    pair<DestIterator, DestAccessor> const & dest, 
                                    float sigma);

    }

Usage:

#include <vigra/multi_morphology.hxx>

    MultiArray<3, unsigned char>::size_type shape(width, height, depth);
    MultiArray<3, unsigned char> source(shape);
    MultiArray<3, unsigned char> dest(shape);
    ...

    // perform isotropic grayscale erosion
    multiGrayscaleDilation(srcMultiArrayRange(source), destMultiArray(dest), 3.0);

See also:
vigra::discErosion()
This function can be used to init the array which must be represented by a pair of iterators compatible to vigra::MultiIterator. It uses an accessor to access the data alements. Note that the iterator range must be specified by a shape object, because otherwise we could not control the range simultaneously in all dimensions (this is a necessary consequence of the vigra::MultiIterator design).

The initial value can either be a constant of appropriate type (compatible with the destination's value_type), or a functor with compatible result_type. These two cases are automatically distinguished when FunctorTraits<FUNCTOR>::isInitializer yields VigraTrueType. Since the functor is passed by const reference, its operator() must be const, and ist internal state may need to be mutable.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class Iterator, class Shape, class Accessor, class VALUETYPE>
        void
        initMultiArray(Iterator s, Shape const & shape, Accessor a,  VALUETYPE const & v);


        template <class Iterator, class Shape, class Accessor, class FUNCTOR>
        void
        initMultiArray(Iterator s, Shape const & shape, Accessor a,  FUNCTOR const & f);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class Iterator, class Shape, class Accessor, class VALUETYPE>
        void
        initMultiArray(triple<Iterator, Shape, Accessor> const & s, VALUETYPE const & v);


        template <class Iterator, class Shape, class Accessor, class FUNCTOR>
        void
        initMultiArray(triple<Iterator, Shape, Accessor> const & s, FUNCTOR const & f);
    }

Usage:

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

    typedef vigra::MultiArray<3, int> Array;
    Array array(Array::size_type(100, 200, 50));
    
    // zero the array
    vigra::initMultiArray(destMultiArrayRange(array), 0);

Required Interface:

The function accepts either a value that is copied into every destination element:

    MultiIterator begin;
    
    Accessor accessor;
    VALUETYPE v;
    
    accessor.set(v, begin); 

or a functor that is called (without argument) at every location, and the result is written into the current element. Internally, functors are recognized by the meta function FunctorTraits<FUNCTOR>::isInitializer yielding VigraTrueType. Make sure that your functor correctly defines FunctorTraits because otherwise the code will not compile.

    MultiIterator begin;    
    Accessor accessor;
    
    FUNCTOR f;
    assert(typeid(FunctorTraits<FUNCTOR>::isInitializer) == typeid(VigraTrueType));
    
    accessor.set(f(), begin); 

This function can be applied in two modes:

Standard Mode:
If the source and destination arrays have the same size, the corresponding array elements are simply copied. If necessary, type conversion takes place.
Expanding Mode:
If the source array has length 1 along some (or even all) dimensions, the source value at index 0 is used for all destination elements in those dimensions. For example, if we have single row of data (column length is 1), we can copy it into a 2D image of the same width: The given row is automatically repeated for every row of the destination image. Again, type conversion os performed if necessary.

The arrays must be represented by iterators compatible with vigra::MultiIterator, and the iteration range is specified by means of shape objects. If only the source shape is given the destination array is assumed to have the same shape, and standard mode is applied. If two shapes are given, the size of corresponding dimensions must be either equal (standard copy), or the source length must be 1 (expanding copy). The function uses accessors to access the data elements.

Declarations:

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

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcShape, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        copyMultiArray(SrcIterator s, 
                       SrcShape const & shape, SrcAccessor src,
                       DestIterator d, DestAccessor dest);


        template <class SrcIterator, class SrcShape, class SrcAccessor,
                  class DestIterator, class DestShape, class DestAccessor>
        void
        copyMultiArray(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
                       DestIterator d, DestShape const & dshape, DestAccessor dest);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcShape, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        copyMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
                       pair<DestIterator, DestAccessor> const & dest);
                       
                       
        template <class SrcIterator, class SrcShape, class SrcAccessor,
                  class DestIterator, class DestShape, class DestAccessor>
        void
        copyMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
                       triple<DestIterator, DestShape, DestAccessor> const & dest);
    }

Usage - Standard Mode:

    typedef vigra::MultiArray<3, int> Array;
    Array src(Array::size_type(100, 200, 50)),
          dest(Array::size_type(100, 200, 50));
    ...
    
    vigra::copyMultiArray(srcMultiArrayRange(src), destMultiArray(dest));

Usage - Expanding Mode:

The source array is only 2D (it has depth 1). Thus, the destination will contain 50 identical copies of this image. Note that the destination shape must be passed to the algorithm for the expansion to work, so we use destMultiArrayRange() rather than destMultiArray().

    typedef vigra::MultiArray<3, int> Array;
    Array src(Array::size_type(100, 200, 1)),
          dest(Array::size_type(100, 200, 50));
    ...
    
    vigra::copyMultiArray(srcMultiArrayRange(src), destMultiArrayRange(dest));

Required Interface:

    MultiIterator src_begin, dest_begin;
    
    SrcAccessor src_accessor;
    DestAccessor dest_accessor;

    dest_accessor.set(src_accessor(src_begin), dest_begin);

This function can be applied in three modes:

Standard Mode:
If the source and destination arrays have the same size, the transformation given by the functor is applied to every source element and the result written into the corresponding destination element. Unary functions, unary functors from the STL and the functors specifically defined in Functors to Transform Images can be used in standard mode. Creation of new functors is easiest by using Functor Expressions.
Expanding Mode:
If the source array has length 1 along some (or even all) dimensions, the source value at index 0 is used for all destination elements in those dimensions. In other words, the source index is not incremented along these dimensions, but the transformation functor is applied as usual. So, we can expand a small array (e.g. a single row of data, column length is 1), into a larger one (e.g. a 2D image with the same width): the given values are simply reused as necessary (e.g. for every row of the destination image). The same functors as in standard mode can be applied.
Reducing Mode:
If the destination array has length 1 along some (or even all) dimensions, the source values in these dimensions are reduced to single values by means of a suitable functor (e.g. vigra::ReduceFunctor), which supports two function call operators: one with a single argument to collect the values, and without argument to obtain the final (reduced) result. This behavior is a multi-dimensional generalization of the C++ standard function std::accumulate().

The arrays must be represented by iterators compatible with vigra::MultiIterator, and the iteration range is specified by means of shape objects. If only the source shape is given the destination array is assumed to have the same shape, and standard mode is applied. If two shapes are given, the size of corresponding dimensions must be either equal (standard copy), or the source length must be 1 (expand mode), or the destination length must be 1 (reduce mode). However, reduction and expansion cannot be executed at the same time, so the latter conditions are mutual exclusive, even if they apply to different dimensions.

The function uses accessors to access the data elements.

Declarations:

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

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcShape, class SrcAccessor,
                  class DestIterator, class DestAccessor, 
                  class Functor>
        void
        transformMultiArray(SrcIterator s, SrcShape const & shape, SrcAccessor src,
                            DestIterator d, DestAccessor dest, Functor const & f);


        template <class SrcIterator, class SrcShape, class SrcAccessor,
                  class DestIterator, class DestShape, class DestAccessor, 
                  class Functor>
        void
        transformMultiArray(SrcIterator s, SrcShape const & sshape, SrcAccessor src,
                            DestIterator d, DestShape const & dshape, DestAccessor dest, 
                            Functor const & f);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcShape, class SrcAccessor,
                  class DestIterator, class DestAccessor, 
                  class Functor>
        void
        transformMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
                            pair<DestIterator, DestAccessor> const & dest, Functor const & f);


        template <class SrcIterator, class SrcShape, class SrcAccessor,
                  class DestIterator, class DestShape, class DestAccessor, 
                  class Functor>
        void
        transformMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & src,
                            triple<DestIterator, DestShape, DestAccessor> const & dest, 
                            Functor const & f)
    }

Usage - Standard Mode:

Source and destination array have the same size.

    #include <cmath>         // for sqrt()

    typedef vigra::MultiArray<3, float> Array;
    Array src(Array::size_type(100, 200, 50)),
          dest(Array::size_type(100, 200, 50));
    ...
    
    vigra::transformMultiArray(srcMultiArrayRange(src),
                               destMultiArray(dest),
                               (float(*)(float))&std::sqrt );

Usage - Expand Mode:

The source array is only 2D (it has depth 1). Thus, the destination will contain 50 identical copies of the transformed source array. Note that the destination shape must be passed to the algorithm for the expansion to work, so we use destMultiArrayRange() rather than destMultiArray().

    #include <cmath>         // for sqrt()

    typedef vigra::MultiArray<3, float> Array;
    Array src(Array::size_type(100, 200, 1)),
          dest(Array::size_type(100, 200, 50));
    ...
    
    vigra::transformMultiArray(srcMultiArrayRange(src),
                               destMultiArrayRange(dest),
                               (float(*)(float))&std::sqrt );

Usage - Reduce Mode:

The destination array is only 1D (it's width and height are 1). Thus, it will contain accumulated data for every slice of the source volume (or for every frame, if the source is intepreted as an image sequence). In the example, we use the functor vigra::FindAverage to calculate the average gray value of every slice. Note that the destination shape must also be passed for the reduction to work, so we use destMultiArrayRange() rather than destMultiArray().

    typedef vigra::MultiArray<3, float> Array;
    Array src(Array::size_type(100, 200, 50)),
          dest(Array::size_type(1, 1, 50));
    ...
    
    vigra::transformMultiArray(srcMultiArrayRange(src),
                               destMultiArrayRange(dest),
                               vigra::FindAverage<float>() );

Required Interface:

In standard and expand mode, the functor must be a model of UnaryFunction (i.e. support function call with one argument and a return value res = functor(arg)):

    MultiIterator src_begin, src_end, dest_begin;
    
    SrcAccessor src_accessor;
    DestAccessor dest_accessor;
    Functor functor;

    dest_accessor.set(functor(src_accessor(src_begin)), dest_begin);

In reduce mode, it must be a model of UnaryAnalyser (i.e. support function call with one argument and no return vakue functor(arg)) and Initializer (i.e. support function call with no argument, but return value res = functor()). Internally, such functors are recognized by the meta functions FunctorTraits<FUNCTOR>::isUnaryAnalyser and FunctorTraits<FUNCTOR>::isInitializer which must both yield VigraTrueType. Make sure that your functor correctly defines FunctorTraits because otherwise reduce mode will not work. In addition, the functor must be copy constructible in order to start each reduction with a fresh functor.

    MultiIterator src_begin, src_end, dest_begin;
    
    SrcAccessor src_accessor;
    DestAccessor dest_accessor;
    
    FUNCTOR initial_functor, functor(initial_functor);
    assert(typeid(FunctorTraits<FUNCTOR>::isInitializer) == typeid(VigraTrueType));
    assert(typeid(FunctorTraits<FUNCTOR>::isUnaryAnalyser) == typeid(VigraTrueType));
    
    functor(src_accessor(src_begin));
    dest_accessor.set(functor(), dest_begin);

This function can be applied in three modes:

Standard Mode:
If the source and destination arrays have the same size, the transformation given by the functor is applied to every pair of corresponding source elements and the result written into the corresponding destination element. Binary functions, binary functors from the STL and the functors specifically defined in Functors to Combine Images can be used in standard mode. Creation of new functors is easiest by using Functor Expressions.
Expanding Mode:
If the source arrays have length 1 along some (or even all) dimensions, the source values at index 0 are used for all destination elements in those dimensions. In other words, the source index is not incremented along those dimensions, but the transformation functor is applied as usual. So, we can expand small arrays (e.g. a single row of data, column length is 1), into larger ones (e.g. a 2D image with the same width): the given values are simply reused as necessary (e.g. for every row of the destination image). It is not even necessary that the source array shapes are equal. For example, we can combine a small array with one that hase the same size as the destination array. The same functors as in standard mode can be applied.
Reducing Mode:
If the destination array has length 1 along some (or even all) dimensions, the source values in these dimensions are reduced to single values by means of a suitable functor which supports two function call operators: one with two arguments to collect the values, and one without argument to obtain the final (reduced) result. This behavior is a multi-dimensional generalization of the C++ standard function std::accumulate().

The arrays must be represented by iterators compatible with vigra::MultiIterator, and the iteration range is specified by means of shape objects. If only a single source shape is given the destination array is assumed to have the same shape, and standard mode is applied. If three shapes are given, the size of corresponding dimensions must be either equal (standard copy), or the length of this dimension must be 1 in one or both source arrays (expand mode), or the destination length must be 1 (reduce mode). However, reduction and expansion cannot be executed at the same time, so the latter conditions are mutual exclusive, even if they apply to different dimensions.

The function uses accessors to access the data elements.

Declarations:

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

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator1, class SrcShape, class SrcAccessor1,
                  class SrcIterator2, class SrcAccessor2,
                  class DestIterator, class DestAccessor, 
                  class Functor>
        void combineTwoMultiArrays(
                       SrcIterator1 s1, SrcShape const & shape, SrcAccessor1 src1,
                       SrcIterator2 s2, SrcAccessor2 src2,
                       DestIterator d, DestAccessor dest, Functor const & f);


        template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
                  class SrcIterator2, class SrcShape2, class SrcAccessor2,
                  class DestIterator, class DestShape, class DestAccessor, 
                  class Functor>
        void combineTwoMultiArrays(
                       SrcIterator1 s1, SrcShape1 const & sshape1, SrcAccessor1 src1,
                       SrcIterator2 s2, SrcShape2 const & sshape2, SrcAccessor2 src2,
                       DestIterator d, DestShape const & dshape, DestAccessor dest, 
                       Functor const & f);
            }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator1, class SrcShape, class SrcAccessor1,
                  class SrcIterator2, class SrcAccessor2,
                  class DestIterator, class DestAccessor, class Functor>
        void combineTwoMultiArrays(
                       triple<SrcIterator1, SrcShape, SrcAccessor1> const & src1,
                       pair<SrcIterator2, SrcAccessor2> const & src2,
                       pair<DestIterator, DestAccessor> const & dest, Functor const & f);


        template <class SrcIterator1, class SrcShape1, class SrcAccessor1,
                  class SrcIterator2, class SrcShape2, class SrcAccessor2,
                  class DestIterator, class DestShape, class DestAccessor, 
                  class Functor>
        void combineTwoMultiArrays(
                       triple<SrcIterator1, SrcShape1, SrcAccessor1> const & src1,
                       triple<SrcIterator2, SrcShape2, SrcAccessor2> const & src2,
                       triple<DestIterator, DestShape, DestAccessor> const & dest, 
                       Functor const & f);
    }

Usage - Standard Mode:

Source and destination arrays have the same size.

    #include <functional>     // for std::plus

    typedef vigra::MultiArray<3, int> Array;
    Array src1(Array::size_type(100, 200, 50)),
          src2(Array::size_type(100, 200, 50)),
          dest(Array::size_type(100, 200, 50));
    ...
    
    vigra::combineTwoMultiArrays(
                srcMultiArrayRange(src1), 
                srcMultiArray(src2), 
                destMultiArray(dest),  
                std::plus<int>());

Usage - Expand Mode:

One source array is only 2D (it has depth 1). This image will be added to every slice of the other source array, and the result if written into the corresponding destination slice. Note that the shapes of all arrays must be passed to the algorithm, so we use srcMultiArrayRange() and destMultiArrayRange() rather than srcMultiArray() and destMultiArray().

    #include <functional>     // for std::plus

    typedef vigra::MultiArray<3, int> Array;
    Array src1(Array::size_type(100, 200, 1)),
          src2(Array::size_type(100, 200, 50)),
          dest(Array::size_type(100, 200, 50));
    ...
    
    vigra::combineTwoMultiArrays(
                srcMultiArrayRange(src1), 
                srcMultiArray(src2), 
                destMultiArray(dest),  
                std::plus<int>());

Usage - Reduce Mode:

The destination array is only 1D (it's width and height are 1). Thus, it will contain accumulated data for every slice of the source volumes (or for every frame, if the sources are intepreted as image sequences). In the example, we use vigra::ReduceFunctor together with a functor expression (see Functor Expressions) to calculate the total absolute difference of the gray values in every pair of source slices. Note that the shapes of all arrays must be passed to the algorithm in order for the reduction to work, so we use srcMultiArrayRange() and destMultiArrayRange() rather than srcMultiArray() and destMultiArray().

    #include <vigra/functorexpression.hxx>
    using namespace vigra::functor;
        
    typedef vigra::MultiArray<3, int> Array;
    Array src1(Array::size_type(100, 200, 50)),
          src2(Array::size_type(100, 200, 50)),
          dest(Array::size_type(1, 1, 50));
    ...
    
    vigra::combineTwoMultiArrays(
                srcMultiArrayRange(src1), 
                srcMultiArray(src2), 
                destMultiArray(dest),  
                reduceFunctor(Arg1() + abs(Arg2() - Arg3()), 0) );
                // Arg1() is the sum accumulated so far, initialzed with 0

Required Interface:

In standard and expand mode, the functor must be a model of BinaryFunction (i.e. support function call with two arguments and a return value res = functor(arg1, arg2)):

    MultiIterator src1_begin, src2_begin, dest_begin;
    
    SrcAccessor1 src1_accessor;
    SrcAccessor2 src2_accessor;
    DestAccessor dest_accessor;
    
    Functor functor;

    dest_accessor.set(
          functor(src1_accessor(src1_begin), src2_accessor(src2_begin)), 
          dest_begin);

In reduce mode, it must be a model of BinaryAnalyser (i.e. support function call with two arguments and no return vakue functor(arg1, arg2)) and Initializer (i.e. support function call with no argument, but return value res = functor()). Internally, such functors are recognized by the meta functions FunctorTraits<FUNCTOR>::isBinaryAnalyser and FunctorTraits<FUNCTOR>::isInitializer which must both yield VigraTrueType. Make sure that your functor correctly defines FunctorTraits because otherwise reduce mode will not work. In addition, the functor must be copy constructible in order to start each reduction with a fresh functor.

    MultiIterator src1_begin, src2_begin, dest_begin;
    
    SrcAccessor1 src1_accessor;
    SrcAccessor2 src2_accessor;
    DestAccessor dest_accessor;
    
    FUNCTOR initial_functor, functor(initial_functor);
    assert(typeid(FunctorTraits<FUNCTOR>::isInitializer) == typeid(VigraTrueType));
    assert(typeid(FunctorTraits<FUNCTOR>::isBinaryAnalyser) == typeid(VigraTrueType));
    
    functor(src1_accessor(src1_begin), src2_accessor(src2_begin));
    dest_accessor.set(functor(), dest_begin);

Except for the fact that it operates on three input arrays, this function is identical to combineTwoMultiArrays().

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator1, class SrcShape, class SrcAccessor1,
                  class SrcIterator2, class SrcAccessor2,
                  class SrcIterator3, class SrcAccessor3,
                  class DestIterator, class DestAccessor, 
                  class Functor>
        void
        combineThreeMultiArrays(SrcIterator1 s1, SrcShape const & shape, SrcAccessor1 src1,
                       SrcIterator2 s2, SrcAccessor2 src2,
                       SrcIterator3 s3, SrcAccessor3 src3,
                       DestIterator d, DestAccessor dest, Functor const & f);
                    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator1, class SrcShape, class SrcAccessor1,
                  class SrcIterator2, class SrcAccessor2,
                  class SrcIterator3, class SrcAccessor3,
                  class DestIterator, class DestAccessor, 
                  class Functor>
        inline void
        combineThreeMultiArrays(triple<SrcIterator1, SrcShape, SrcAccessor1> const & src1,
                       pair<SrcIterator2, SrcAccessor2> const & src2,
                       pair<SrcIterator3, SrcAccessor3> const & src3,
                       pair<DestIterator, DestAccessor> const & dest, Functor const & f);
    }

Usage:

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

    #include <functional>     // for plus

    typedef vigra::MultiArray<3, int> Array;
    Array src1(Array::size_type(100, 200, 50)),
          src2(Array::size_type(100, 200, 50)),
          src3(Array::size_type(100, 200, 50)),
          dest(Array::size_type(100, 200, 50));
    ...
    
    vigra::combineThreeMultiArrays(
                srcMultiArrayRange(src1), 
                srcMultiArray(src2), 
                srcMultiArray(src3), 
                destMultiArray(dest),  
                SomeThreeArgumentFunctor());

This function can be used to collect statistics of the array etc. The results must be stored in the functor, which serves as a return value. The arrays must be represented by iterators compatible with vigra::MultiIterator. The function uses an accessor to access the pixel data. Note that the iterator range must be specified by a shape object, because otherwise we could not control the range simultaneously in all dimensions (this is a necessary consequence of the vigra::MultiIterator design).

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class Iterator, class Shape, class Accessor, class Functor>
        void
        inspectMultiArray(Iterator s, Shape const & shape, Accessor a,  Functor & f);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class Iterator, class Shape, class Accessor, class Functor>
        void
        inspectMultiArray(triple<Iterator, Shape, Accessor> const & s, Functor & f);
    }

Usage:

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

    typedef vigra::MultiArray<3, int> Array;
    Array array(Array::size_type(100, 200, 50));

    // init functor
    vigra::FindMinMax<int> minmax;

    vigra::inspectMultiArray(srcMultiArrayRange(array), minmax);

    cout << "Min: " << minmax.min << " Max: " << minmax.max;

Required Interface:

    MultiIterator src_begin;

    Accessor accessor;
    Functor functor;

    functor(accessor(src_begin)); 

This function can be used to collect statistics of the array etc. The results must be stored in the functor, which serves as a return value. The arrays must be represented by iterators compatible with vigra::MultiIterator. The function uses an accessor to access the pixel data. Note that the iterator range must be specified by a shape object, because otherwise we could not control the range simultaneously in all dimensions (this is a necessary consequence of the vigra::MultiIterator design).

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class Iterator1, class Shape, class Accessor1, 
                  class Iterator2, class Accessor2, 
                  class Functor>
        void
        inspectTwoMultiArrays(Iterator1 s1, Shape const & shape, Accessor1 a1,
                              Iterator2 s2, Accessor2 a2, Functor & f);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class Iterator1, class Shape1, class Accessor1, 
                  class Iterator2, class Accessor2, 
                  class Functor>
        void
        inspectTwoMultiArrays(triple<Iterator1, Shape1, Accessor1> const & s1, 
                              pair<Iterator2, Accessor2> const & s2, Functor & f);
    }

Usage:

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

    typedef vigra::MultiArray<3, int> Array;
    Array array1(Array::size_type(100, 200, 50)),
          array2(Array::size_type(100, 200, 50));

    // init functor
    SomeStatisticsFunctor stats(..);

    vigra::inspectTwoMultiArrays(srcMultiArrayRange(array1), srcMultiArray(array2), stats);

Required Interface:

    MultiIterator src1_begin, src2_begin;

    Accessor a1, a2;
    Functor functor;

    functor(a1(src1_begin), a2(src2_begin)); 

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class Shape, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  class Kernel = BSpline<3, double> >
        void
        resizeMultiArraySplineInterpolation(
                              SrcIterator si, Shape const & sshape, SrcAccessor src,
                              DestIterator di, Shape const & dshape, DestAccessor dest,
                              Kernel const & spline = BSpline<3, double>());
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class Shape, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  class Kernel = BSpline<3, double> >
        void
        resizeMultiArraySplineInterpolation(
                              triple<SrcIterator, Shape, SrcAccessor> src,
                              triple<DestIterator, Shape, DestAccessor> dest,
                              Kernel const & spline = BSpline<3, double>());
    }

The function implements separable spline interpolation algorithm described in

M. Unser, A. Aldroubi, M. Eden, "B-Spline Signal Processing" IEEE Transactions on Signal Processing, vol. 41, no. 2, pp. 821-833 (part I), pp. 834-848 (part II), 1993.

to obtain optimal interpolation quality and speed. You may pass the funcion a spline of arbitrary order (e.g. BSpline<ORDER, double> or CatmullRomSpline<double>). The default is a third order spline which gives a twice continuously differentiable interpolant. The implementation ensures that image values are interpolated rather than smoothed by first calling a recursive (sharpening) prefilter as described in the above paper. Then the actual interpolation is done using resamplingConvolveLine().

The range of both the input and output images (resp. regions) must be given. The input image must have a size of at least 4x4, the destination of at least 2x2. The scaling factors are then calculated accordingly. If the source image is larger than the destination, it is smoothed (band limited) using a recursive exponential filter. The source value_type (SrcAccessor::value_type) must be a linear algebra, i.e. it must support addition, subtraction, and multiplication (+, -, *), multiplication with a scalar real number and NumericTraits. The function uses accessors.

Usage:

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

    typedef vigra::MultiArray<3, float>::difference_type Shape;
    vigra::MultiArray<3, float> src(Shape(5, 7, 10)),
                                dest(Shape(9, 13, 19)); // double the size

    // use default cubic spline interpolator
    vigra::resizeMultiArraySplineInterpolation(
               srcMultiArrayRange(src),
               destMultiArrayRange(dest));

Required Interface:

The source and destination iterators must be compatible with vigra::MultiIterator. The array value types must be models of LinearSpace.

This operator applies an algorithm described in

W. Förstner: "Image Preprocessing for Feature Extraction in Digital Intensity, Color and Range Images", Proc. Summer School on Data Analysis and the Statistical Foundations of Geomatics, Lecture Notes in Earth Science, Berlin: Springer, 1999

in order to estimate the noise variance as a function of the image intensity in a robust way, i.e. so that intensity changes due to edges do not bias the estimate. The source value type (SrcAccessor::value_type) must be a scalar type which is convertible to double. The result is written into the result sequence, whose value_type must be constructible from two double values. The following options can be set via the options object (see vigra::NoiseNormalizationOptions for details):

useGradient, windowRadius, noiseEstimationQuantile, noiseVarianceInitialGuess

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor, class BackInsertable>
        void noiseVarianceEstimation(SrcIterator sul, SrcIterator slr, SrcAccessor src,
                                     BackInsertable & result,
                                     NoiseNormalizationOptions const & options = NoiseNormalizationOptions());
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor, class BackInsertable>
        void noiseVarianceEstimation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                                     BackInsertable & result,
                                     NoiseNormalizationOptions const & options = NoiseNormalizationOptions());
    }

Usage:

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

    vigra::BImage src(w,h);
    std::vector<vigra::TinyVector<double, 2> > result;
    
    ...
    vigra::noiseVarianceEstimation(srcImageRange(src), result, 
                                  vigra::NoiseNormalizationOptions().windowRadius(9).noiseVarianceInitialGuess(25.0));
    
    // print the intensity / variance pairs found
    for(int k=0; k<result.size(); ++k)
        std::cout << "Intensity: " << result[k][0] << ", estimated variance: " << result[k][1] << std::endl;

Required Interface:

    SrcIterator upperleft, lowerright;
    SrcAccessor src;
    
    typedef SrcAccessor::value_type SrcType;
    typedef NumericTraits<SrcType>::isScalar isScalar;
    assert(isScalar::asBool == true);
    
    double value = src(uperleft);
    
    BackInsertable result;
    typedef BackInsertable::value_type ResultType;    
    double intensity, variance;
    result.push_back(ResultType(intensity, variance));

This operator first calls noiseVarianceEstimation() to obtain a sequence of intensity/variance pairs, which are then clustered using the median cut algorithm. Then the cluster centers (i.e. average variance vs. average intensity) are determined and returned in the result sequence.

In addition to the options valid for noiseVarianceEstimation(), the following options can be set via the options object (see vigra::NoiseNormalizationOptions for details):

clusterCount, averagingQuantile

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor, class BackInsertable>
        void noiseVarianceClustering(SrcIterator sul, SrcIterator slr, SrcAccessor src,
                                BackInsertable & result,
                                NoiseNormalizationOptions const & options = NoiseNormalizationOptions());
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor, class BackInsertable>
        void noiseVarianceClustering(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                                BackInsertable & result,
                                NoiseNormalizationOptions const & options = NoiseNormalizationOptions());
    }

Usage:

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

    vigra::BImage src(w,h);
    std::vector<vigra::TinyVector<double, 2> > result;
    
    ...
    vigra::noiseVarianceClustering(srcImageRange(src), result, 
                                  vigra::NoiseNormalizationOptions().windowRadius(9).noiseVarianceInitialGuess(25.0).
                                  clusterCount(15));
    
    // print the intensity / variance pairs representing the cluster centers
    for(int k=0; k<result.size(); ++k)
        std::cout << "Cluster: " << k << ", intensity: " << result[k][0] << ", estimated variance: " << result[k][1] << std::endl;

Required Interface:

same as noiseVarianceEstimation()

This function works similar to nonparametricNoiseNormalization() with the exception that the functional dependency of the noise variance from the intensity is given (by a quadratic function) rather than estimated:

    variance = a0 + a1 * intensity + a2 * sq(intensity)

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void quadraticNoiseNormalization(SrcIterator sul, SrcIterator slr, SrcAccessor src,
                                         DestIterator dul, DestAccessor dest,
                                         double a0, double a1, double a2);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void quadraticNoiseNormalization(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                                        pair<DestIterator, DestAccessor> dest,
                                        double a0, double a1, double a2);
    }

Usage:

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

    vigra::BRGBImage src(w,h), dest(w, h);
    
    ...
    vigra::quadraticNoiseNormalization(srcImageRange(src), destImage(dest), 
                                       100, 0.02, 1e-6);

Required Interface:

The source value type must be convertible to double or must be a vector whose elements are convertible to double. Likewise, the destination type must be assignable from double or a vector whose elements are assignable from double.

This function works similar to nonparametricNoiseNormalization() with the exception that the functional dependency of the noise variance from the intensity is given (as a linear function) rather than estimated:

    variance = a0 + a1 * intensity

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void linearNoiseNormalization(SrcIterator sul, SrcIterator slr, SrcAccessor src,
                                      DestIterator dul, DestAccessor dest,
                                      double a0, double a1);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void linearNoiseNormalization(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                                      pair<DestIterator, DestAccessor> dest,
                                      double a0, double a1);
    }

Usage:

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

    vigra::BRGBImage src(w,h), dest(w, h);
    
    ...
    vigra::linearNoiseNormalization(srcImageRange(src), destImage(dest), 
                                    100, 0.02);

Required Interface:

The source value type must be convertible to double or must be a vector whose elements are convertible to double. Likewise, the destination type must be assignable from double or a vector whose elements are assignable from double.

The algorithm solves the non-linear diffusion equation

\[ \frac{\partial}{\partial t} u = \frac{\partial}{\partial x} \left( g(|\nabla u|) \frac{\partial}{\partial x} u \right) \]

where t is the time, x is the location vector, u( x , t) is the smoothed image at time t, and g(.) is the location dependent diffusivity. At time zero, the image u( x , 0) is simply the original image. The time is propotional to the square of the scale parameter: $t = s^2$. The diffusion equation is solved iteratively according to the Additive Operator Splitting Scheme (AOS) from

J. Weickert: "Recursive Separable Schemes for Nonlinear Diffusion Filters", in: B. ter Haar Romeny, L. Florack, J. Koenderingk, M. Viergever (eds.): 1st Intl. Conf. on Scale-Space Theory in Computer Vision 1997, Springer LNCS 1252

DiffusivityFunctor implements the gradient dependent local diffusivity. It is passed as an argument to gradientBasedTransform(). The return value must be between 0 and 1 and determines the weight a pixel gets when its neighbors are smoothed. Weickert recommends the use of the diffusivity implemented by class DiffusivityFunctor. It's also possible to use other functors, for example one that always returns 1, in which case we obtain the solution to the linear diffusion equation, i.e. Gaussian convolution.

The source value type must be a linear space with internal addition, scalar multiplication, and NumericTraits defined. The value_type of the DiffusivityFunctor must be the scalar field over wich the source value type's linear space is defined.

In addition to nonlinearDiffusion(), there is an algorithm nonlinearDiffusionExplicit() which implements the Explicit Scheme described in the above article. Both algorithms have the same interface, but the explicit scheme gives slightly more accurate approximations of the diffusion process at the cost of much slower processing.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  class DiffusivityFunctor>
        void nonlinearDiffusion(SrcIterator sul, SrcIterator slr, SrcAccessor as,
                                DestIterator dul, DestAccessor ad,
                                DiffusivityFunctor const & weight, double scale);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  class DiffusivityFunctor>
        void nonlinearDiffusion(
                  triple<SrcIterator, SrcIterator, SrcAccessor> src,
                  pair<DestIterator, DestAccessor> dest,
                  DiffusivityFunctor const & weight, double scale);
    }

Usage:

#include <vigra/nonlineardiffusion.hxx>

    FImage src(w,h), dest(w,h);
    float edge_threshold, scale;
    ...
    
    nonlinearDiffusion(srcImageRange(src), destImage(dest),
                       DiffusivityFunctor<float>(edge_threshold), scale);

Required Interface:

Precondition:

scale > 0

This function implements anisotropic tensor smoothing by an hourglass-shaped filters as described in

U. Köthe: "Edge and Junction Detection with an Improved Structure Tensor", in: Proc. of 25th DAGM Symposium, Magdeburg 2003, Lecture Notes in Computer Science 2781, pp. 25-32, Heidelberg: Springer, 2003

It is closely related to the structure tensor (see structureTensor()), but replaces the linear tensor smoothing with a smoothing along edges only. Smoothing accross edges is largely suppressed. This means that the image structure is preserved much better because nearby features such as parallel edges are not blended into each other.

The hourglass filter is typically applied to a gradient tensor, i.e. the Euclidean product of the gradient with itself, which can be obtained by a gradient operator followed with vectorToTensor(), see example below. The hourglass shape of the filter can be interpreted as indicating the likely continuations of a local edge element. The parameter sigma determines the radius of the hourglass (i.e. how far the influence of the edge element reaches), and rho controls its opening angle (i.e. how narrow the edge orientation os followed). Recommended values are sigma = 1.4 (or, more generally, two to three times the scale of the gradient operator used in the first step), and rho = 0.4 which corresponds to an opening angle of 22.5 degrees to either side of the edge.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void hourGlassFilter(SrcIterator sul, SrcIterator slr, SrcAccessor src,
                             DestIterator dul, DestAccessor dest,
                             double sigma, double rho);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        inline
        void hourGlassFilter(triple<SrcIterator, SrcIterator, SrcAccessor> s,
                             pair<DestIterator, DestAccessor> d,
                             double sigma, double rho);
    }

Usage:

#include <vigra/orientedtensorfilters.hxx>

    FImage img(w,h);
    FVector2Image gradient(w,h);
    FVector3Image tensor(w,h), smoothedTensor(w,h);
    
    gaussianGradient(srcImageRange(img), destImage(gradient), 1.0);
    vectorToTensor(srcImageRange(gradient), destImage(tensor));
    hourGlassFilter(srcImageRange(tensor), destImage(smoothedTensor), 2.0, 0.4);

See also:
vectorToTensor()
The function performs a causal and an anti-causal first or second order recursive filtering with the given filter parameter b1 and border treatment border (first order filter, b2 = 0) or parameters b1, b2 and BORDER_TREATMENT_REFLECT (second order filter). Thus, the result is always a filtering with linear phase.

\[ \begin{array}{rcl} a_{i, causal} & = & source_i + b1 * a_{i-1, causal} + b2 * a_{i-2, causal} \\ a_{i, anticausal} & = & source_i + b1 * a_{i+1, anticausal} + b2 * a_{i+2, anticausal} \\ dest_i & = & \frac{1 - b1 - b2}{1 + b1 + b2}(a_{i, causal} + a_{i, anticausal} - source_i) \end{array} \]

The signal's value_type (SrcAccessor::value_type) must be a linear space over double, i.e. addition of source values, multiplication with double, and NumericTraits must be defined.

Declaration:

First order recursive filter:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
              class DestIterator, class DestAccessor>
        void recursiveFilterLine(SrcIterator is, SrcIterator isend, SrcAccessor as,
                     DestIterator id, DestAccessor ad, 
                     double b1, BorderTreatmentMode border)
    }

Second order recursive filter:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
              class DestIterator, class DestAccessor>
        void recursiveFilterLine(SrcIterator is, SrcIterator isend, SrcAccessor as,
                     DestIterator id, DestAccessor ad, 
                     double b1, double b2)
    }

Usage:

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

    vector<float> src, dest;    
    ...
    
    vigra::DefaultAccessor<vector<float>::iterator, float> FAccessor;
    
    
    vigra::recursiveFilterLine(src.begin(), src.end(), FAccessor(), 
                               dest.begin(), FAccessor(), 
                               0.5, BORDER_TREATMENT_REFLECT);

Required Interface:

    RandomAccessIterator is, isend;
    RandomAccessIterator id;
    
    SrcAccessor src_accessor;
    DestAccessor dest_accessor;
    
    NumericTraits<SrcAccessor::value_type>::RealPromote s = src_accessor(is);
    double d;
    
    s = s + s;
    s = d * s;

    dest_accessor.set(
        NumericTraits<DestAccessor::value_type>::fromRealPromote(s), id);

Preconditions:

    -1 < b  < 1

This function calls recursiveFilterLine() with b = exp(-1.0/scale) and border = BORDER_TREATMENT_REPEAT. See recursiveFilterLine() for more documentation.

Declaration:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
              class DestIterator, class DestAccessor>
        void recursiveSmoothLine(SrcIterator is, SrcIterator isend, SrcAccessor as,
                     DestIterator id, DestAccessor ad, double scale)
    }

Usage:

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

    vector<float> src, dest;    
    ...
    
    vigra::DefaultAccessor<vector<float>::iterator, float> FAccessor;
    
    
    vigra::recursiveSmoothLine(src.begin(), src.end(), FAccessor(), 
                        dest.begin(), FAccessor(), 3.0);

Required Interface:

    RandomAccessIterator is, isend;
    RandomAccessIterator id;
    
    SrcAccessor src_accessor;
    DestAccessor dest_accessor;
    
    NumericTraits<SrcAccessor::value_type>::RealPromote s = src_accessor(is);
    double d;
    
    s = s + s;
    s = d * s;

    dest_accessor.set(
        NumericTraits<DestAccessor::value_type>::fromRealPromote(s), id);

Preconditions:

    scale > 0

It uses the first derivative an exponential d/dx exp(-abs(x)/scale) as a kernel. The signal's value_type (SrcAccessor::value_type) must be a linear space over double, i.e. addition and subtraction of source values, multiplication with double, and NumericTraits must be defined. Border treatment is always BORDER_TREATMENT_REPEAT.

Declaration:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
              class DestIterator, class DestAccessor>
        void recursiveFirstDerivativeLine(SrcIterator is, SrcIterator isend, SrcAccessor as,
                     DestIterator id, DestAccessor ad, double scale)
    }

Usage:

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

    vector<float> src, dest;    
    ...
    
    vigra::DefaultAccessor<vector<float>::iterator, float> FAccessor;
    
    
    vigra::recursiveFirstDerivativeLine(src.begin(), src.end(), FAccessor(), 
                        dest.begin(), FAccessor(), 3.0);

Required Interface:

    RandomAccessIterator is, isend;
    RandomAccessIterator id;
    
    SrcAccessor src_accessor;
    DestAccessor dest_accessor;
    
    NumericTraits<SrcAccessor::value_type>::RealPromote s = src_accessor(is);
    double d;
    
    s = s + s;
    s = -s;
    s = d * s;

    dest_accessor.set(
        NumericTraits<DestAccessor::value_type>::fromRealPromote(s), id);

Preconditions:

    scale > 0

It uses the second derivative an exponential d2/dx2 exp(-abs(x)/scale) as a kernel. The signal's value_type (SrcAccessor::value_type) must be a linear space over double, i.e. addition and subtraction of source values, multiplication with double, and NumericTraits must be defined. Border treatment is always BORDER_TREATMENT_REPEAT.

Declaration:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
              class DestIterator, class DestAccessor>
        void recursiveSecondDerivativeLine(SrcIterator is, SrcIterator isend, SrcAccessor as,
                     DestIterator id, DestAccessor ad, double scale)
    }

Usage:

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

    vector<float> src, dest;    
    ...
    
    vigra::DefaultAccessor<vector<float>::iterator, float> FAccessor;
    
    
    vigra::recursiveSecondDerivativeLine(src.begin(), src.end(), FAccessor(), 
                        dest.begin(), FAccessor(), 3.0);

Required Interface:

    RandomAccessIterator is, isend;
    RandomAccessIterator id;
    
    SrcAccessor src_accessor;
    DestAccessor dest_accessor;
    
    NumericTraits<SrcAccessor::value_type>::RealPromote s = src_accessor(is);
    double d;
    
    s = s + s;
    s = s - s;
    s = d * s;

    dest_accessor.set(
        NumericTraits<DestAccessor::value_type>::fromRealPromote(s), id);

Preconditions:

    scale > 0

It calls recursiveFilterLine() for every row of the image. See recursiveFilterLine() for more information about required interfaces and vigra_preconditions.

Declarations:

pass arguments explicitly:

    namespace vigra {
        // first order filter
        template <class SrcImageIterator, class SrcAccessor,
                  class DestImageIterator, class DestAccessor>
        void recursiveFilterX(SrcImageIterator supperleft, 
                               SrcImageIterator slowerright, SrcAccessor as,
                               DestImageIterator dupperleft, DestAccessor ad, 
                               double b, BorderTreatmentMode border);

        // second order filter
        template <class SrcImageIterator, class SrcAccessor,
                  class DestImageIterator, class DestAccessor>
        void recursiveFilterX(SrcImageIterator supperleft, 
                               SrcImageIterator slowerright, SrcAccessor as,
                               DestImageIterator dupperleft, DestAccessor ad, 
                               double b1, double b2);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        // first order filter
        template <class SrcImageIterator, class SrcAccessor,
                  class DestImageIterator, class DestAccessor>
        void recursiveFilterX(
                    triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
                    pair<DestImageIterator, DestAccessor> dest, 
                    double b, BorderTreatmentMode border);

        // second order filter
        template <class SrcImageIterator, class SrcAccessor,
                  class DestImageIterator, class DestAccessor>
        void recursiveFilterX(
                    triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
                    pair<DestImageIterator, DestAccessor> dest, 
                    double b1, double b2);
            }

Usage:

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

    vigra::FImage src(w,h), dest(w,h);    
    ...
    
    vigra::recursiveSmoothX(srcImageRange(src), destImage(dest), 
           0.5, BORDER_TREATMENT_REFLECT);

It calls recursiveSmoothLine() for every row of the image. See recursiveSmoothLine() for more information about required interfaces and vigra_preconditions.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
              class DestImageIterator, class DestAccessor>
        void recursiveSmoothX(SrcImageIterator supperleft, 
                  SrcImageIterator slowerright, SrcAccessor as,
                  DestImageIterator dupperleft, DestAccessor ad, 
                  double scale)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
              class DestImageIterator, class DestAccessor>
        void recursiveSmoothX(
            triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
            pair<DestImageIterator, DestAccessor> dest, 
            double scale)
    }

Usage:

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

    vigra::FImage src(w,h), dest(w,h);    
    ...
    
    vigra::recursiveSmoothX(srcImageRange(src), destImage(dest), 3.0);

It calls recursiveFilterLine() for every column of the image. See recursiveFilterLine() for more information about required interfaces and vigra_preconditions.

Declarations:

pass arguments explicitly:

    namespace vigra {
        // first order filter
        template <class SrcImageIterator, class SrcAccessor,
                  class DestImageIterator, class DestAccessor>
        void recursiveFilterY(SrcImageIterator supperleft, 
                               SrcImageIterator slowerright, SrcAccessor as,
                               DestImageIterator dupperleft, DestAccessor ad, 
                               double b, BorderTreatmentMode border);

        // second order filter
        template <class SrcImageIterator, class SrcAccessor,
                  class DestImageIterator, class DestAccessor>
        void recursiveFilterY(SrcImageIterator supperleft, 
                               SrcImageIterator slowerright, SrcAccessor as,
                               DestImageIterator dupperleft, DestAccessor ad, 
                               double b1, double b2);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        // first order filter
        template <class SrcImageIterator, class SrcAccessor,
                  class DestImageIterator, class DestAccessor>
        void recursiveFilterY(
                    triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
                    pair<DestImageIterator, DestAccessor> dest, 
                    double b, BorderTreatmentMode border);

        // second order filter
        template <class SrcImageIterator, class SrcAccessor,
                  class DestImageIterator, class DestAccessor>
        void recursiveFilterY(
                    triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
                    pair<DestImageIterator, DestAccessor> dest, 
                    double b1, double b2);
            }

Usage:

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

    vigra::FImage src(w,h), dest(w,h);    
    ...
    
    vigra::recursiveFilterY(srcImageRange(src), destImage(dest), -0.6, -0.06);

It calls recursiveSmoothLine() for every column of the image. See recursiveSmoothLine() for more information about required interfaces and vigra_preconditions.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
              class DestImageIterator, class DestAccessor>
        void recursiveSmoothY(SrcImageIterator supperleft, 
                  SrcImageIterator slowerright, SrcAccessor as,
                  DestImageIterator dupperleft, DestAccessor ad, 
                  double scale)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
              class DestImageIterator, class DestAccessor>
        void recursiveSmoothY(
            triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
            pair<DestImageIterator, DestAccessor> dest, 
            double scale)
    }

Usage:

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

    vigra::FImage src(w,h), dest(w,h);    
    ...
    
    vigra::recursiveSmoothY(srcImageRange(src), destImage(dest), 3.0);

It calls recursiveFirstDerivativeLine() for every row of the image. See recursiveFirstDerivativeLine() for more information about required interfaces and vigra_preconditions.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
              class DestImageIterator, class DestAccessor>
        void recursiveFirstDerivativeX(SrcImageIterator supperleft, 
                  SrcImageIterator slowerright, SrcAccessor as,
                  DestImageIterator dupperleft, DestAccessor ad, 
                  double scale)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
              class DestImageIterator, class DestAccessor>
        void recursiveFirstDerivativeX(
            triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
            pair<DestImageIterator, DestAccessor> dest, 
            double scale)
    }

Usage:

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

    vigra::FImage src(w,h), dest(w,h);    
    ...
    
    vigra::recursiveFirstDerivativeX(srcImageRange(src), destImage(dest), 3.0);

It calls recursiveFirstDerivativeLine() for every column of the image. See recursiveFirstDerivativeLine() for more information about required interfaces and vigra_preconditions.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
              class DestImageIterator, class DestAccessor>
        void recursiveFirstDerivativeY(SrcImageIterator supperleft, 
                  SrcImageIterator slowerright, SrcAccessor as,
                  DestImageIterator dupperleft, DestAccessor ad, 
                  double scale)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
              class DestImageIterator, class DestAccessor>
        void recursiveFirstDerivativeY(
            triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
            pair<DestImageIterator, DestAccessor> dest, 
            double scale)
    }

Usage:

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

    vigra::FImage src(w,h), dest(w,h);    
    ...
    
    vigra::recursiveFirstDerivativeY(srcImageRange(src), destImage(dest), 3.0);

It calls recursiveSecondDerivativeLine() for every row of the image. See recursiveSecondDerivativeLine() for more information about required interfaces and vigra_preconditions.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
              class DestImageIterator, class DestAccessor>
        void recursiveSecondDerivativeX(SrcImageIterator supperleft, 
                  SrcImageIterator slowerright, SrcAccessor as,
                  DestImageIterator dupperleft, DestAccessor ad, 
                  double scale)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
              class DestImageIterator, class DestAccessor>
        void recursiveSecondDerivativeX(
            triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
            pair<DestImageIterator, DestAccessor> dest, 
            double scale)
    }

Usage:

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

    vigra::FImage src(w,h), dest(w,h);    
    ...
    
    vigra::recursiveSecondDerivativeX(srcImageRange(src), destImage(dest), 3.0);

It calls recursiveSecondDerivativeLine() for every column of the image. See recursiveSecondDerivativeLine() for more information about required interfaces and vigra_preconditions.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
              class DestImageIterator, class DestAccessor>
        void recursiveSecondDerivativeY(SrcImageIterator supperleft, 
                  SrcImageIterator slowerright, SrcAccessor as,
                  DestImageIterator dupperleft, DestAccessor ad, 
                  double scale)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
              class DestImageIterator, class DestAccessor>
        void recursiveSecondDerivativeY(
            triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
            pair<DestImageIterator, DestAccessor> dest, 
            double scale)
    }

Usage:

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

    vigra::FImage src(w,h), dest(w,h);    
    ...
    
    vigra::recursiveSecondDerivativeY(srcImageRange(src), destImage(dest), 3.0);

This function is mainly used internally: It is called for each dimension of a higher dimensional array in order to perform a separable resize operation.

Declaration:

#include <vigra/resampling_convolution.hxx>

    namespace vigra {
        template <class SrcIter, class SrcAcc,
                  class DestIter, class DestAcc,
                  class KernelArray,
                  class Functor>
        void
        resamplingConvolveLine(SrcIter s, SrcIter send, SrcAcc src,
                               DestIter d, DestIter dend, DestAcc dest,
                               KernelArray const & kernels,
                               Functor mapTargetToSourceCoordinate)    
    }

This function implements a convolution operation in x-direction (i.e. applies a 1D filter to every row) where the width of the source and destination images differ. This is typically used to avoid aliasing if the image is scaled down, or to interpolate smoothly if the image is scaled up. The target coordinates are transformed into source coordinates by

    xsource = (xtarget - offset) / samplingRatio

The samplingRatio and offset must be given as vigra::Rational in order to avoid rounding errors in this transformation. It is required that for all pixels of the target image, xsource remains within the range of the source image (i.e. 0 <= xsource <= sourceWidth-1. Since xsource is in general not an integer, the kernel must be a functor that can be accessed at arbitrary (double) coordinates. It must also provide a member function radius() which specifies the support (non-zero interval) of the kernel. VIGRA already provides a number of suitable functors, e.g. vigra::Gaussian, vigra::BSpline vigra::CatmullRomSpline, and vigra::CoscotFunction. The function resizeImageSplineInterpolation() is implemented by means resamplingConvolveX() and resamplingConvolveY().

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIter, class SrcAcc,
                  class DestIter, class DestAcc,
                  class Kernel>
        void
        resamplingConvolveX(SrcIter sul, SrcIter slr, SrcAcc src,
                            DestIter dul, DestIter dlr, DestAcc dest,
                            Kernel const & kernel,
                            Rational<int> const & samplingRatio, Rational<int> const & offset);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIter, class SrcAcc,
                  class DestIter, class DestAcc,
                  class Kernel>
        void
        resamplingConvolveX(triple<SrcIter, SrcIter, SrcAcc> src,
                            triple<DestIter, DestIter, DestAcc> dest,
                            Kernel const & kernel,
                            Rational<int> const & samplingRatio, Rational<int> const & offset);
    }

Usage:

#include <vigra/resampling_convolution.hxx>

    Rational<int> ratio(2), offset(0);

    FImage src(w,h),
           dest(rational_cast<int>(ratio*w), h);

    float sigma = 2.0;
    Gaussian<float> smooth(sigma);
    ...

    // simpultaneously enlarge and smooth source image
    resamplingConvolveX(srcImageRange(src), destImageRange(dest),
                        smooth, ratio, offset);

Required Interface:

    Kernel kernel;
    int kernelRadius = kernel.radius();
    double x = ...;  // must be <= radius()
    double value = kernel(x);

This function implements a convolution operation in y-direction (i.e. applies a 1D filter to every column) where the height of the source and destination images differ. This is typically used to avoid aliasing if the image is scaled down, or to interpolate smoothly if the image is scaled up. The target coordinates are transformed into source coordinates by

    ysource = (ytarget - offset) / samplingRatio

The samplingRatio and offset must be given as vigra::Rational in order to avoid rounding errors in this transformation. It is required that for all pixels of the target image, ysource remains within the range of the source image (i.e. 0 <= ysource <= sourceHeight-1. Since ysource is in general not an integer, the kernel must be a functor that can be accessed at arbitrary (double) coordinates. It must also provide a member function radius() which specifies the support (non-zero interval) of the kernel. VIGRA already provides a number of suitable functors, e.g. vigra::Gaussian, vigra::BSpline vigra::CatmullRomSpline, and vigra::CoscotFunction. The function resizeImageSplineInterpolation() is implemented by means resamplingConvolveX() and resamplingConvolveY().

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIter, class SrcAcc,
                  class DestIter, class DestAcc,
                  class Kernel>
        void
        resamplingConvolveY(SrcIter sul, SrcIter slr, SrcAcc src,
                            DestIter dul, DestIter dlr, DestAcc dest,
                            Kernel const & kernel,
                            Rational<int> const & samplingRatio, Rational<int> const & offset);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIter, class SrcAcc,
                  class DestIter, class DestAcc,
                  class Kernel>
        void
        resamplingConvolveY(triple<SrcIter, SrcIter, SrcAcc> src,
                            triple<DestIter, DestIter, DestAcc> dest,
                            Kernel const & kernel,
                            Rational<int> const & samplingRatio, Rational<int> const & offset);
    }

Usage:

#include <vigra/resampling_convolution.hxx>

    Rational<int> ratio(2), offset(0);

    FImage src(w,h),
           dest(w, rational_cast<int>(ratio*h));

    float sigma = 2.0;
    Gaussian<float> smooth(sigma);
    ...

    // simpultaneously enlarge and smooth source image
    resamplingConvolveY(srcImageRange(src), destImageRange(dest),
                        smooth, ratio, offset);

Required Interface:

    Kernel kernel;
    int kernelRadius = kernel.radius();
    double y = ...;  // must be <= radius()
    double value = kernel(y);

This function is a shorthand for the concatenation of a call to resamplingConvolveX() and resamplingConvolveY() with the given kernels. See there for detailed documentation.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  class KernelX, class KernelY>
        void resamplingConvolveImage(SrcIterator sul,SrcIterator slr, SrcAccessor src,
                           DestIterator dul, DestIterator dlr, DestAccessor dest,
                           KernelX const & kx,
                           Rational<int> const & samplingRatioX, Rational<int> const & offsetX,
                           KernelY const & ky,
                           Rational<int> const & samplingRatioY, Rational<int> const & offsetY);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  class KernelX, class KernelY>
        void
        resamplingConvolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                           triple<DestIterator, DestIterator, DestAccessor> dest,
                           KernelX const & kx,
                           Rational<int> const & samplingRatioX, Rational<int> const & offsetX,
                           KernelY const & ky,
                           Rational<int> const & samplingRatioY, Rational<int> const & offsetY);
    }

Usage:

#include <vigra/resampling_convolution.hxx>

    Rational<int> xratio(2), yratio(3), offset(0);

    FImage src(w,h),
           dest(rational_cast<int>(xratio*w), rational_cast<int>(yratio*h));

    float sigma = 2.0;
    Gaussian<float> smooth(sigma);
    ...

    // simpultaneously enlarge and smooth source image
    resamplingConvolveImage(srcImageRange(src), destImageRange(dest),
                            smooth, xratio, offset,
                            smooth, yratio, offset);

Sorry, no detailedDocumentation() available yet.

Declarations:

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

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void pyramidReduceBurtFilter(SrcIterator sul, SrcIterator slr, SrcAccessor src,
                                     DestIterator dul, DestIterator dlr, DestAccessor dest,
                                     double centerValue = 0.4);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void pyramidReduceBurtFilter(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                                     triple<DestIterator, DestIterator, DestAccessor> dest,
                                     double centerValue = 0.4);
    }

use a vigra::ImagePyramid :

    namespace vigra {
        template <class Image, class Alloc>
        void pyramidReduceBurtFilter(ImagePyramid<Image, Alloc> & pyramid, int fromLevel, int toLevel,
                                     double centerValue = 0.4);
    }

Sorry, no detailedDocumentation() available yet.

Declarations:

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

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void pyramidExpandBurtFilter(SrcIterator sul, SrcIterator slr, SrcAccessor src,
                                     DestIterator dul, DestIterator dlr, DestAccessor dest,
                                     double centerValue = 0.4);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void pyramidExpandBurtFilter(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                                     triple<DestIterator, DestIterator, DestAccessor> dest,
                                     double centerValue = 0.4);
    }

use a vigra::ImagePyramid :

    namespace vigra {
        template <class Image, class Alloc>
        void pyramidExpandBurtFilter(ImagePyramid<Image, Alloc> & pyramid, int fromLevel, int toLevel,
                                     double centerValue = 0.4);
    }

This algorithm is very fast and does not require any arithmetic on the pixel types.

The range of both the input and output images (resp. regions) must be given. Both images must have a size of at least 2x2 pixels. The scaling factors are then calculated accordingly. Destination pixels are directly copied from the appropriate source pixels.

The function uses accessors.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
                  class DestImageIterator, class DestAccessor>
        void
        resizeImageNoInterpolation(
              SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa,
              DestImageIterator id, DestImageIterator idend, DestAccessor da)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
                  class DestImageIterator, class DestAccessor>
        void
        resizeImageNoInterpolation(
              triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
              triple<DestImageIterator, DestImageIterator, DestAccessor> dest)
    }

Usage:

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

    vigra::resizeImageNoInterpolation(
               src.upperLeft(), src.lowerRight(), src.accessor(),
               dest.upperLeft(), dest.lowerRight(), dest.accessor());

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator dest_upperleft, src_lowerright;

    SrcAccessor src_accessor;
    DestAccessor dest_accessor;

    dest_accessor.set(src_accessor(src_upperleft), dest_upperleft);

Preconditions:

    src_lowerright.x - src_upperleft.x > 1
    src_lowerright.y - src_upperleft.y > 1
    dest_lowerright.x - dest_upperleft.x > 1
    dest_lowerright.y - dest_upperleft.y > 1

The function uses the standard separable bilinear interpolation algorithm to obtain a good compromize between quality and speed.

The range must of both the input and output images (resp. regions) must be given. Both images must have a size of at least 2x2. The scaling factors are then calculated accordingly. If the source image is larger than the destination, it is smoothed (band limited) using a recursive exponential filter. The source value_type (SrcAccessor::value_type) must be a linear space, i.e. it must support addition, multiplication with a scalar real number and NumericTraits. The function uses accessors.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
                  class DestImageIterator, class DestAccessor>
        void
        resizeImageLinearInterpolation(
              SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa,
              DestImageIterator id, DestImageIterator idend, DestAccessor da)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
                  class DestImageIterator, class DestAccessor>
        void
        resizeImageLinearInterpolation(
              triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
              triple<DestImageIterator, DestImageIterator, DestAccessor> dest)
    }

Usage:

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

    vigra::resizeImageLinearInterpolation(
               src.upperLeft(), src.lowerRight(), src.accessor(),
               dest.upperLeft(), dest.lowerRight(), dest.accessor());

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator dest_upperleft, src_lowerright;

    SrcAccessor src_accessor;
    DestAccessor dest_accessor;

    NumericTraits<SrcAccessor::value_type>::RealPromote
                             u = src_accessor(src_upperleft),
                 v = src_accessor(src_upperleft, 1);
    double d;

    u = d * v;
    u = u + v;

    dest_accessor.set(
        NumericTraits<DestAccessor::value_type>::fromRealPromote(u),
    dest_upperleft);

Preconditions:

    src_lowerright.x - src_upperleft.x > 1
    src_lowerright.y - src_upperleft.y > 1
    dest_lowerright.x - dest_upperleft.x > 1
    dest_lowerright.y - dest_upperleft.y > 1

The function implements separable spline interpolation algorithm described in

M. Unser, A. Aldroubi, M. Eden, "B-Spline Signal Processing" IEEE Transactions on Signal Processing, vol. 41, no. 2, pp. 821-833 (part I), pp. 834-848 (part II), 1993.

to obtain optimal interpolation quality and speed. You may pass the funcion a spline of arbitrary order (e.g. BSpline<ORDER, double> or CatmullRomSpline<double>). The default is a third order spline which gives a twice continuously differentiable interpolant. The implementation ensures that image values are interpolated rather than smoothed by first calling a recursive (sharpening) prefilter as described in the above paper. Then the actual interpolation is done using resamplingConvolveLine().

The range of both the input and output images (resp. regions) must be given. The input image must have a size of at least 4x4, the destination of at least 2x2. The scaling factors are then calculated accordingly. If the source image is larger than the destination, it is smoothed (band limited) using a recursive exponential filter. The source value_type (SrcAccessor::value_type) must be a linear algebra, i.e. it must support addition, subtraction, and multiplication (+, -, *), multiplication with a scalar real number and NumericTraits. The function uses accessors.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
                  class DestImageIterator, class DestAccessor,
                  class SPLINE>
        void
        resizeImageSplineInterpolation(
              SrcImageIterator is, SrcImageIterator iend, SrcAccessor sa,
              DestImageIterator id, DestImageIterator idend, DestAccessor da,
              SPLINE spline = BSpline<3, double>())
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
                  class DestImageIterator, class DestAccessor,
                  class SPLINE>
        void
        resizeImageSplineInterpolation(
              triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
              triple<DestImageIterator, DestImageIterator, DestAccessor> dest,
              SPLINE spline = BSpline<3, double>())
    }

Usage:

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

    vigra::resizeImageSplineInterpolation(
               src.upperLeft(), src.lowerRight(), src.accessor(),
               dest.upperLeft(), dest.lowerRight(), dest.accessor());

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator dest_upperleft, src_lowerright;

    SrcAccessor src_accessor;
    DestAccessor dest_accessor;

    NumericTraits<SrcAccessor::value_type>::RealPromote
                             u = src_accessor(src_upperleft),
                 v = src_accessor(src_upperleft, 1);
    double d;

    u = d * v;
    u = u + v;
    u = u - v;
    u = u * v;
    u += v;
    u -= v;

    dest_accessor.set(
        NumericTraits<DestAccessor::value_type>::fromRealPromote(u),
    dest_upperleft);

Preconditions:

    src_lowerright.x - src_upperleft.x > 3
    src_lowerright.y - src_upperleft.y > 3
    dest_lowerright.x - dest_upperleft.x > 1
    dest_lowerright.y - dest_upperleft.y > 1

The function calls like resizeImageSplineInterpolation() with vigra::CatmullRomSpline as an interpolation kernel. The interpolated function has one continuous derivative. (See resizeImageSplineInterpolation() for more documentation)

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        resizeImageCatmullRomInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
                              DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        resizeImageCatmullRomInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                              triple<DestIterator, DestIterator, DestAccessor> dest);
    }

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

The function calls resizeImageSplineInterpolation() with vigra::CoscotFunction as an interpolation kernel. The interpolated function has one continuous derivative. (See resizeImageSplineInterpolation() for more documentation)

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        resizeImageCoscotInterpolation(SrcIterator src_iter, SrcIterator src_iter_end, SrcAccessor src_acc,
                              DestIterator dest_iter, DestIterator dest_iter_end, DestAccessor dest_acc);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void
        resizeImageCoscotInterpolation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                              triple<DestIterator, DestIterator, DestAccessor> dest);
    }

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

This algorithm implements seeded region growing as described in

R. Adams, L. Bischof: "<em> Seeded Region Growing</em>", IEEE Trans. on Pattern Analysis and Maschine Intelligence, vol 16, no 6, 1994, and

Ullrich Köthe: Primary Image Segmentation, in: G. Sagerer, S. Posch, F. Kummert (eds.): Mustererkennung 1995, Proc. 17. DAGM-Symposium, Springer 1995

The seed image is a partly segmented image which contains uniquely labeled regions (the seeds) and unlabeled pixels (the candidates, label 0). Seed regions can be as large as you wish and as small as one pixel. If there are no candidates, the algorithm will simply copy the seed image into the output image. Otherwise it will aggregate the candidates into the existing regions so that a cost function is minimized. This works as follows:

  1. Find all candidate pixels that are 4-adjacent to a seed region. Calculate the cost for aggregating each candidate into its adajacent region and put the candidates into a priority queue.

  2. While( priority queue is not empty)

    1. Take the candidate with least cost from the queue. If it has not already been merged, merge it with it's adjacent region.

    2. Put all candidates that are 4-adjacent to the pixel just processed into the priority queue.

If SRGType == CompleteGrow (the default), this algorithm will produce a complete 4-connected tesselation of the image. If SRGType == KeepContours, a one-pixel-wide border will be left between the regions. The border pixels get label 0 (zero).

The cost is determined jointly by the source image and the region statistics functor. The source image contains feature values for each pixel which will be used by the region statistics functor to calculate and update statistics for each region and to calculate the cost for each candidate. The RegionStatisticsArray must be compatible to the ArrayOfRegionStatistics functor and contains an array of statistics objects for each region. The indices must correspond to the labels of the seed regions. The statistics for the initial regions must have been calculated prior to calling seededRegionGrowing() (for example by means of inspectTwoImagesIf()).

For each candidate x that is adjacent to region i, the algorithm will call stats[i].cost(as(x)) to get the cost (where x is a SrcImageIterator and as is the SrcAccessor). When a candidate has been merged with a region, the statistics are updated by calling stats[i].operator()(as(x)). Since the RegionStatisticsArray is passed by reference, this will overwrite the original statistics.

If a candidate could be merged into more than one regions with identical cost, the algorithm will favour the nearest region.

In some cases, the cost only depends on the feature value of the current pixel. Then the update operation will simply be a no-op, and the cost() function returns its argument. This behavior is implemented by the SeedRgDirectValueFunctor. With SRGType == KeepContours, this is equivalent to the watershed algorithm.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
                  class SeedImageIterator, class SeedAccessor,
                  class DestImageIterator, class DestAccessor,
                  class RegionStatisticsArray>
        void seededRegionGrowing(SrcImageIterator srcul,
                                 SrcImageIterator srclr, SrcAccessor as,
                                 SeedImageIterator seedsul, SeedAccessor aseeds,
                                 DestImageIterator destul, DestAccessor ad,
                                 RegionStatisticsArray & stats,
                                 SRGType srgType = CompleteGrow);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
                  class SeedImageIterator, class SeedAccessor,
                  class DestImageIterator, class DestAccessor,
                  class RegionStatisticsArray>
        void
        seededRegionGrowing(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> img1,
                            pair<SeedImageIterator, SeedAccessor> img3,
                            pair<DestImageIterator, DestAccessor> img4,
                            RegionStatisticsArray & stats,
                            SRGType srgType = CompleteGrow);
    }

Usage:

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

Example: implementation of the voronoi tesselation

    vigra::BImage points(w,h);
    vigra::FImage dist(x,y);

    // empty edge image
    points = 0;
    dist = 0;

    int max_region_label = 100;

    // throw in some random points:
    for(int i = 1; i <= max_region_label; ++i)
           points(w * rand() / RAND_MAX , h * rand() / RAND_MAX) = i;

    // calculate Euclidean distance transform
    vigra::distanceTransform(srcImageRange(points), destImage(dist), 2);

    // init statistics functor
    vigra::ArrayOfRegionStatistics<vigra::SeedRgDirectValueFunctor<float> >
                                              stats(max_region_label);

    // find voronoi region of each point
   vigra:: seededRegionGrowing(srcImageRange(dist), srcImage(points),
                               destImage(points), stats);

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    SeedImageIterator seed_upperleft;
    DestImageIterator dest_upperleft;

    SrcAccessor src_accessor;
    SeedAccessor seed_accessor;
    DestAccessor dest_accessor;

    RegionStatisticsArray stats;

    // calculate costs
    RegionStatisticsArray::value_type::cost_type cost =
        stats[seed_accessor(seed_upperleft)].cost(src_accessor(src_upperleft));

    // compare costs
    cost < cost;

    // update statistics
    stats[seed_accessor(seed_upperleft)](src_accessor(src_upperleft));

    // set result
    dest_accessor.set(seed_accessor(seed_upperleft), dest_upperleft);

Further requirements are determined by the RegionStatisticsArray.

This algorithm implements seeded region growing as described in

The seed image is a partly segmented multi-dimensional array which contains uniquely labeled regions (the seeds) and unlabeled voxels (the candidates, label 0). Seed regions can be as large as you wish and as small as one voxel. If there are no candidates, the algorithm will simply copy the seed array into the output array. Otherwise it will aggregate the candidates into the existing regions so that a cost function is minimized. This works as follows:

  1. Find all candidate pixels that are 6-adjacent to a seed region. Calculate the cost for aggregating each candidate into its adajacent region and put the candidates into a priority queue.

  2. While( priority queue is not empty)

    1. Take the candidate with least cost from the queue. If it has not already been merged, merge it with it's adjacent region.

    2. Put all candidates that are 4-adjacent to the pixel just processed into the priority queue.

If SRGType == CompleteGrow (the default), this algorithm will produce a complete 6-connected tesselation of the array. Other grow types (such as keeping contours for watersheds) are currently not supported

The cost is determined jointly by the source array and the region statistics functor. The source array contains feature values for each pixel which will be used by the region statistics functor to calculate and update statistics for each region and to calculate the cost for each candidate. The RegionStatisticsArray must be compatible to the ArrayOfRegionStatistics functor and contains an array of statistics objects for each region. The indices must correspond to the labels of the seed regions. The statistics for the initial regions must have been calculated prior to calling seededRegionGrowing3D()

For each candidate x that is adjacent to region i, the algorithm will call stats[i].cost(as(x)) to get the cost (where x is a SrcImageIterator and as is the SrcAccessor). When a candidate has been merged with a region, the statistics are updated by calling stats[i].operator()(as(x)). Since the RegionStatisticsArray is passed by reference, this will overwrite the original statistics.

If a candidate could be merged into more than one regions with identical cost, the algorithm will favour the nearest region. If, at any point in the algorithm, the cost of the current candidate exceeds the optional max_cost value (which defaults to -1), region growing is aborted, and all voxels not yet assigned to a region remain unlabeled.

In some cases, the cost only depends on the feature value of the current voxel. Then the update operation will simply be a no-op, and the cost() function returns its argument. This behavior is implemented by the SeedRgDirectValueFunctor.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator, class Diff_type, class SrcAccessor,
                  class SeedImageIterator, class SeedAccessor,
                  class DestImageIterator, class DestAccessor,
                  class RegionStatisticsArray, class CostThresholdType >
        void seededRegionGrowing3D(SrcImageIterator srcul, Diff_type shape,
                                 SrcAccessor as,
                                 SeedImageIterator seedsul, SeedAccessor aseeds,
                                 DestImageIterator destul, DestAccessor ad,
                                 RegionStatisticsArray & stats, 
                                 CostThresholdType max_cost = -1.0,
                                 const SRGType srgType == CompleteGrow);

        template <class SrcImageIterator, class Diff_type, class SrcAccessor,
                  class SeedImageIterator, class SeedAccessor,
                  class DestImageIterator, class DestAccessor,
                  class RegionStatisticsArray>
        void seededRegionGrowing3D(SrcImageIterator srcul, Diff_type shape,
                                 SrcAccessor as,
                                 SeedImageIterator seedsul, SeedAccessor aseeds,
                                 DestImageIterator destul, DestAccessor ad,
                                 RegionStatisticsArray & stats, 
                                 const SRGType srgType == CompleteGrow);

       }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
            template <class SrcImageIterator, class Shape, class SrcAccessor,
                  class SeedImageIterator, class SeedAccessor,
                  class DestImageIterator, class DestAccessor,
                  class RegionStatisticsArray, class CostThresholdType>
            void
            seededRegionGrowing3D(triple<SrcImageIterator, Shape, SrcAccessor> img1,
                            pair<SeedImageIterator, SeedAccessor> img3,
                            pair<DestImageIterator, DestAccessor> img4,
                            RegionStatisticsArray & stats, 
                            CostThresholdType max_cost = -1.0,
                            const SRGType srgType == CompleteGrow);

            template <class SrcImageIterator, class Shape, class SrcAccessor,
                  class SeedImageIterator, class SeedAccessor,
                  class DestImageIterator, class DestAccessor,
                  class RegionStatisticsArray>
            void
            seededRegionGrowing3D(triple<SrcImageIterator, Shape, SrcAccessor> img1,
                            pair<SeedImageIterator, SeedAccessor> img3,
                            pair<DestImageIterator, DestAccessor> img4,
                            RegionStatisticsArray & stats, 
                            const SRGType srgType == CompleteGrow);
    }

The KernelIterator must point to the center iterator, and the kernel's size is given by its left (kleft <= 0) and right (kright >= 0) borders. The signal must always be larger than the kernel. At those positions where the kernel does not completely fit into the signal's range, the specified BorderTreatmentMode is applied.

The signal's value_type (SrcAccessor::value_type) must be a linear space over the kernel's value_type (KernelAccessor::value_type), i.e. addition of source values, multiplication with kernel values, and NumericTraits must be defined. The kernel's value_type must be an algebraic field, i.e. the arithmetic operations (+, -, *, /) and NumericTraits must be defined.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  class KernelIterator, class KernelAccessor>
        void convolveLine(SrcIterator is, SrcIterator isend, SrcAccessor sa,
                          DestIterator id, DestAccessor da,
                          KernelIterator ik, KernelAccessor ka,
                          int kleft, int kright, BorderTreatmentMode border)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor,
                  class KernelIterator, class KernelAccessor>
        void convolveLine(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                          pair<DestIterator, DestAccessor> dest,
                          tuple5<KernelIterator, KernelAccessor,
                                 int, int, BorderTreatmentMode> kernel)
    }

Usage:

#include <vigra/separableconvolution.hxx>

    std::vector<float> src, dest;
    ...

    // define binomial filter of size 5
    static float kernel[] =
           { 1.0/16.0, 4.0/16.0, 6.0/16.0, 4.0/16.0, 1.0/16.0};

    typedef vigra::StandardAccessor<float> FAccessor;
    typedef vigra::StandardAccessor<float> KernelAccessor;


    vigra::convolveLine(src.begin(), src.end(), FAccessor(), dest.begin(), FAccessor(),
             kernel+2, KernelAccessor(), -2, 2, BORDER_TREATMENT_REFLECT);
    //       ^^^^^^^^  this is the center of the kernel

Required Interface:

    RandomAccessIterator is, isend;
    RandomAccessIterator id;
    RandomAccessIterator ik;

    SrcAccessor src_accessor;
    DestAccessor dest_accessor;
    KernelAccessor kernel_accessor;

    NumericTraits<SrcAccessor::value_type>::RealPromote s = src_accessor(is);

    s = s + s;
    s = kernel_accessor(ik) * s;

    dest_accessor.set(
        NumericTraits<DestAccessor::value_type>::fromRealPromote(s), id);

If border == BORDER_TREATMENT_CLIP:

    NumericTraits<KernelAccessor::value_type>::RealPromote k = kernel_accessor(ik);

    k = k + k;
    k = k - k;
    k = k * k;
    k = k / k;

Preconditions:

    kleft <= 0
    kright >= 0
    iend - is >= kright + kleft + 1

If border == BORDER_TREATMENT_CLIP: Sum of kernel elements must be != 0.

It calls convolveLine() for every row of the image. See convolveLine() for more information about required interfaces and vigra_preconditions.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
                  class DestImageIterator, class DestAccessor,
                  class KernelIterator, class KernelAccessor>
        void separableConvolveX(SrcImageIterator supperleft,
                                SrcImageIterator slowerright, SrcAccessor sa,
                                DestImageIterator dupperleft, DestAccessor da,
                                KernelIterator ik, KernelAccessor ka,
                                int kleft, int kright, BorderTreatmentMode border)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
                  class DestImageIterator, class DestAccessor,
                  class KernelIterator, class KernelAccessor>
        void separableConvolveX(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
                                pair<DestImageIterator, DestAccessor> dest,
                                tuple5<KernelIterator, KernelAccessor,
                                             int, int, BorderTreatmentMode> kernel)
    }

Usage:

#include <vigra/separableconvolution.hxx>

    vigra::FImage src(w,h), dest(w,h);
    ...

    // define Gaussian kernel with std. deviation 3.0
    vigra::Kernel1D<double> kernel;
    kernel.initGaussian(3.0);

    vigra::separableConvolveX(srcImageRange(src), destImage(dest), kernel1d(kernel));

It calls convolveLine() for every column of the image. See convolveLine() for more information about required interfaces and vigra_preconditions.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
                  class DestImageIterator, class DestAccessor,
                  class KernelIterator, class KernelAccessor>
        void separableConvolveY(SrcImageIterator supperleft,
                                SrcImageIterator slowerright, SrcAccessor sa,
                                DestImageIterator dupperleft, DestAccessor da,
                                KernelIterator ik, KernelAccessor ka,
                                int kleft, int kright, BorderTreatmentMode border)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
                  class DestImageIterator, class DestAccessor,
                  class KernelIterator, class KernelAccessor>
        void separableConvolveY(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
                                pair<DestImageIterator, DestAccessor> dest,
                                tuple5<KernelIterator, KernelAccessor,
                                             int, int, BorderTreatmentMode> kernel)
    }

Usage:

#include <vigra/separableconvolution.hxx>

    vigra::FImage src(w,h), dest(w,h);
    ...

    // define Gaussian kernel with std. deviation 3.0
    vigra::Kernel1D kernel;
    kernel.initGaussian(3.0);

    vigra::separableConvolveY(srcImageRange(src), destImage(dest), kernel1d(kernel));

This operator estimates the magnitude transfer function (MTF) of a camera by means of the slanted edge method described in:

ISO Standard No. 12233: "Photography - Electronic still picture cameras - Resolution measurements", 2000

The input must be an image that contains a single step edge with bright pixels on one side and dark pixels on the other. However, the intensity values must be neither saturated nor zero. The algorithms computes the MTF from the Fourier transform of the edge's derivative. Thus, if the actual MTF is unisotropic, the estimated MTF does actually only apply in the direction perpendicular to the edge - several edges at different orientations are required to estimate an unisotropic MTF.

The algorithm returns a sequence of frequency / attenuation pairs. The frequency axis is normalized so that the Nyquist frequency of the original image is 0.5. Since the edge's derivative is computed with subpixel accuracy, the attenuation can usually be computed for frequencies significantly above the Nyquist frequency as well. The MTF estimate ends at either the first zero crossing of the MTF or at frequency 1, whichever comes earlier.

The present implementation improves the original slanted edge algorithm according to ISO 12233 in a number of ways:

  • The edge is not required to run nearly vertically or horizontally (i.e. with a slant of approximately 5 degrees). The algorithm will automatically compute the edge's actual angle and adjust estimates accordingly. However, it is still necessary for the edge to be somewhat slanted, because subpixel-accurate estimation of the derivative is impossible otherwise (i.e. the edge position perpendicular to the edge direction must differ by at least 1 pixel between the two ends of the edge).

  • Our implementation uses a more accurate subpixel derivative algrithm. In addition, we first perform a shading correction in order to reduce possible derivative bias due to nonuniform illumination.

  • If the input image is large enough (i.e. there are at least 20 pixels on either side of the edge over the edge's entire length), our algorithm attempts to subtract the estimated noise power spectrum from the estimated MTF.

The source value type (SrcAccessor::value_type) must be a scalar type which is convertible to double. The result is written into the result sequence, whose value_type must be constructible from two double values. Algorithm options can be set via the options object (see vigra::NoiseNormalizationOptions for details).

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor, class BackInsertable>
        void
        slantedEdgeMTF(SrcIterator sul, SrcIterator slr, SrcAccessor src, BackInsertable & mtf,
                    SlantedEdgeMTFOptions const & options = SlantedEdgeMTFOptions());
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor, class BackInsertable>
        void
        slantedEdgeMTF(triple<SrcIterator, SrcIterator, SrcAccessor> src, BackInsertable & mtf,
                       SlantedEdgeMTFOptions const & options = SlantedEdgeMTFOptions())
    }

Usage:

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

    vigra::BImage src(w,h);
    std::vector<vigra::TinyVector<double, 2> > mtf;
    
    ...
    vigra::slantedEdgeMTF(srcImageRange(src), mtf);
    
    // print the frequency / attenuation pairs found
    for(int k=0; k<result.size(); ++k)
        std::cout << "frequency: " << mtf[k][0] << ", estimated attenuation: " << mtf[k][1] << std::endl;

Required Interface:

    SrcIterator upperleft, lowerright;
    SrcAccessor src;
    
    typedef SrcAccessor::value_type SrcType;
    typedef NumericTraits<SrcType>::isScalar isScalar;
    assert(isScalar::asBool == true);
    
    double value = src(uperleft);
    
    BackInsertable result;
    typedef BackInsertable::value_type ResultType;    
    double intensity, variance;
    result.push_back(ResultType(intensity, variance));

This functions computes normalized convolution as defined in Knutsson, H. and Westin, C-F.: Normalized and differential convolution: Methods for Interpolation and Filtering of incomplete and uncertain data. Proc. of the IEEE Conf. on Computer Vision and Pattern Recognition, 1993, 515-523.

The mask image must be binary and encodes which pixels of the original image are valid. It is used as follows: Only pixel under the mask are used in the calculations. Whenever a part of the kernel lies outside the mask, it is ignored, and the kernel is renormalized to its original norm (analogous to the CLIP BorderTreatmentMode). Thus, a useful convolution result is computed whenever at least one valid pixel is within the current window Thus, destination pixels not under the mask still receive a value if they are near the mask. Therefore, this algorithm is useful as an interpolator of sparse input data. If you are only interested in the destination values under the mask, you can perform a subsequent copyImageIf().

The KernelIterator must point to the center of the kernel, and the kernel's size is given by its upper left (x and y of distance <= 0) and lower right (distance >= 0) corners. The image must always be larger than the kernel. At those positions where the kernel does not completely fit into the image, the specified BorderTreatmentMode is applied. Only BORDER_TREATMENT_CLIP and BORDER_TREATMENT_AVOID are currently supported.

The images's pixel type (SrcAccessor::value_type) must be a linear space over the kernel's value_type (KernelAccessor::value_type), i.e. addition of source values, multiplication with kernel values, and NumericTraits must be defined. The kernel's value_type must be an algebraic field, i.e. the arithmetic operations (+, -, *, /) and NumericTraits must be defined.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class MaskIterator, class MaskAccessor,
                  class DestIterator, class DestAccessor,
                  class KernelIterator, class KernelAccessor>
        void
        normalizedConvolveImage(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc,
                                MaskIterator mul, MaskAccessor am,
                                DestIterator dest_ul, DestAccessor dest_acc,
                                KernelIterator ki, KernelAccessor ak,
                                Diff2D kul, Diff2D klr, BorderTreatmentMode border);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class MaskIterator, class MaskAccessor,
                  class DestIterator, class DestAccessor,
                  class KernelIterator, class KernelAccessor>
        void normalizedConvolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                                     pair<MaskIterator, MaskAccessor> mask,
                                     pair<DestIterator, DestAccessor> dest,
                                     tuple5<KernelIterator, KernelAccessor, Diff2D, Diff2D,
                                     BorderTreatmentMode> kernel);
    }

Usage:

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

    vigra::FImage src(w,h), dest(w,h);
    vigra::CImage mask(w,h);
    ...

    // define 3x3 binomial filter
    vigra::Kernel2D<float> binom;

    binom.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) =   // upper left and lower right
                         0.0625, 0.125, 0.0625,
                         0.125,  0.25,  0.125,
                         0.0625, 0.125, 0.0625;

    vigra::normalizedConvolveImage(srcImageRange(src), maskImage(mask), destImage(dest), kernel2d(binom));

Required Interface:

    ImageIterator src_ul, src_lr;
    ImageIterator mul;
    ImageIterator dest_ul;
    ImageIterator ik;

    SrcAccessor src_accessor;
    MaskAccessor mask_accessor;
    DestAccessor dest_accessor;
    KernelAccessor kernel_accessor;

    NumericTraits<SrcAccessor::value_type>::RealPromote s = src_accessor(src_ul);

    s = s + s;
    s = kernel_accessor(ik) * s;
    s -= s;

    if(mask_accessor(mul)) ...;

    dest_accessor.set(
    NumericTraits<DestAccessor::value_type>::fromRealPromote(s), dest_ul);

    NumericTraits<KernelAccessor::value_type>::RealPromote k = kernel_accessor(ik);

    k += k;
    k -= k;
    k = k / k;

Preconditions:

    kul.x <= 0
    kul.y <= 0
    klr.x >= 0
    klr.y >= 0
    src_lr.x - src_ul.x >= klr.x + kul.x + 1
    src_lr.y - src_ul.y >= klr.y + kul.y + 1
    border == BORDER_TREATMENT_CLIP || border == BORDER_TREATMENT_AVOID

Sum of kernel elements must be != 0.

See normalizedConvolveImage() for documentation.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class MaskIterator, class MaskAccessor,
                  class DestIterator, class DestAccessor,
                  class KernelIterator, class KernelAccessor>
        void
        convolveImageWithMask(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc,
                              MaskIterator mul, MaskAccessor am,
                              DestIterator dest_ul, DestAccessor dest_acc,
                              KernelIterator ki, KernelAccessor ak,
                              Diff2D kul, Diff2D klr, BorderTreatmentMode border);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class MaskIterator, class MaskAccessor,
                  class DestIterator, class DestAccessor,
                  class KernelIterator, class KernelAccessor>
        void convolveImageWithMask(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                                   pair<MaskIterator, MaskAccessor> mask,
                                   pair<DestIterator, DestAccessor> dest,
                                   tuple5<KernelIterator, KernelAccessor, Diff2D, Diff2D,
                                   BorderTreatmentMode> kernel);
    }

This algorithm implements the Fast Radial Symmetry Transform according to [G. Loy, A. Zelinsky: "A Fast Radial Symmetry Transform for Detecting Points of Interest", in: A. Heyden et al. (Eds.): Proc. of 7th European Conf. on Computer Vision, Part 1, pp. 358-368, Springer LNCS 2350, 2002]. Minima of the algorithm response mark dark blobs, maxima correspond to light blobs. The "radial strictness parameter" is fixed at alpha = 2.0, the spatial spreading of the raw response is done by a Gaussian convolution at 0.25*scale (these values are recommendations from the paper). Loy and Zelinsky additionally propose to add the operator response from several scales (see usage example below).

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                    class DestIterator, class DestAccessor>
        void
        radialSymmetryTransform(SrcIterator sul, SrcIterator slr, SrcAccessor as,
                                      DestIterator dul, DestAccessor ad,
                                      double scale)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                    class DestIterator, class DestAccessor>
        inline
        void radialSymmetryTransform(
                 triple<SrcIterator, SrcIterator, SrcAccessor> src,
                 pair<DestIterator, DestAccessor> dest,
                 double scale)
    }

Usage:

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

    vigra::BImage src(w,h), centers(w,h);
    vigra::FImage symmetry(w,h);

    // empty result image
    centers.init(128);
    symmetry.init(0.0);

    // input width of edge detection filter
    for(double scale = 2.0; scale <= 8.0; scale *= 2.0)
    {
        vigra::FImage tmp(w,h);

        // find centers of symmetry
        radialSymmetryTransform(srcImageRange(src), destImage(tmp), scale);

        combineTwoImages(srcImageRange(symmetry), srcImage(tmp), destImage(symmetry),
                         std::plus<float>());
    }

    localMinima(srcImageRange(symmetry), destImage(centers), 0);
    localMaxima(srcImageRange(symmetry), destImage(centers), 255);

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator dest_upperleft;

    SrcAccessor src_accessor;
    DestAccessor dest_accessor;

    // SrcAccessor::value_type must be a built-in type
    SrcAccessor::value_type u = src_accessor(src_upperleft);

    dest_accessor.set(u, dest_upperleft);

This function is useful to transform vector images into a tensor representation that can be used as input to tensor based processing and analysis functions (e.g. tensor smoothing). The imput pixel type must be vectors of length 2, whereas the output must contain vectors of length 3 which will represent the tensor components in the order t11, t12 (== t21 due to symmetry), t22.

Note: By default, this function negates the second component of the vector in order to turn a left handed vector (the usual resul of convolution, e.g. a gradient filter, because y runs from top to bottom) into a right handed tensor (as is required by all tensor function in VIGRA). This behavior can be switched off by setting negateComponent2 = false.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void vectorToTensor(SrcIterator sul, SrcIterator slr, SrcAccessor src,
                            DestIterator dul, DestAccessor dest,
                            bool negateComponent2 = true);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void vectorToTensor(triple<SrcIterator, SrcIterator, SrcAccessor> s,
                            pair<DestIterator, DestAccessor> d,
                            bool negateComponent2 = true);
    }

Usage:

#include <vigra/tensorutilities.hxx>

    FImage img(w,h);
    FVector2Image gradient(w,h);
    FVector3Image tensor(w,h);
    
    gaussianGradient(srcImageRange(img), destImage(gradient), 2.0);
    vectorToTensor(srcImageRange(gradient), destImage(tensor));

This function turns a 3-band image representing the tensor components t11, t12 (== t21 due to symmetry), t22 into the a 3-band image holding the eigen representation e1, e2, and angle, where e1 > e2. The original tensor must be defined in a right-handed coordinate system, and the angle of the tensor will then be given in mathematical positive (counter-clockwise) orientation, starting at the x-axis.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void tensorEigenRepresentation(SrcIterator sul, SrcIterator slr, SrcAccessor src,
                                       DestIterator dul, DestAccessor dest);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void tensorEigenRepresentation(triple<SrcIterator, SrcIterator, SrcAccessor> s,
                                       pair<DestIterator, DestAccessor> d);
    }

Usage:

#include <vigra/tensorutilities.hxx>

    FVector3Image tensor(w,h);
    FVector3Image eigen(w,h);
    
    tensorEigenRepresentation(srcImageRange(tensor), destImage(eigen));

This function turns a 3-band image representing the tensor components t11, t12 (== t21 due to symmetry), t22 into the a 1-band image holding the tensor trace t11 + t22.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void tensorTrace(SrcIterator sul, SrcIterator slr, SrcAccessor src,
                         DestIterator dul, DestAccessor dest);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator, class DestAccessor>
        void tensorTrace(triple<SrcIterator, SrcIterator, SrcAccessor> s,
                         pair<DestIterator, DestAccessor> d);
    }

Usage:

#include <vigra/tensorutilities.hxx>

    FVector3Image tensor(w,h);
    FImage trace(w,h);
    
    tensorTrace(srcImageRange(tensor), destImage(trace));

This function turns a 3-band image representing the tensor components t11, t12 (== t21 due to symmetry), t22 into the a 2-band image holding the tensor's edgeness (difference of the tensor's eigenvalues) and orientation, and a 1-band image representing its corner part (equal to the twice the small eigen value). The original tensor must be positive definite and defined in a right-handed coordinate system (e.g. the tensor resulting from boundaryTensor()).

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator1, class DestAccessor1,
                  class DestIterator2, class DestAccessor2>
        void tensorToEdgeCorner(SrcIterator sul, SrcIterator slr, SrcAccessor src,
                                DestIterator1 edgeul, DestAccessor1 edge,
                                DestIterator2 cornerul, DestAccessor2 corner);
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcIterator, class SrcAccessor,
                  class DestIterator1, class DestAccessor1,
                  class DestIterator2, class DestAccessor2>
        void tensorToEdgeCorner(triple<SrcIterator, SrcIterator, SrcAccessor> s,
                                pair<DestIterator1, DestAccessor1> edge,
                                pair<DestIterator2, DestAccessor2> corner);
    }

Usage:

#include <vigra/tensorutilities.hxx>

    FVector3Image tensor(w,h);
    FVector2Image edgePart(w,h);
    FImage cornerPart(w,h);
    
    tensorTrace(srcImageRange(tensor), destImage(edgePart), destImage(cornerPart));

Accessors are used to write the data. This function calls tiffToScalarImage() or tiffToRGBImage(), depending on the accessor's value_type.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class ImageIterator, class Accessor>
        void
        importTiffImage(TiffImage * tiff, ImageIterator iter, Accessor a)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class ImageIterator, class Accessor>
        void
        importTiffImage(TiffImage * tiff, pair<ImageIterator, Accessor> dest)
    }

Usage:

#include <vigra/tiff.hxx>

    uint32 w, h;
    TiffImage * tiff = TIFFOpen("tiffimage.tiff", "r");
    TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &w);
    TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &h);
    
    vigra::BImage img(w,h);
    
    vigra::importTiffImage(tiff, destImage(img));
    
    TIFFClose(tiff);

Required Interface:

see tiffToScalarImage() and tiffToRGBImage()

Preconditions:

see tiffToScalarImage() and tiffToRGBImage()

This function uses accessors to write the data.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class ImageIterator, class Accessor>
        void
        tiffToScalarImage(TiffImage * tiff, ImageIterator iter, Accessor a)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class ImageIterator, class Accessor>
        void
        tiffToScalarImage(TiffImage * tiff, pair<ImageIterator, Accessor> dest)
    }

Usage:

#include <vigra/tiff.hxx>

    uint32 w, h;
    uint16 photometric
    TiffImage * tiff = TIFFOpen("tiffimage.tiff", "r");
    TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &w);
    TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &h);
    TIFFGetField(tiff_, TIFFTAG_PHOTOMETRIC, &photometric);
        
    if(photometric != PHOTOMETRIC_MINISWHITE &&
       photometric != PHOTOMETRIC_MINISBLACK)
    {
        // not a scalar image - handle error
    }
    
    vigra::BImage img(w,h);
    
    vigra::tiffToScalarImage(tiff, destImage(img));
    
    TIFFClose(tiff);

Required Interface:

    ImageIterator upperleft;
    <unsigned char, short, long, float, double> value;
    
    Accessor accessor;
               
    accessor.set(value, upperleft);

Preconditions:

ImageIterator must refer to a large enough image.

    uint16 sampleFormat, samplesPerPixel, bitsPerSample, photometric;
           
    TIFFGetField(tiff, TIFFTAG_SAMPLEFORMAT, &sampleFormat);
    TIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samplesPerPixel);
    TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitsPerSample);
    TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric);

    sampleFormat != SAMPLEFORMAT_VOID
    samplesPerPixel == 1
    photometric == PHOTOMETRIC_MINISWHITE ||
       photometric == PHOTOMETRIC_MINISBLACK
    bitsPerSample == 1 || 
       bitsPerSample == 8 || 
       bitsPerSample == 16 || 
       bitsPerSample == 32 || 
       bitsPerSample == 64

This function uses RGBAccessor to write the data. A RGBImageIterator is an iterator which is associated with a RGBAccessor.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class RGBImageIterator, class RGBAccessor>
        void
        tiffToRGBImage(TiffImage * tiff, RGBImageIterator iter, RGBAccessor a)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class RGBImageIterator, class RGBAccessor>
        void
        tiffToRGBImage(TiffImage * tiff, pair<RGBImageIterator, RGBAccessor> dest)
    }

Usage:

#include <vigra/tiff.hxx>

    uint32 w, h;
    uint16 photometric
    TiffImage * tiff = TIFFOpen("tiffimage.tiff", "r");
    TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &w);
    TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &h);
    TIFFGetField(tiff_, TIFFTAG_PHOTOMETRIC, &photometric);
        
    if(photometric != PHOTOMETRIC_RGB &&
       photometric != PHOTOMETRIC_PALETTE)
    {
        // not an RGB image - handle error
    }
    
    vigra::BRGBImage img(w, h);
    
    vigra::tiffToRGBImage(tiff, destImage(img));
    
    TIFFClose(tiff);

Required Interface:

    ImageIterator upperleft;
    <unsigned char, short, long, float, double> rvalue, gvalue, bvalue;
    
    RGBAccessor accessor;
                           
    accessor.setRed(rvalue, upperleft);
    accessor.setGreen(gvalue, upperleft);
    accessor.setBlue(bvalue, upperleft);

Preconditions:

ImageIterator must refer to a large enough image.

    uint16 sampleFormat, samplesPerPixel, bitsPerSample, photometric;
           
    TIFFGetField(tiff, TIFFTAG_SAMPLEFORMAT, &sampleFormat);
    TIFFGetField(tiff, TIFFTAG_SAMPLESPERPIXEL, &samplesPerPixel);
    TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitsPerSample);
    TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric);

    sampleFormat != SAMPLEFORMAT_VOID
    samplesPerPixel == 3 // unlass photometric == PHOTOMETRIC_PALETTE
    photometric == PHOTOMETRIC_RGB ||
       photometric == PHOTOMETRIC_PALETTE
    bitsPerSample == 1 || 
       bitsPerSample == 8 || 
       bitsPerSample == 16 || 
       bitsPerSample == 32 || 
       bitsPerSample == 64

Type and size of the TiffImage are determined by the input image. Currently, the function can create scalar images and RGB images of type unsigned char, short, int, float, and double. This function uses accessors to read the data.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class ImageIterator, class Accessor>
        TiffImage *
        createTiffImage(ImageIterator upperleft, ImageIterator lowerright, 
                        Accessor a)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class ImageIterator, class Accessor>
        TiffImage *
        createTiffImage(triple<ImageIterator, ImageIterator, Accessor> src)
    }

Usage:

#include <vigra/tiff.hxx>

    vigra::BImage img(width, height);
    
    ...
    
    TiffImage * tiff = TIFFOpen(("tiffimage.tiff", "w");

    vigra::createTiffImage(srcImageRange(img), tiff);

    TIFFClose(tiff);   // implicitly writes the image to the disk

Required Interface:

    ImageIterator upperleft;
    Accessor accessor;
                           
    accessor(upperleft);   // result written into TiffImage

Type and size of the TiffImage are determined by the input image (may be one of unsigned char, short, int, float, or double). This function uses accessors to read the data.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class ImageIterator, class Accessor>
        TiffImage *
        createScalarTiffImage(ImageIterator upperleft, ImageIterator lowerright, 
                  Accessor a)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class ImageIterator, class Accessor>
        TiffImage *
        createScalarTiffImage(triple<ImageIterator, ImageIterator, Accessor> src)
    }

Usage:

#include <vigra/tiff.hxx>

    vigra::BImage img(width, height);
    
    ...
    
    TiffImage * tiff = TIFFOpen(("tiffimage.tiff", "w");

    vigra::createScalarTiffImage(srcImageRange(img), tiff);

    TIFFClose(tiff);   // implicitly writes the image to the disk

Required Interface:

    ImageIterator upperleft;
    Accessor accessor;
                           
    accessor(upperleft);   // result written into TiffImage

Type and size of the TiffImage are determined by the input image (may be one of unsigned char, int, float, or double). This function uses RGBAccessor to read the data. A RGBImageIterator is an iterator that is associated with a RGBAccessor.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class RGBImageIterator, class RGBAccessor>
        TiffImage *
        createRGBTiffImage(RGBImageIterator upperleft, RGBImageIterator lowerright,
                   RGBAccessor a)
                }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class RGBImageIterator, class RGBAccessor>
        TiffImage *
        createRGBTiffImage(triple<RGBImageIterator, RGBImageIterator, RGBAccessor> src)
    }

Usage:

#include <vigra/tiff.hxx>

    vigra::BRGBImage img(width, height);
    
    ...
    
    TiffImage * tiff = TIFFOpen(("tiffimage.tiff", "w");

    vigra::createRGBTiffImage(srcImageRange(img), tiff);

    TIFFClose(tiff);   // implicitly writes the image to the disk

Required Interface:

    ImageIterator upperleft;
    RGBAccessor accessor;
                           
    accessor.red(upperleft);     // result written into TiffImage
    accessor.green(upperleft);   // result written into TiffImage
    accessor.blue(upperleft);    // result written into TiffImage

The transformation given by the functor is applied to every source pixel and the result written into the corresponding destination pixel. The function uses accessors to access the pixel data. Note that the unary functors of the STL can be used in addition to the functors specifically defined in Functors to Transform Images. Creation of new functors is easiest by using Functor Expressions.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
                  class DestImageIterator, class DestAccessor, class Functor>
        void
        transformImage(SrcImageIterator src_upperleft,
               SrcImageIterator src_lowerright, SrcAccessor sa,
               DestImageIterator dest_upperleft, DestAccessor da,
               Functor const & f)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
                  class DestImageIterator, class DestAccessor, class Functor>
        void
        transformImage(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
               pair<DestImageIterator, DestAccessor> dest,
               Functor const & f)
    }

Usage:

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

    #include <cmath>         // for sqrt()

    vigra::transformImage(srcImageRange(src),
                          destImage(dest),
                          (double(*)(double))&std::sqrt );

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator      dest_upperleft;
    SrcImageIterator::row_iterator sx = src_upperleft.rowIterator();
    DestImageIterator::row_iterator dx = dest_upperleft.rowIterator();

    SrcAccessor src_accessor;
    DestAccessor dest_accessor;

    Functor functor;

    dest_accessor.set(functor(src_accessor(sx)), dx);

The transformation given by the functor is applied to every source pixel in the ROI (i.e. when the return vlaue of the mask's accessor is not zero) and the result is written into the corresponding destination pixel. The function uses accessors to access the pixel data. Note that the unary functors of the STL can be used in addition to the functors specifically defined in Functors to Transform Images. Creation of new functors is easiest by using Functor Expressions.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
                  class MaskImageIterator, class MaskAccessor,
                  class DestImageIterator, clas DestAccessor,
                  class Functor>
        void
        transformImageIf(SrcImageIterator src_upperleft,
                         SrcImageIterator src_lowerright, SrcAccessor sa,
                         MaskImageIterator mask_upperleft, MaskAccessor ma,
                         DestImageIterator dest_upperleft, DestAccessor da,
                         Functor const & f)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
                  class MaskImageIterator, class MaskAccessor,
                  class DestImageIterator, clas DestAccessor,
                  class Functor>
        void
        transformImageIf(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
                         pair<MaskImageIterator, MaskAccessor> mask,
                         pair<DestImageIterator, DestAccessor> dest,
                         Functor const & f)
    }

Usage:

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

    #include <cmath>         // for sqrt()

    vigra::transformImageIf(srcImageRange(src),
                            maskImage(mask),
                            destImage(dest),
                            (double(*)(double))&std::sqrt );

Required Interface:

    SrcImageIterator src_upperleft, src_lowerright;
    DestImageIterator  dest_upperleft;
    MaskImageIterator mask_upperleft;
    SrcImageIterator::row_iterator sx = src_upperleft.rowIterator();
    MaskImageIterator::row_iterator mx = mask_upperleft.rowIterator();
    DestImageIterator::row_iterator dx = dest_upperleft.rowIterator();

    SrcAccessor src_accessor;
    DestAccessor dest_accessor;
    MaskAccessor mask_accessor;
    Functor functor;

    if(mask_accessor(mx))
       dest_accessor.set(functor(src_accessor(sx)), dx);

The gradient and the function represented by Functor f are calculated in one go: for each location, the symmetric difference in x- and y-directions (asymmetric difference at the image borders) are passed to the given functor, and the result is written the destination image. Functors to be used with this function include MagnitudeFunctor and RGBGradientMagnitudeFunctor.

Declarations:

pass arguments explicitly:

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
                  class DestImageIterator, class DestAccessor, class Functor>
        void
        gradientBasedTransform(SrcImageIterator srcul, SrcImageIterator srclr, SrcAccessor sa,
                               DestImageIterator destul, DestAccessor da, Functor const & f)
    }

use argument objects in conjunction with Argument Object Factories :

    namespace vigra {
        template <class SrcImageIterator, class SrcAccessor,
                  class DestImageIterator, class DestAccessor, class Functor>
        void
        gradientBasedTransform(triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
                               pair<DestImageIterator, DestAccessor> dest, Functor const & const & f)
    }

Usage:

#include <vigra/transformimage.hxx>

    vigra::FImage src(w,h), magnitude(w,h);
    ...

    gradientBasedTransform(srcImageRange(src), destImage(magnitude),
                                vigra::MagnitudeFunctor<float>());

Required Interface:

    SrcImageIterator is, isend;
    DestImageIterator id;

    SrcAccessor src_accessor;
    DestAccessor dest_accessor;

    typename NumericTraits<typename SrcAccessor::value_type>::RealPromote
        diffx, diffy;

    diffx = src_accessor(is, Diff2D(-1,0)) - src_accessor(is, Diff2D(1,0));
    diffy = src_accessor(is, Diff2D(0,-1)) - src_accessor(is, Diff2D(0,1));

    Functor f;

    dest_accessor.set(f(diffx, diffy), id);

Definition at line 1242 of file fftw3.hxx.

{
    detail::fourierTransformImpl(sul, slr, src, dul, dest, FFTW_FORWARD);
}


Generated by  Doxygen 1.6.0   Back to index