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

| vigra/symmetry.hxx |
--- | --- | ---

    00001 /************************************************************************/
    00002 /*                                                                      */
    00003 /*               Copyright 1998-2002 by Ullrich Koethe                  */
    00004 /*       Cognitive Systems Group, University of Hamburg, Germany        */
    00005 /*                                                                      */
    00006 /*    This file is part of the VIGRA computer vision library.           */
    00007 /*    ( Version 1.3.2, Jan 27 2005 )                                    */
    00008 /*    You may use, modify, and distribute this software according       */
    00009 /*    to the terms stated in the LICENSE file included in               */
    00010 /*    the VIGRA distribution.                                           */
    00011 /*                                                                      */
    00012 /*    The VIGRA Website is                                              */
    00013 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
    00014 /*    Please direct questions, bug reports, and contributions to        */
    00015 /*        koethe@informatik.uni-hamburg.de                              */
    00016 /*                                                                      */
    00017 /*  THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR          */
    00018 /*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED      */
    00019 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
    00020 /*                                                                      */
    00021 /************************************************************************/
    00022
    00023 #ifndef VIGRA_SYMMETRY_HXX
    00024 #define VIGRA_SYMMETRY_HXX
    00025
    00026 #include <vigra/utilities.hxx>
    00027 #include <vigra/numerictraits.hxx>
    00028 #include <vigra/stdimage.hxx>
    00029 #include <vigra/convolution.hxx>
    00030
    00031 namespace vigra {
    00032
    00033 /** \addtogroup SymmetryDetection Symmetry Detection
    00034     Measure the local symmetry at each pixel.
    00035 */
    00036 //@{
    00037
    00038 /********************************************************/
    00039 /*                                                      */
    00040 /*                 radialSymmetryTransform              */
    00041 /*                                                      */
    00042 /********************************************************/
    00043
    00044 /** \brief Find centers of radial symmetry in an image.
    00045
    00046     This algorithm implements the Fast Radial Symmetry Transform according to
    00047     [G. Loy, A. Zelinsky: <em> "A Fast Radial Symmetry Transform for Detecting
    00048     Points of Interest"</em>, in: A. Heyden et al. (Eds.): Proc. of 7th European
    00049     Conf. on Computer Vision, Part 1, pp. 358-368, Springer LNCS 2350, 2002].
    00050     Minima of the algorithm response mark dark blobs, maxima correspond to light blobs.
    00051     The "radial strictness parameter" is fixed at <TT>alpha</tt> = 2.0, the
    00052     spatial spreading of the raw response is done by a Gaussian convolution
    00053     at <tt>0.25*scale</TT> (these values are recommendations from the paper).
    00054     Loy and Zelinsky additionally propose to add the operator response from several
    00055     scales (see usage example below).
    00056
    00057     <b> Declarations:</b>
    00058
    00059     pass arguments explicitly:
    00060     \code
    00061     namespace vigra {
    00062         template <class SrcIterator, class SrcAccessor,
    00063               class DestIterator, class DestAccessor>
    00064         void
    00065         radialSymmetryTransform(SrcIterator sul, SrcIterator slr, SrcAccessor as,
    00066                    DestIterator dul, DestAccessor ad,
    00067                    double scale)
    00068     }
    00069     \endcode
    00070
    00071     use argument objects in conjunction with \ref ArgumentObjectFactories:
    00072     \code
    00073     namespace vigra {
    00074         template <class SrcIterator, class SrcAccessor,
    00075               class DestIterator, class DestAccessor>
    00076         inline
    00077         void radialSymmetryTransform(
    00078                triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00079                pair<DestIterator, DestAccessor> dest,
    00080                double scale)
    00081     }
    00082     \endcode
    00083
    00084     <b> Usage:</b>
    00085
    00086         <b>\#include</b> "<a href="symmetry_8hxx-source.html">vigra/symmetry.hxx</a>"<br>
    00087     Namespace: vigra
    00088
    00089     \code
    00090     vigra::BImage src(w,h), centers(w,h);
    00091     vigra::FImage symmetry(w,h);
    00092
    00093     // empty result image
    00094     centers.init(128);
    00095     symmetry.init(0.0);
    00096
    00097     // input width of edge detection filter
    00098     for(double scale = 2.0; scale <= 8.0; scale *= 2.0)
    00099     {
    00100         vigra::FImage tmp(w,h);
    00101
    00102         // find centers of symmetry
    00103         radialSymmetryTransform(srcImageRange(src), destImage(tmp), scale);
    00104
    00105         combineTwoImages(srcImageRange(symmetry), srcImage(tmp), destImage(symmetry),
    00106                          std::plus<float>());
    00107     }
    00108
    00109     localMinima(srcImageRange(symmetry), destImage(centers), 0);
    00110     localMaxima(srcImageRange(symmetry), destImage(centers), 255);
    00111     \endcode
    00112
    00113     <b> Required Interface:</b>
    00114
    00115     \code
    00116     SrcImageIterator src_upperleft, src_lowerright;
    00117     DestImageIterator dest_upperleft;
    00118
    00119     SrcAccessor src_accessor;
    00120     DestAccessor dest_accessor;
    00121
    00122     // SrcAccessor::value_type must be a built-in type
    00123     SrcAccessor::value_type u = src_accessor(src_upperleft);
    00124
    00125     dest_accessor.set(u, dest_upperleft);
    00126     \endcode
    00127 */
    00128 template <class SrcIterator, class SrcAccessor,
    00129           class DestIterator, class DestAccessor>
    00130 void
    00131 radialSymmetryTransform(SrcIterator sul, SrcIterator slr, SrcAccessor as,
    00132                DestIterator dul, DestAccessor ad,
    00133         double scale)
    00134 {
    00135     vigra_precondition(scale > 0.0,
    00136                  "radialSymmetryTransform(): Scale must be > 0");
    00137
    00138     int w = slr.x - sul.x;
    00139     int h = slr.y - sul.y;
    00140
    00141     if(w <= 0 || h <= 0) return;
    00142
    00143     typedef typename
    00144         NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType;
    00145
    00146     typedef BasicImage<TmpType> TmpImage;
    00147     typedef typename TmpImage::Iterator TmpIterator;
    00148
    00149     TmpImage gx(w,h);
    00150     TmpImage gy(w,h);
    00151     IImage   orientationCounter(w,h);
    00152     TmpImage magnitudeAccumulator(w,h);
    00153
    00154     gaussianGradient(srcIterRange(sul, slr, as),
    00155                      destImage(gx), destImage(gy),
    00156                      scale);
    00157
    00158     orientationCounter.init(0);
    00159     magnitudeAccumulator.init(NumericTraits<TmpType>::zero());
    00160
    00161     TmpIterator gxi = gx.upperLeft();
    00162     TmpIterator gyi = gy.upperLeft();
    00163     int y;
    00164     for(y=0; y<h; ++y, ++gxi.y, ++gyi.y)
    00165     {
    00166         typename TmpIterator::row_iterator gxr = gxi.rowIterator();
    00167         typename TmpIterator::row_iterator gyr = gyi.rowIterator();
    00168
    00169         for(int x = 0; x<w; ++x, ++gxr, ++gyr)
    00170         {
    00171             double angle = VIGRA_CSTD::atan2(-*gyr, *gxr);
    00172             double magnitude = VIGRA_CSTD::sqrt(*gxr * *gxr + *gyr * *gyr);
    00173
    00174             if(magnitude < NumericTraits<TmpType>::epsilon()*10.0)
    00175                 continue;
    00176
    00177             int dx = NumericTraits<int>::fromRealPromote(scale * VIGRA_CSTD::cos(angle));
    00178             int dy = NumericTraits<int>::fromRealPromote(scale * VIGRA_CSTD::sin(angle));
    00179
    00180             int xx = x + dx;
    00181             int yy = y - dy;
    00182
    00183             if(xx >= 0 && xx < w && yy >= 0 && yy < h)
    00184             {
    00185                 orientationCounter(xx, yy) += 1;
    00186                 magnitudeAccumulator(xx, yy) += magnitude;
    00187             }
    00188
    00189             xx = x - dx;
    00190             yy = y + dy;
    00191
    00192             if(xx >= 0 && xx < w && yy >= 0 && yy < h)
    00193             {
    00194                 orientationCounter(xx, yy) -= 1;
    00195                 magnitudeAccumulator(xx, yy) -= magnitude;
    00196             }
    00197         }
    00198     }
    00199
    00200     int maxOrientation = 0;
    00201     TmpType maxMagnitude = NumericTraits<TmpType>::zero();
    00202
    00203     for(y=0; y<h; ++y)
    00204     {
    00205         for(int x = 0; x<w; ++x)
    00206         {
    00207             int o = VIGRA_CSTD::abs(orientationCounter(x,y));
    00208
    00209             if(o > maxOrientation)
    00210                 maxOrientation = o;
    00211
    00212             TmpType m = VIGRA_CSTD::abs(magnitudeAccumulator(x,y));
    00213
    00214             if(m > maxMagnitude)
    00215                 maxMagnitude = m;
    00216         }
    00217     }
    00218
    00219     for(y=0; y<h; ++y)
    00220     {
    00221         for(int x = 0; x<w; ++x)
    00222         {
    00223             double o = (double)orientationCounter(x, y) / maxOrientation;
    00224             magnitudeAccumulator(x, y) = o * o * magnitudeAccumulator(x, y) / maxMagnitude;
    00225         }
    00226     }
    00227
    00228     gaussianSmoothing(srcImageRange(magnitudeAccumulator), destIter(dul, ad), 0.25*scale);
    00229 }
    00230
    00231 template <class SrcIterator, class SrcAccessor,
    00232           class DestIterator, class DestAccessor>
    00233 inline
    00234 void radialSymmetryTransform(
    00235            triple<SrcIterator, SrcIterator, SrcAccessor> src,
    00236        pair<DestIterator, DestAccessor> dest,
    00237        double scale)
    00238 {
    00239     radialSymmetryTransform(src.first, src.second, src.third,
    00240                             dest.first, dest.second,
    00241                 scale);
    00242 }
    00243
    00244
    00245 //@}
    00246
    00247 } // namespace vigra
    00248
    00249
    00250 #endif /* VIGRA_SYMMETRY_HXX */

© Ullrich Köthe (koethe@informatik.uni-hamburg.de) Cognitive Systems Group, University of Hamburg, Germany | html generated using doxygen and Python VIGRA 1.3.2 (27 Jan 2005)