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

details vigra/symmetry.hxx VIGRA

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.3, Aug 18 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.3 (18 Aug 2005)