[ 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.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) |
html generated using doxygen and Python
|