vigra - Edge Detection

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

| Edge Detection |

## Classes
class | Edgel
## Functions
template<... >
void | beautifyCrackEdgeImage (...)
| Beautify crack edge image for visualization.
template<... >
void | cannyEdgeImage (...)
| Detect and mark edges in an edge image using Canny's algorithm.
template<... >
void | cannyEdgeImageFromGradWithThinning (...)
| Detect and mark edges in an edge image using Canny's algorithm.
template<... >
void | cannyEdgeImageWithThinning (...)
| Detect and mark edges in an edge image using Canny's algorithm.
template<... >
void | cannyEdgelList (...)
| Simple implementation of Canny's edge detector.
template<... >
void | cannyEdgelList3x3 (...)
| Improved implementation of Canny's edge detector.
template<... >
void | cannyEdgelList3x3Threshold (...)
| Improved implementation of Canny's edge detector with thresholding.
template<... >
void | cannyEdgelListThreshold (...)
| Canny's edge detector with thresholding.
template<... >
void | closeGapsInCrackEdgeImage (...)
| Close one-pixel wide gaps in a cell grid edge image.
template<... >
void | differenceOfExponentialCrackEdgeImage (...)
| Detect and mark edges in a crack edge image using the Shen/Castan zero-crossing detector.
template<... >
void | differenceOfExponentialEdgeImage (...)
| Detect and mark edges in an edge image using the Shen/Castan zero-crossing detector.
template<... >
void | removeShortEdges (...)
| Remove short edges from an edge image.

## Detailed Description

Edge detectors based on first and second derivatives, and related post-processing.

## Function Documentation

void vigra::differenceOfExponentialEdgeImage | ( |  | ... | ) |

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

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

Examples:
  edge.cxx.

void vigra::differenceOfExponentialCrackEdgeImage | ( |  | ... | ) |

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

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 conforms 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

void vigra::removeShortEdges | ( |  | ... | ) |

Remove short edges from an edge image.

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

void vigra::closeGapsInCrackEdgeImage | ( |  | ... | ) |

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

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

void vigra::beautifyCrackEdgeImage | ( |  | ... | ) |

Beautify crack edge image for visualization.

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

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

Therefore, this algorithm should only be applied as a visualization 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);

void vigra::cannyEdgelList | ( |  | ... | ) |

Simple implementation of Canny's edge detector.

The function can be called in two modes: If you pass a 'scale', it is assumed that the original image is scalar, and the Gaussian gradient is internally computed at the given 'scale'. If the function is called without scale parameter, it is assumed that the given image already contains the gradient (i.e. its value_type must be a vector of length 2).

