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