[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]
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) |
html generated using doxygen and Python
|