On the basis of the gradient image, a simple non-maxima suppression 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 octants). 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 {
            // compute edgels from a gradient image
            template <class SrcIterator, class SrcAccessor, class BackInsertable>
            void
            cannyEdgelList(SrcIterator ul, SrcIterator lr, SrcAccessor src,
                           BackInsertable & edgels);

            // compute edgels from a scalar image (determine gradient internally at 'scale')
            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 {
            // compute edgels from a gradient image
            template <class SrcIterator, class SrcAccessor, class BackInsertable>
            void
            cannyEdgelList(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                           BackInsertable & edgels);

            // compute edgels from a scalar image (determine gradient internally at 'scale')
            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

void vigra::cannyEdgelListThreshold | ( |  | ... | ) |

Canny's edge detector with thresholding.

This function works exactly like cannyEdgelList(), but you also pass a threshold for the minimal gradient magnitude, so that edgels whose strength is below the threshold are not inserted into the edgel list.

Declarations:

pass arguments explicitly:

        namespace vigra {
            // compute edgels from a gradient image
            template <class SrcIterator, class SrcAccessor,
                      class BackInsertable, class GradValue>
            void
            cannyEdgelListThreshold(SrcIterator ul, SrcIterator lr, SrcAccessor src,
                                    BackInsertable & edgels, GradValue grad_threshold);

            // compute edgels from a scalar image (determine gradient internally at 'scale')
            template <class SrcIterator, class SrcAccessor,
                      class BackInsertable, class GradValue>
            void
            cannyEdgelListThreshold(SrcIterator ul, SrcIterator lr, SrcAccessor src,
                                    BackInsertable & edgels, double scale, GradValue grad_threshold);
        }

use argument objects in conjunction with Argument Object Factories :

        namespace vigra {
            // compute edgels from a gradient image
            template <class SrcIterator, class SrcAccessor,
                      class BackInsertable, class GradValue>
            void
            cannyEdgelListThreshold(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                                    BackInsertable & edgels, GradValue grad_threshold);

            // compute edgels from a scalar image (determine gradient internally at 'scale')
            template <class SrcIterator, class SrcAccessor,
                      class BackInsertable, class GradValue>
            void
            cannyEdgelListThreshold(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                                    BackInsertable & edgels, double scale, GradValue grad_threshold);
        }

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, only considering gradient above 2.0
        vigra::cannyEdgelListThreshold(srcImageRange(src), edgels, 0.8, 2.0);

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

void vigra::cannyEdgeImage | ( |  | ... | ) |

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

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

Examples:
  edge.cxx.

void vigra::cannyEdgeImageFromGradWithThinning | ( |  | ... | ) |

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

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

void vigra::cannyEdgeImageWithThinning | ( |  | ... | ) |

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

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

void vigra::cannyEdgelList3x3 | ( |  | ... | ) |

Improved implementation of Canny's edge detector.

This operator first computes pixels which are crossed by the edge using cannyEdgeImageWithThinning(). The gradient magnitudes 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.

The function can be called in two modes: If you pass a 'scale', it is assumed that the original image is scalar, and the Gaussian gradient is internally computed at the given 'scale'. If the function is called without scale parameter, it is assumed that the given image already contains the gradient (i.e. its value_type must be a vector of length 2).

Declarations:

pass arguments explicitly:

        namespace vigra {
            // compute edgels from a gradient image
            template <class SrcIterator, class SrcAccessor, class BackInsertable>
            void cannyEdgelList3x3(SrcIterator ul, SrcIterator lr, SrcAccessor src,
                                   BackInsertable & edgels);

            // compute edgels from a scalar image (determine gradient internally at 'scale')
            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 {
            // compute edgels from a gradient image
            template <class SrcIterator, class SrcAccessor, class BackInsertable>
            void
            cannyEdgelList3x3(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                              BackInsertable & edgels);

            // compute edgels from a scalar image (determine gradient internally at 'scale')
            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

void vigra::cannyEdgelList3x3Threshold | ( |  | ... | ) |

Improved implementation of Canny's edge detector with thresholding.

This function works exactly like cannyEdgelList3x3(), but you also pass a threshold for the minimal gradient magnitude, so that edgels whose strength is below the threshold are not inserted into the edgel list.

Declarations:

pass arguments explicitly:

        namespace vigra {
            // compute edgels from a gradient image
            template <class SrcIterator, class SrcAccessor,
                      class BackInsertable, class GradValue>
            void
            cannyEdgelList3x3Threshold(SrcIterator ul, SrcIterator lr, SrcAccessor src,
                                       BackInsertable & edgels, GradValue grad_thresh);

            // compute edgels from a scalar image (determine gradient internally at 'scale')
            template <class SrcIterator, class SrcAccessor,
                      class BackInsertable, class GradValue>
            void
            cannyEdgelList3x3Threshold(SrcIterator ul, SrcIterator lr, SrcAccessor src,
                                       BackInsertable & edgels, double scale, GradValue grad_thresh);
        }

use argument objects in conjunction with Argument Object Factories :

        namespace vigra {
            // compute edgels from a gradient image
            template <class SrcIterator, class SrcAccessor,
                      class BackInsertable, class GradValue>
            void
            cannyEdgelList3x3Threshold(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                                       BackInsertable & edgels, GradValue grad_thresh);

            // compute edgels from a scalar image (determine gradient internally at 'scale')
            template <class SrcIterator, class SrcAccessor,
                      class BackInsertable, class GradValue>
            void
            cannyEdgelList3x3Threshold(triple<SrcIterator, SrcIterator, SrcAccessor> src,
                                       BackInsertable & edgels, double scale, GradValue grad_thresh);
        }

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

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