[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | 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 /*    The VIGRA Website is                                              */
00008 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
00009 /*    Please direct questions, bug reports, and contributions to        */
00010 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
00011 /*        vigra@informatik.uni-hamburg.de                               */
00012 /*                                                                      */
00013 /*    Permission is hereby granted, free of charge, to any person       */
00014 /*    obtaining a copy of this software and associated documentation    */
00015 /*    files (the "Software"), to deal in the Software without           */
00016 /*    restriction, including without limitation the rights to use,      */
00017 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
00018 /*    sell copies of the Software, and to permit persons to whom the    */
00019 /*    Software is furnished to do so, subject to the following          */
00020 /*    conditions:                                                       */
00021 /*                                                                      */
00022 /*    The above copyright notice and this permission notice shall be    */
00023 /*    included in all copies or substantial portions of the             */
00024 /*    Software.                                                         */
00025 /*                                                                      */
00026 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
00027 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
00028 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
00029 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
00030 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
00031 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
00032 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
00033 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */                
00034 /*                                                                      */
00035 /************************************************************************/
00036 
00037 #ifndef VIGRA_SYMMETRY_HXX
00038 #define VIGRA_SYMMETRY_HXX
00039 
00040 #include "utilities.hxx"
00041 #include "numerictraits.hxx"
00042 #include "stdimage.hxx"
00043 #include "convolution.hxx"
00044 
00045 namespace vigra {
00046 
00047 /** \addtogroup SymmetryDetection Symmetry Detection
00048     Measure the local symmetry at each pixel.
00049 */
00050 //@{
00051 
00052 /********************************************************/
00053 /*                                                      */
00054 /*                 radialSymmetryTransform              */
00055 /*                                                      */
00056 /********************************************************/
00057 
00058 /** \brief Find centers of radial symmetry in an image.
00059 
00060     This algorithm implements the Fast Radial Symmetry Transform according to
00061     [G. Loy, A. Zelinsky: <em> "A Fast Radial Symmetry Transform for Detecting
00062     Points of Interest"</em>, in: A. Heyden et al. (Eds.): Proc. of 7th European
00063     Conf. on Computer Vision, Part 1, pp. 358-368, Springer LNCS 2350, 2002].
00064     Minima of the algorithm response mark dark blobs, maxima correspond to light blobs.
00065     The "radial strictness parameter" is fixed at <TT>alpha</tt> = 2.0, the
00066     spatial spreading of the raw response is done by a Gaussian convolution
00067     at <tt>0.25*scale</TT> (these values are recommendations from the paper).
00068     Loy and Zelinsky additionally propose to add the operator response from several
00069     scales (see usage example below).
00070 
00071     <b> Declarations:</b>
00072 
00073     pass arguments explicitly:
00074     \code
00075     namespace vigra {
00076         template <class SrcIterator, class SrcAccessor,
00077                   class DestIterator, class DestAccessor>
00078         void
00079         radialSymmetryTransform(SrcIterator sul, SrcIterator slr, SrcAccessor as,
00080                                 DestIterator dul, DestAccessor ad,
00081                                 double scale)
00082     }
00083     \endcode
00084 
00085     use argument objects in conjunction with \ref ArgumentObjectFactories :
00086     \code
00087     namespace vigra {
00088         template <class SrcIterator, class SrcAccessor,
00089                   class DestIterator, class DestAccessor>
00090         inline
00091         void radialSymmetryTransform(
00092                triple<SrcIterator, SrcIterator, SrcAccessor> src,
00093                pair<DestIterator, DestAccessor> dest,
00094                double scale)
00095     }
00096     \endcode
00097 
00098     <b> Usage:</b>
00099 
00100         <b>\#include</b> <<a href="symmetry_8hxx-source.html">vigra/symmetry.hxx</a>><br>
00101     Namespace: vigra
00102 
00103     \code
00104     vigra::BImage src(w,h), centers(w,h);
00105     vigra::FImage symmetry(w,h);
00106 
00107     // empty result image
00108     centers.init(128);
00109     symmetry.init(0.0);
00110 
00111     // input width of edge detection filter
00112     for(double scale = 2.0; scale <= 8.0; scale *= 2.0)
00113     {
00114         vigra::FImage tmp(w,h);
00115 
00116         // find centers of symmetry
00117         radialSymmetryTransform(srcImageRange(src), destImage(tmp), scale);
00118 
00119         combineTwoImages(srcImageRange(symmetry), srcImage(tmp), destImage(symmetry),
00120                          std::plus<float>());
00121     }
00122 
00123     localMinima(srcImageRange(symmetry), destImage(centers), 0);
00124     localMaxima(srcImageRange(symmetry), destImage(centers), 255);
00125     \endcode
00126 
00127     <b> Required Interface:</b>
00128 
00129     \code
00130     SrcImageIterator src_upperleft, src_lowerright;
00131     DestImageIterator dest_upperleft;
00132 
00133     SrcAccessor src_accessor;
00134     DestAccessor dest_accessor;
00135 
00136     // SrcAccessor::value_type must be a built-in type
00137     SrcAccessor::value_type u = src_accessor(src_upperleft);
00138 
00139     dest_accessor.set(u, dest_upperleft);
00140     \endcode
00141 */
00142 doxygen_overloaded_function(template <...> void radialSymmetryTransform)
00143 
00144 template <class SrcIterator, class SrcAccessor,
00145           class DestIterator, class DestAccessor>
00146 void
00147 radialSymmetryTransform(SrcIterator sul, SrcIterator slr, SrcAccessor as,
00148                DestIterator dul, DestAccessor ad,
00149         double scale)
00150 {
00151     vigra_precondition(scale > 0.0,
00152                  "radialSymmetryTransform(): Scale must be > 0");
00153 
00154     int w = slr.x - sul.x;
00155     int h = slr.y - sul.y;
00156 
00157     if(w <= 0 || h <= 0) return;
00158 
00159     typedef typename
00160         NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType;
00161 
00162     typedef BasicImage<TmpType> TmpImage;
00163     typedef typename TmpImage::Iterator TmpIterator;
00164 
00165     TmpImage gx(w,h);
00166     TmpImage gy(w,h);
00167     IImage   orientationCounter(w,h);
00168     TmpImage magnitudeAccumulator(w,h);
00169 
00170     gaussianGradient(srcIterRange(sul, slr, as),
00171                      destImage(gx), destImage(gy),
00172                      scale);
00173 
00174     orientationCounter.init(0);
00175     magnitudeAccumulator.init(NumericTraits<TmpType>::zero());
00176 
00177     TmpIterator gxi = gx.upperLeft();
00178     TmpIterator gyi = gy.upperLeft();
00179     int y;
00180     for(y=0; y<h; ++y, ++gxi.y, ++gyi.y)
00181     {
00182         typename TmpIterator::row_iterator gxr = gxi.rowIterator();
00183         typename TmpIterator::row_iterator gyr = gyi.rowIterator();
00184 
00185         for(int x = 0; x<w; ++x, ++gxr, ++gyr)
00186         {
00187             double angle = VIGRA_CSTD::atan2(-*gyr, *gxr);
00188             double magnitude = VIGRA_CSTD::sqrt(*gxr * *gxr + *gyr * *gyr);
00189 
00190             if(magnitude < NumericTraits<TmpType>::epsilon()*10.0)
00191                 continue;
00192 
00193             int dx = NumericTraits<int>::fromRealPromote(scale * VIGRA_CSTD::cos(angle));
00194             int dy = NumericTraits<int>::fromRealPromote(scale * VIGRA_CSTD::sin(angle));
00195 
00196             int xx = x + dx;
00197             int yy = y - dy;
00198 
00199             if(xx >= 0 && xx < w && yy >= 0 && yy < h)
00200             {
00201                 orientationCounter(xx, yy) += 1;
00202                 magnitudeAccumulator(xx, yy) += magnitude;
00203             }
00204 
00205             xx = x - dx;
00206             yy = y + dy;
00207 
00208             if(xx >= 0 && xx < w && yy >= 0 && yy < h)
00209             {
00210                 orientationCounter(xx, yy) -= 1;
00211                 magnitudeAccumulator(xx, yy) -= magnitude;
00212             }
00213         }
00214     }
00215 
00216     int maxOrientation = 0;
00217     TmpType maxMagnitude = NumericTraits<TmpType>::zero();
00218 
00219     for(y=0; y<h; ++y)
00220     {
00221         for(int x = 0; x<w; ++x)
00222         {
00223             int o = VIGRA_CSTD::abs(orientationCounter(x,y));
00224 
00225             if(o > maxOrientation)
00226                 maxOrientation = o;
00227 
00228             TmpType m = VIGRA_CSTD::abs(magnitudeAccumulator(x,y));
00229 
00230             if(m > maxMagnitude)
00231                 maxMagnitude = m;
00232         }
00233     }
00234 
00235     for(y=0; y<h; ++y)
00236     {
00237         for(int x = 0; x<w; ++x)
00238         {
00239             double o = (double)orientationCounter(x, y) / maxOrientation;
00240             magnitudeAccumulator(x, y) = o * o * magnitudeAccumulator(x, y) / maxMagnitude;
00241         }
00242     }
00243 
00244     gaussianSmoothing(srcImageRange(magnitudeAccumulator), destIter(dul, ad), 0.25*scale);
00245 }
00246 
00247 template <class SrcIterator, class SrcAccessor,
00248           class DestIterator, class DestAccessor>
00249 inline
00250 void radialSymmetryTransform(
00251            triple<SrcIterator, SrcIterator, SrcAccessor> src,
00252        pair<DestIterator, DestAccessor> dest,
00253        double scale)
00254 {
00255     radialSymmetryTransform(src.first, src.second, src.third,
00256                             dest.first, dest.second,
00257                 scale);
00258 }
00259 
00260 
00261 //@}
00262 
00263 } // namespace vigra
00264 
00265 
00266 #endif /* VIGRA_SYMMETRY_HXX */

© 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.6.0 (5 Nov 2009)