[ 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 00038 #ifndef VIGRA_CONVOLUTION_HXX 00039 #define VIGRA_CONVOLUTION_HXX 00040 00041 #include <functional> 00042 #include "stdconvolution.hxx" 00043 #include "separableconvolution.hxx" 00044 #include "recursiveconvolution.hxx" 00045 #include "nonlineardiffusion.hxx" 00046 #include "combineimages.hxx" 00047 00048 /** \page Convolution Functions to Convolve Images and Signals 00049 00050 1D and 2D filters, including separable and recursive convolution, and non-linear diffusion 00051 00052 <b>\#include</b> <<a href="convolution_8hxx-source.html">vigra/convolution.hxx</a>><br> 00053 Namespace: vigra 00054 00055 <UL style="list-style-image:url(documents/bullet.gif)"> 00056 <LI> \ref CommonConvolutionFilters 00057 <BR> <em>Short-hands for the most common 2D convolution filters</em> 00058 <LI> \ref MultiArrayConvolutionFilters 00059 <BR> <em>Convolution filters for arbitrary dimensional arrays (MultiArray etc.)</em> 00060 <LI> \ref ResamplingConvolutionFilters 00061 <BR> <em>Resampling convolution filters</em> 00062 <LI> \ref StandardConvolution 00063 <BR> <em>2D non-separable convolution, with and without ROI mask </em> 00064 <LI> \ref vigra::Kernel2D 00065 <BR> <em>Generic 2-dimensional discrete convolution kernel </em> 00066 <LI> \ref SeparableConvolution 00067 <BR> <em>1D convolution and separable filters in 2 dimensions </em> 00068 <LI> \ref vigra::Kernel1D 00069 <BR> <em>Generic 1-dimensional discrete convolution kernel </em> 00070 <LI> \ref RecursiveConvolution 00071 <BR> <em>Recursive filters (1st and 2nd order)</em> 00072 <LI> \ref NonLinearDiffusion 00073 <BR> <em>Edge-preserving smoothing </em> 00074 <LI> \ref BorderTreatmentMode 00075 <BR> <em>Choose between different border treatment modes </em> 00076 <LI> \ref KernelArgumentObjectFactories 00077 <BR> <em>Factory functions to create argument objects to simplify passing kernels</em> 00078 </UL> 00079 */ 00080 00081 /** \page KernelArgumentObjectFactories Kernel Argument Object Factories 00082 00083 These factory functions allow to create argument objects for 1D 00084 and 2D convolution kernel analogously to 00085 \ref ArgumentObjectFactories for images. 00086 00087 \section Kernel1dFactory kernel1d() 00088 00089 Pass a \ref vigra::Kernel1D to a 1D or separable convolution algorithm. 00090 00091 These factories can be used to create argument objects when we 00092 are given instances or subclasses of \ref vigra::Kernel1D 00093 (analogous to the \ref ArgumentObjectFactories for images). 00094 These factory functions access <TT>kernel.center()</TT>, 00095 <TT>kernel.left()</TT>, <TT>kernel.right()</TT>, <TT>kernel.accessor()</TT>, 00096 and <TT>kernel.borderTreatment()</TT> to obtain the necessary 00097 information. The following factory functions are provided: 00098 00099 <table> 00100 <tr><th bgcolor="#f0e0c0" colspan=2 align=left> 00101 <TT>\ref vigra::Kernel1D "vigra::Kernel1D<SomeType>" kernel;</TT> 00102 </th> 00103 </tr> 00104 <tr><td> 00105 <TT>kernel1d(kernel)</TT> 00106 </td><td> 00107 create argument object from information provided by 00108 kernel 00109 00110 </td></tr> 00111 <tr><td> 00112 <TT>kernel1d(kernel, vigra::BORDER_TREATMENT_CLIP)</TT> 00113 </td><td> 00114 create argument object from information provided by 00115 kernel, but use given border treatment mode 00116 00117 </td></tr> 00118 <tr><td> 00119 <TT>kernel1d(kerneliterator, kernelaccessor,</TT><br> 00120 <TT> kernelleft, kernelright,</TT><br> 00121 <TT> vigra::BORDER_TREATMENT_CLIP)</TT> 00122 </td><td> 00123 create argument object from explicitly given iterator 00124 (pointing to the center of th kernel), accessor, 00125 left and right boundaries, and border treatment mode 00126 00127 </table> 00128 00129 For usage examples see 00130 \ref SeparableConvolution "one-dimensional and separable convolution functions". 00131 00132 \section Kernel2dFactory kernel2d() 00133 00134 Pass a \ref vigra::Kernel2D to a 2D (non-separable) convolution algorithm. 00135 00136 These factories can be used to create argument objects when we 00137 are given instances or subclasses of \ref vigra::Kernel2D 00138 (analogous to the \ref ArgumentObjectFactories for images). 00139 These factory functions access <TT>kernel.center()</TT>, 00140 <TT>kernel.upperLeft()</TT>, <TT>kernel.lowerRight()</TT>, <TT>kernel.accessor()</TT>, 00141 and <TT>kernel.borderTreatment()</TT> to obtain the necessary 00142 information. The following factory functions are provided: 00143 00144 <table> 00145 <tr><th bgcolor="#f0e0c0" colspan=2 align=left> 00146 <TT>\ref vigra::Kernel2D "vigra::Kernel2D<SomeType>" kernel;</TT> 00147 </th> 00148 </tr> 00149 <tr><td> 00150 <TT>kernel2d(kernel)</TT> 00151 </td><td> 00152 create argument object from information provided by 00153 kernel 00154 00155 </td></tr> 00156 <tr><td> 00157 <TT>kernel2d(kernel, vigra::BORDER_TREATMENT_CLIP)</TT> 00158 </td><td> 00159 create argument object from information provided by 00160 kernel, but use given border treatment mode 00161 00162 </td></tr> 00163 <tr><td> 00164 <TT>kernel2d(kerneliterator, kernelaccessor,</TT> 00165 <TT> upperleft, lowerright,</TT> 00166 <TT> vigra::BORDER_TREATMENT_CLIP)</TT> 00167 </td><td> 00168 create argument object from explicitly given iterator 00169 (pointing to the center of th kernel), accessor, 00170 upper left and lower right corners, and border treatment mode 00171 00172 </table> 00173 00174 For usage examples see \ref StandardConvolution "two-dimensional convolution functions". 00175 */ 00176 00177 namespace vigra { 00178 00179 00180 00181 /********************************************************/ 00182 /* */ 00183 /* Common convolution filters */ 00184 /* */ 00185 /********************************************************/ 00186 00187 /** \addtogroup CommonConvolutionFilters Common Filters 00188 00189 These functions calculate common filters by appropriate sequences of calls 00190 to \ref separableConvolveX() and \ref separableConvolveY(). 00191 */ 00192 //@{ 00193 00194 /********************************************************/ 00195 /* */ 00196 /* convolveImage */ 00197 /* */ 00198 /********************************************************/ 00199 00200 /** \brief Apply two separable filters successively, the first in x-direction, 00201 the second in y-direction. 00202 00203 This function is a shorthand for the concatenation of a call to 00204 \ref separableConvolveX() and \ref separableConvolveY() 00205 with the given kernels. 00206 00207 <b> Declarations:</b> 00208 00209 pass arguments explicitly: 00210 \code 00211 namespace vigra { 00212 template <class SrcIterator, class SrcAccessor, 00213 class DestIterator, class DestAccessor, 00214 class T> 00215 void convolveImage(SrcIterator supperleft, 00216 SrcIterator slowerright, SrcAccessor sa, 00217 DestIterator dupperleft, DestAccessor da, 00218 Kernel1D<T> const & kx, Kernel1D<T> const & ky); 00219 } 00220 \endcode 00221 00222 00223 use argument objects in conjunction with \ref ArgumentObjectFactories : 00224 \code 00225 namespace vigra { 00226 template <class SrcIterator, class SrcAccessor, 00227 class DestIterator, class DestAccessor, 00228 class T> 00229 inline void 00230 convolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> src, 00231 pair<DestIterator, DestAccessor> dest, 00232 Kernel1D<T> const & kx, Kernel1D<T> const & ky); 00233 } 00234 \endcode 00235 00236 <b> Usage:</b> 00237 00238 <b>\#include</b> <<a href="convolution_8hxx-source.html">vigra/convolution.hxx</a>> 00239 00240 00241 \code 00242 vigra::FImage src(w,h), dest(w,h); 00243 ... 00244 00245 // implement sobel filter in x-direction 00246 Kernel1D<double> kx, ky; 00247 kx.initSymmetricGradient(); 00248 ky.initBinomial(1); 00249 00250 vigra::convolveImage(srcImageRange(src), destImage(dest), kx, ky); 00251 00252 \endcode 00253 00254 */ 00255 template <class SrcIterator, class SrcAccessor, 00256 class DestIterator, class DestAccessor, 00257 class T> 00258 void convolveImage(SrcIterator supperleft, 00259 SrcIterator slowerright, SrcAccessor sa, 00260 DestIterator dupperleft, DestAccessor da, 00261 Kernel1D<T> const & kx, Kernel1D<T> const & ky) 00262 { 00263 typedef typename 00264 NumericTraits<typename SrcAccessor::value_type>::RealPromote 00265 TmpType; 00266 BasicImage<TmpType> tmp(slowerright - supperleft); 00267 00268 separableConvolveX(srcIterRange(supperleft, slowerright, sa), 00269 destImage(tmp), kernel1d(kx)); 00270 separableConvolveY(srcImageRange(tmp), 00271 destIter(dupperleft, da), kernel1d(ky)); 00272 } 00273 00274 template <class SrcIterator, class SrcAccessor, 00275 class DestIterator, class DestAccessor, 00276 class T> 00277 inline void 00278 convolveImage(triple<SrcIterator, SrcIterator, SrcAccessor> src, 00279 pair<DestIterator, DestAccessor> dest, 00280 Kernel1D<T> const & kx, Kernel1D<T> const & ky) 00281 { 00282 convolveImage(src.first, src.second, src.third, 00283 dest.first, dest.second, kx, ky); 00284 } 00285 00286 /********************************************************/ 00287 /* */ 00288 /* simpleSharpening */ 00289 /* */ 00290 /********************************************************/ 00291 00292 /** \brief Perform simple sharpening function. 00293 00294 This function use \ref convolveImage() with following filter: 00295 00296 \code 00297 -sharpening_factor/16.0, -sharpening_factor/8.0, -sharpening_factor/16.0, 00298 -sharpening_factor/8.0, 1.0+sharpening_factor*0.75, -sharpening_factor/8.0, 00299 -sharpening_factor/16.0, -sharpening_factor/8.0, -sharpening_factor/16.0; 00300 \endcode 00301 00302 and use <TT>BORDER_TREATMENT_REFLECT</TT> as border treatment mode. 00303 00304 <b> Preconditions:</b> 00305 \code 00306 1. sharpening_factor >= 0 00307 2. scale >= 0 00308 \endcode 00309 00310 <b> Declarations:</b> 00311 00312 <b> Declarations:</b> 00313 00314 pass arguments explicitly: 00315 \code 00316 namespace vigra { 00317 template <class SrcIterator, class SrcAccessor, 00318 class DestIterator, class DestAccessor> 00319 void simpleSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc, 00320 DestIterator dest_ul, DestAccessor dest_acc, double sharpening_factor) 00321 00322 } 00323 \endcode 00324 00325 00326 use argument objects in conjunction with \ref ArgumentObjectFactories : 00327 \code 00328 namespace vigra { 00329 template <class SrcIterator, class SrcAccessor, 00330 class DestIterator, class DestAccessor> 00331 inline 00332 void simpleSharpening(triple<SrcIterator, SrcIterator, SrcAccessor> src, 00333 pair<DestIterator, DestAccessor> dest, double sharpening_factor) 00334 { 00335 simpleSharpening(src.first, src.second, src.third, 00336 dest.first, dest.second, sharpening_factor); 00337 } 00338 00339 } 00340 \endcode 00341 00342 <b> Usage:</b> 00343 00344 <b>\#include</b> <<a href="convolution_8hxx-source.html">vigra/convolution.hxx</a>> 00345 00346 00347 \code 00348 vigra::FImage src(w,h), dest(w,h); 00349 ... 00350 00351 // sharpening with sharpening_factor = 0.1 00352 vigra::simpleSharpening(srcImageRange(src), destImage(dest), 0.1); 00353 00354 \endcode 00355 00356 */ 00357 doxygen_overloaded_function(template <...> void simpleSharpening) 00358 00359 template <class SrcIterator, class SrcAccessor, 00360 class DestIterator, class DestAccessor> 00361 void simpleSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc, 00362 DestIterator dest_ul, DestAccessor dest_acc, double sharpening_factor) 00363 { 00364 00365 vigra_precondition(sharpening_factor >= 0.0, 00366 "simpleSharpening(): amount of sharpening must be >= 0."); 00367 00368 Kernel2D<double> kernel; 00369 00370 kernel.initExplicitly(Diff2D(-1,-1), Diff2D(1,1)) = -sharpening_factor/16.0, -sharpening_factor/8.0, -sharpening_factor/16.0, 00371 -sharpening_factor/8.0, 1.0+sharpening_factor*0.75, -sharpening_factor/8.0, 00372 -sharpening_factor/16.0, -sharpening_factor/8.0, -sharpening_factor/16.0; 00373 00374 convolveImage(src_ul, src_lr, src_acc, dest_ul, dest_acc, 00375 kernel.center(), kernel.accessor(), 00376 kernel.upperLeft(), kernel.lowerRight() , BORDER_TREATMENT_REFLECT ); 00377 } 00378 00379 template <class SrcIterator, class SrcAccessor, 00380 class DestIterator, class DestAccessor> 00381 inline 00382 void simpleSharpening(triple<SrcIterator, SrcIterator, SrcAccessor> src, 00383 pair<DestIterator, DestAccessor> dest, double sharpening_factor) 00384 { 00385 simpleSharpening(src.first, src.second, src.third, 00386 dest.first, dest.second, sharpening_factor); 00387 } 00388 00389 00390 /********************************************************/ 00391 /* */ 00392 /* gaussianSharpening */ 00393 /* */ 00394 /********************************************************/ 00395 00396 /** \brief Perform sharpening function with gaussian filter. 00397 00398 00399 This function use the \ref gaussianSmoothing() 00400 at first and scale the source image 00401 (\code src \endcode) with the \code scale \endcode 00402 factor in an temporary image (\code tmp \endcode). At second the new 00403 pixel in the destination image will be with following 00404 formel calculate: 00405 \code 00406 dest = (1 + sharpening_factor)*src - sharpening_factor*tmp 00407 \endcode 00408 00409 <b> Preconditions:</b> 00410 \code 00411 1. sharpening_factor >= 0 00412 2. scale >= 0 00413 \endcode 00414 00415 <b> Declarations:</b> 00416 00417 pass arguments explicitly: 00418 \code 00419 namespace vigra { 00420 template <class SrcIterator, class SrcAccessor, 00421 class DestIterator, class DestAccessor> 00422 void gaussianSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc, 00423 DestIterator dest_ul, DestAccessor dest_acc, double sharpening_factor, 00424 double scale) 00425 } 00426 \endcode 00427 00428 00429 use argument objects in conjunction with \ref ArgumentObjectFactories : 00430 \code 00431 namespace vigra { 00432 template <class SrcIterator, class SrcAccessor, 00433 class DestIterator, class DestAccessor> 00434 void gaussianSharpening(triple<SrcIterator, SrcIterator, SrcAccessor> src, 00435 pair<DestIterator, DestAccessor> dest, double sharpening_factor, 00436 double scale) 00437 } 00438 \endcode 00439 00440 <b> Usage:</b> 00441 00442 <b>\#include</b> <<a href="convolution_8hxx-source.html">vigra/convolution.hxx</a>> 00443 00444 00445 \code 00446 vigra::FImage src(w,h), dest(w,h); 00447 ... 00448 00449 // sharpening with sharpening_factor = 3.0 00450 // smoothing with scale = 0.5 00451 vigra::gaussianSmoothing(srcImageRange(src), destImage(dest), 3.0, 0.5); 00452 00453 \endcode 00454 00455 */ 00456 doxygen_overloaded_function(template <...> void gaussianSharpening) 00457 00458 template <class SrcIterator, class SrcAccessor, 00459 class DestIterator, class DestAccessor> 00460 void gaussianSharpening(SrcIterator src_ul, SrcIterator src_lr, SrcAccessor src_acc, 00461 DestIterator dest_ul, DestAccessor dest_acc, double sharpening_factor, 00462 double scale) 00463 { 00464 vigra_precondition(sharpening_factor >= 0.0, 00465 "gaussianSharpening(): amount of sharpening must be >= 0"); 00466 vigra_precondition(scale >= 0.0, 00467 "gaussianSharpening(): scale parameter should be >= 0."); 00468 00469 typedef typename NumericTraits<typename SrcAccessor::value_type>::RealPromote ValueType; 00470 00471 BasicImage<ValueType> tmp(src_lr - src_ul); 00472 00473 gaussianSmoothing(src_ul, src_lr, src_acc, tmp.upperLeft(), tmp.accessor(), scale); 00474 00475 SrcIterator i_src = src_ul; 00476 DestIterator i_dest = dest_ul; 00477 typename BasicImage<ValueType>::traverser tmp_ul = tmp.upperLeft(); 00478 typename BasicImage<ValueType>::traverser i_tmp = tmp_ul; 00479 typename BasicImage<ValueType>::Accessor tmp_acc = tmp.accessor(); 00480 00481 for(; i_src.y != src_lr.y ; i_src.y++, i_dest.y++, i_tmp.y++ ) 00482 { 00483 for (;i_src.x != src_lr.x ; i_src.x++, i_dest.x++, i_tmp.x++ ) 00484 { 00485 dest_acc.set((1.0 + sharpening_factor)*src_acc(i_src) - sharpening_factor*tmp_acc(i_tmp), i_dest); 00486 } 00487 i_src.x = src_ul.x; 00488 i_dest.x = dest_ul.x; 00489 i_tmp.x = tmp_ul.x; 00490 } 00491 } 00492 00493 template <class SrcIterator, class SrcAccessor, 00494 class DestIterator, class DestAccessor> 00495 void gaussianSharpening(triple<SrcIterator, SrcIterator, SrcAccessor> src, 00496 pair<DestIterator, DestAccessor> dest, double sharpening_factor, 00497 double scale) 00498 { 00499 gaussianSharpening(src.first, src.second, src.third, 00500 dest.first, dest.second, 00501 sharpening_factor, scale); 00502 } 00503 00504 00505 00506 /********************************************************/ 00507 /* */ 00508 /* gaussianSmoothing */ 00509 /* */ 00510 /********************************************************/ 00511 00512 /** \brief Perform isotropic Gaussian convolution. 00513 00514 This function is a shorthand for the concatenation of a call to 00515 \ref separableConvolveX() and \ref separableConvolveY() with a 00516 Gaussian kernel of the given scale. The function uses 00517 <TT>BORDER_TREATMENT_REFLECT</TT>. 00518 00519 <b> Declarations:</b> 00520 00521 pass arguments explicitly: 00522 \code 00523 namespace vigra { 00524 template <class SrcIterator, class SrcAccessor, 00525 class DestIterator, class DestAccessor> 00526 void gaussianSmoothing(SrcIterator supperleft, 00527 SrcIterator slowerright, SrcAccessor sa, 00528 DestIterator dupperleft, DestAccessor da, 00529 double scale); 00530 } 00531 \endcode 00532 00533 00534 use argument objects in conjunction with \ref ArgumentObjectFactories : 00535 \code 00536 namespace vigra { 00537 template <class SrcIterator, class SrcAccessor, 00538 class DestIterator, class DestAccessor> 00539 inline void 00540 gaussianSmoothing(triple<SrcIterator, SrcIterator, SrcAccessor> src, 00541 pair<DestIterator, DestAccessor> dest, 00542 double scale); 00543 } 00544 \endcode 00545 00546 <b> Usage:</b> 00547 00548 <b>\#include</b> <<a href="convolution_8hxx-source.html">vigra/convolution.hxx</a>> 00549 00550 00551 \code 00552 vigra::FImage src(w,h), dest(w,h); 00553 ... 00554 00555 // smooth with scale = 3.0 00556 vigra::gaussianSmoothing(srcImageRange(src), destImage(dest), 3.0); 00557 00558 \endcode 00559 00560 */ 00561 doxygen_overloaded_function(template <...> void gaussianSmoothing) 00562 00563 template <class SrcIterator, class SrcAccessor, 00564 class DestIterator, class DestAccessor> 00565 void gaussianSmoothing(SrcIterator supperleft, 00566 SrcIterator slowerright, SrcAccessor sa, 00567 DestIterator dupperleft, DestAccessor da, 00568 double scale) 00569 { 00570 typedef typename 00571 NumericTraits<typename SrcAccessor::value_type>::RealPromote 00572 TmpType; 00573 BasicImage<TmpType> tmp(slowerright - supperleft); 00574 00575 Kernel1D<double> smooth; 00576 smooth.initGaussian(scale); 00577 smooth.setBorderTreatment(BORDER_TREATMENT_REFLECT); 00578 00579 separableConvolveX(srcIterRange(supperleft, slowerright, sa), 00580 destImage(tmp), kernel1d(smooth)); 00581 separableConvolveY(srcImageRange(tmp), 00582 destIter(dupperleft, da), kernel1d(smooth)); 00583 } 00584 00585 template <class SrcIterator, class SrcAccessor, 00586 class DestIterator, class DestAccessor> 00587 inline void 00588 gaussianSmoothing(triple<SrcIterator, SrcIterator, SrcAccessor> src, 00589 pair<DestIterator, DestAccessor> dest, 00590 double scale) 00591 { 00592 gaussianSmoothing(src.first, src.second, src.third, 00593 dest.first, dest.second, scale); 00594 } 00595 00596 /********************************************************/ 00597 /* */ 00598 /* gaussianGradient */ 00599 /* */ 00600 /********************************************************/ 00601 00602 /** \brief Calculate the gradient vector by means of a 1st derivatives of 00603 Gaussian filter. 00604 00605 This function is a shorthand for the concatenation of a call to 00606 \ref separableConvolveX() and \ref separableConvolveY() with the 00607 appropriate kernels at the given scale. Note that this function can either produce 00608 two separate result images for the x- and y-components of the gradient, or write 00609 into a vector valued image (with at least two components). 00610 00611 <b> Declarations:</b> 00612 00613 pass arguments explicitly: 00614 \code 00615 namespace vigra { 00616 // write x and y component of the gradient into separate images 00617 template <class SrcIterator, class SrcAccessor, 00618 class DestIteratorX, class DestAccessorX, 00619 class DestIteratorY, class DestAccessorY> 00620 void gaussianGradient(SrcIterator supperleft, 00621 SrcIterator slowerright, SrcAccessor sa, 00622 DestIteratorX dupperleftx, DestAccessorX dax, 00623 DestIteratorY dupperlefty, DestAccessorY day, 00624 double scale); 00625 00626 // write x and y component of the gradient into a vector-valued image 00627 template <class SrcIterator, class SrcAccessor, 00628 class DestIterator, class DestAccessor> 00629 void gaussianGradient(SrcIterator supperleft, 00630 SrcIterator slowerright, SrcAccessor src, 00631 DestIterator dupperleft, DestAccessor dest, 00632 double scale); 00633 } 00634 \endcode 00635 00636 00637 use argument objects in conjunction with \ref ArgumentObjectFactories : 00638 \code 00639 namespace vigra { 00640 // write x and y component of the gradient into separate images 00641 template <class SrcIterator, class SrcAccessor, 00642 class DestIteratorX, class DestAccessorX, 00643 class DestIteratorY, class DestAccessorY> 00644 void 00645 gaussianGradient(triple<SrcIterator, SrcIterator, SrcAccessor> src, 00646 pair<DestIteratorX, DestAccessorX> destx, 00647 pair<DestIteratorY, DestAccessorY> desty, 00648 double scale); 00649 00650 // write x and y component of the gradient into a vector-valued image 00651 template <class SrcIterator, class SrcAccessor, 00652 class DestIterator, class DestAccessor> 00653 void 00654 gaussianGradient(triple<SrcIterator, SrcIterator, SrcAccessor> src, 00655 pair<DestIterator, DestAccessor> dest, 00656 double scale); 00657 } 00658 \endcode 00659 00660 <b> Usage:</b> 00661 00662 <b>\#include</b> <<a href="convolution_8hxx-source.html">vigra/convolution.hxx</a>> 00663 00664 00665 \code 00666 vigra::FImage src(w,h), gradx(w,h), grady(w,h); 00667 ... 00668 00669 // calculate gradient vector at scale = 3.0 00670 vigra::gaussianGradient(srcImageRange(src), 00671 destImage(gradx), destImage(grady), 3.0); 00672 00673 \endcode 00674 00675 */ 00676 doxygen_overloaded_function(template <...> void gaussianGradient) 00677 00678 template <class SrcIterator, class SrcAccessor, 00679 class DestIteratorX, class DestAccessorX, 00680 class DestIteratorY, class DestAccessorY> 00681 void gaussianGradient(SrcIterator supperleft, 00682 SrcIterator slowerright, SrcAccessor sa, 00683 DestIteratorX dupperleftx, DestAccessorX dax, 00684 DestIteratorY dupperlefty, DestAccessorY day, 00685 double scale) 00686 { 00687 typedef typename 00688 NumericTraits<typename SrcAccessor::value_type>::RealPromote 00689 TmpType; 00690 BasicImage<TmpType> tmp(slowerright - supperleft); 00691 00692 Kernel1D<double> smooth, grad; 00693 smooth.initGaussian(scale); 00694 grad.initGaussianDerivative(scale, 1); 00695 00696 separableConvolveX(srcIterRange(supperleft, slowerright, sa), 00697 destImage(tmp), kernel1d(grad)); 00698 separableConvolveY(srcImageRange(tmp), 00699 destIter(dupperleftx, dax), kernel1d(smooth)); 00700 separableConvolveX(srcIterRange(supperleft, slowerright, sa), 00701 destImage(tmp), kernel1d(smooth)); 00702 separableConvolveY(srcImageRange(tmp), 00703 destIter(dupperlefty, day), kernel1d(grad)); 00704 } 00705 00706 template <class SrcIterator, class SrcAccessor, 00707 class DestIterator, class DestAccessor> 00708 void gaussianGradient(SrcIterator supperleft, 00709 SrcIterator slowerright, SrcAccessor src, 00710 DestIterator dupperleft, DestAccessor dest, 00711 double scale) 00712 { 00713 VectorElementAccessor<DestAccessor> gradx(0, dest), grady(1, dest); 00714 gaussianGradient(supperleft, slowerright, src, 00715 dupperleft, gradx, dupperleft, grady, scale); 00716 } 00717 00718 template <class SrcIterator, class SrcAccessor, 00719 class DestIteratorX, class DestAccessorX, 00720 class DestIteratorY, class DestAccessorY> 00721 inline void 00722 gaussianGradient(triple<SrcIterator, SrcIterator, SrcAccessor> src, 00723 pair<DestIteratorX, DestAccessorX> destx, 00724 pair<DestIteratorY, DestAccessorY> desty, 00725 double scale) 00726 { 00727 gaussianGradient(src.first, src.second, src.third, 00728 destx.first, destx.second, desty.first, desty.second, scale); 00729 } 00730 00731 template <class SrcIterator, class SrcAccessor, 00732 class DestIterator, class DestAccessor> 00733 inline void 00734 gaussianGradient(triple<SrcIterator, SrcIterator, SrcAccessor> src, 00735 pair<DestIterator, DestAccessor> dest, 00736 double scale) 00737 { 00738 gaussianGradient(src.first, src.second, src.third, 00739 dest.first, dest.second, scale); 00740 } 00741 00742 /** \brief Calculate the gradient magnitude by means of a 1st derivatives of 00743 Gaussian filter. 00744 00745 This function calls gaussianGradient() and returns the pixel-wise magnitude of 00746 the resulting gradient vectors. If the original image has multiple bands, 00747 the squared gradient magnitude is computed for each band separately, and the 00748 return value is the square root of the sum of these sqaured magnitudes. 00749 00750 <b> Declarations:</b> 00751 00752 pass arguments explicitly: 00753 \code 00754 namespace vigra { 00755 template <class SrcIterator, class SrcAccessor, 00756 class DestIterator, class DestAccessor> 00757 void gaussianGradientMagnitude(SrcIterator sul, 00758 SrcIterator slr, SrcAccessor src, 00759 DestIterator dupperleft, DestAccessor dest, 00760 double scale); 00761 } 00762 \endcode 00763 00764 00765 use argument objects in conjunction with \ref ArgumentObjectFactories : 00766 \code 00767 namespace vigra { 00768 template <class SrcIterator, class SrcAccessor, 00769 class DestIterator, class DestAccessor> 00770 void 00771 gaussianGradientMagnitude(triple<SrcIterator, SrcIterator, SrcAccessor> src, 00772 pair<DestIterator, DestAccessor> dest, 00773 double scale); 00774 } 00775 \endcode 00776 00777 <b> Usage:</b> 00778 00779 <b>\#include</b> <<a href="convolution_8hxx-source.html">vigra/convolution.hxx</a>> 00780 00781 00782 \code 00783 vigra::FImage src(w,h), grad(w,h); 00784 ... 00785 00786 // calculate gradient magnitude at scale = 3.0 00787 vigra::gaussianGradientMagnitude(srcImageRange(src), destImage(grad), 3.0); 00788 00789 \endcode 00790 00791 */ 00792 doxygen_overloaded_function(template <...> void gaussianGradientMagnitude) 00793 00794 template <class SrcIterator, class SrcAccessor, 00795 class DestIterator, class DestAccessor> 00796 void gaussianGradientMagnitude(SrcIterator sul, 00797 SrcIterator slr, SrcAccessor src, 00798 DestIterator dupperleft, DestAccessor dest, 00799 double scale) 00800 { 00801 typedef typename NumericTraits<typename SrcAccessor::value_type>::RealPromote TmpType; 00802 BasicImage<TmpType> gradx(slr-sul), grady(slr-sul); 00803 00804 gaussianGradient(srcIterRange(sul, slr, src), 00805 destImage(gradx), destImage(grady), scale); 00806 combineTwoImages(srcImageRange(gradx), srcImage(grady), destIter(dupperleft, dest), 00807 MagnitudeFunctor<TmpType>()); 00808 } 00809 00810 template <class SrcIterator, class SrcAccessor, 00811 class DestIterator, class DestAccessor> 00812 inline void 00813 gaussianGradientMagnitude(triple<SrcIterator, SrcIterator, SrcAccessor> src, 00814 pair<DestIterator, DestAccessor> dest, 00815 double scale) 00816 { 00817 gaussianGradientMagnitude(src.first, src.second, src.third, 00818 dest.first, dest.second, scale); 00819 } 00820 00821 /********************************************************/ 00822 /* */ 00823 /* laplacianOfGaussian */ 00824 /* */ 00825 /********************************************************/ 00826 00827 /** \brief Filter image with the Laplacian of Gaussian operator 00828 at the given scale. 00829 00830 This function calls \ref separableConvolveX() and \ref separableConvolveY() with the appropriate 2nd derivative 00831 of Gaussian kernels in x- and y-direction and then sums the results 00832 to get the Laplacian. 00833 00834 <b> Declarations:</b> 00835 00836 pass arguments explicitly: 00837 \code 00838 namespace vigra { 00839 template <class SrcIterator, class SrcAccessor, 00840 class DestIterator, class DestAccessor> 00841 void laplacianOfGaussian(SrcIterator supperleft, 00842 SrcIterator slowerright, SrcAccessor sa, 00843 DestIterator dupperleft, DestAccessor da, 00844 double scale); 00845 } 00846 \endcode 00847 00848 00849 use argument objects in conjunction with \ref ArgumentObjectFactories : 00850 \code 00851 namespace vigra { 00852 template <class SrcIterator, class SrcAccessor, 00853 class DestIterator, class DestAccessor> 00854 inline void 00855 laplacianOfGaussian(triple<SrcIterator, SrcIterator, SrcAccessor> src, 00856 pair<DestIterator, DestAccessor> dest, 00857 double scale); 00858 } 00859 \endcode 00860 00861 <b> Usage:</b> 00862 00863 <b>\#include</b> <<a href="convolution_8hxx-source.html">vigra/convolution.hxx</a>> 00864 00865 00866 \code 00867 vigra::FImage src(w,h), dest(w,h); 00868 ... 00869 00870 // calculate Laplacian of Gaussian at scale = 3.0 00871 vigra::laplacianOfGaussian(srcImageRange(src), destImage(dest), 3.0); 00872 00873 \endcode 00874 00875 */ 00876 doxygen_overloaded_function(template <...> void laplacianOfGaussian) 00877 00878 template <class SrcIterator, class SrcAccessor, 00879 class DestIterator, class DestAccessor> 00880 void laplacianOfGaussian(SrcIterator supperleft, 00881 SrcIterator slowerright, SrcAccessor sa, 00882 DestIterator dupperleft, DestAccessor da, 00883 double scale) 00884 { 00885 typedef typename 00886 NumericTraits<typename SrcAccessor::value_type>::RealPromote 00887 TmpType; 00888 BasicImage<TmpType> tmp(slowerright - supperleft), 00889 tmpx(slowerright - supperleft), 00890 tmpy(slowerright - supperleft); 00891 00892 Kernel1D<double> smooth, deriv; 00893 smooth.initGaussian(scale); 00894 deriv.initGaussianDerivative(scale, 2); 00895 00896 separableConvolveX(srcIterRange(supperleft, slowerright, sa), 00897 destImage(tmp), kernel1d(deriv)); 00898 separableConvolveY(srcImageRange(tmp), 00899 destImage(tmpx), kernel1d(smooth)); 00900 separableConvolveX(srcIterRange(supperleft, slowerright, sa), 00901 destImage(tmp), kernel1d(smooth)); 00902 separableConvolveY(srcImageRange(tmp), 00903 destImage(tmpy), kernel1d(deriv)); 00904 combineTwoImages(srcImageRange(tmpx), srcImage(tmpy), 00905 destIter(dupperleft, da), std::plus<TmpType>()); 00906 } 00907 00908 template <class SrcIterator, class SrcAccessor, 00909 class DestIterator, class DestAccessor> 00910 inline void 00911 laplacianOfGaussian(triple<SrcIterator, SrcIterator, SrcAccessor> src, 00912 pair<DestIterator, DestAccessor> dest, 00913 double scale) 00914 { 00915 laplacianOfGaussian(src.first, src.second, src.third, 00916 dest.first, dest.second, scale); 00917 } 00918 00919 /********************************************************/ 00920 /* */ 00921 /* hessianMatrixOfGaussian */ 00922 /* */ 00923 /********************************************************/ 00924 00925 /** \brief Filter image with the 2nd derivatives of the Gaussian 00926 at the given scale to get the Hessian matrix. 00927 00928 The Hessian matrix is a symmetric matrix defined as: 00929 00930 \f[ 00931 \mbox{\rm Hessian}(I) = \left( 00932 \begin{array}{cc} 00933 G_{xx} \ast I & G_{xy} \ast I \\ 00934 G_{xy} \ast I & G_{yy} \ast I 00935 \end{array} \right) 00936 \f] 00937 00938 where \f$G_{xx}, G_{xy}, G_{yy}\f$ denote 2nd derivatives of Gaussians 00939 at the given scale, and 00940 \f$\ast\f$ is the convolution symbol. This function calls 00941 \ref separableConvolveX() and \ref separableConvolveY() 00942 with the appropriate 2nd derivative 00943 of Gaussian kernels and puts the results in 00944 the three destination images. The first destination image will 00945 contain the second derivative in x-direction, the second one the mixed 00946 derivative, and the third one holds the derivative in y-direction. 00947 00948 <b> Declarations:</b> 00949 00950 pass arguments explicitly: 00951 \code 00952 namespace vigra { 00953 template <class SrcIterator, class SrcAccessor, 00954 class DestIteratorX, class DestAccessorX, 00955 class DestIteratorXY, class DestAccessorXY, 00956 class DestIteratorY, class DestAccessorY> 00957 void hessianMatrixOfGaussian(SrcIterator supperleft, 00958 SrcIterator slowerright, SrcAccessor sa, 00959 DestIteratorX dupperleftx, DestAccessorX dax, 00960 DestIteratorXY dupperleftxy, DestAccessorXY daxy, 00961 DestIteratorY dupperlefty, DestAccessorY day, 00962 double scale); 00963 } 00964 \endcode 00965 00966 00967 use argument objects in conjunction with \ref ArgumentObjectFactories : 00968 \code 00969 namespace vigra { 00970 template <class SrcIterator, class SrcAccessor, 00971 class DestIteratorX, class DestAccessorX, 00972 class DestIteratorXY, class DestAccessorXY, 00973 class DestIteratorY, class DestAccessorY> 00974 inline void 00975 hessianMatrixOfGaussian(triple<SrcIterator, SrcIterator, SrcAccessor> src, 00976 pair<DestIteratorX, DestAccessorX> destx, 00977 pair<DestIteratorXY, DestAccessorXY> destxy, 00978 pair<DestIteratorY, DestAccessorY> desty, 00979 double scale); 00980 } 00981 \endcode 00982 00983 <b> Usage:</b> 00984 00985 <b>\#include</b> <<a href="convolution_8hxx-source.html">vigra/convolution.hxx</a>> 00986 00987 00988 \code 00989 vigra::FImage src(w,h), hxx(w,h), hxy(w,h), hyy(w,h); 00990 ... 00991 00992 // calculate Hessian of Gaussian at scale = 3.0 00993 vigra::hessianMatrixOfGaussian(srcImageRange(src), 00994 destImage(hxx), destImage(hxy), destImage(hyy), 3.0); 00995 00996 \endcode 00997 00998 */ 00999 doxygen_overloaded_function(template <...> void hessianMatrixOfGaussian) 01000 01001 template <class SrcIterator, class SrcAccessor, 01002 class DestIteratorX, class DestAccessorX, 01003 class DestIteratorXY, class DestAccessorXY, 01004 class DestIteratorY, class DestAccessorY> 01005 void hessianMatrixOfGaussian(SrcIterator supperleft, 01006 SrcIterator slowerright, SrcAccessor sa, 01007 DestIteratorX dupperleftx, DestAccessorX dax, 01008 DestIteratorXY dupperleftxy, DestAccessorXY daxy, 01009 DestIteratorY dupperlefty, DestAccessorY day, 01010 double scale) 01011 { 01012 typedef typename 01013 NumericTraits<typename SrcAccessor::value_type>::RealPromote 01014 TmpType; 01015 BasicImage<TmpType> tmp(slowerright - supperleft); 01016 01017 Kernel1D<double> smooth, deriv1, deriv2; 01018 smooth.initGaussian(scale); 01019 deriv1.initGaussianDerivative(scale, 1); 01020 deriv2.initGaussianDerivative(scale, 2); 01021 01022 separableConvolveX(srcIterRange(supperleft, slowerright, sa), 01023 destImage(tmp), kernel1d(deriv2)); 01024 separableConvolveY(srcImageRange(tmp), 01025 destIter(dupperleftx, dax), kernel1d(smooth)); 01026 separableConvolveX(srcIterRange(supperleft, slowerright, sa), 01027 destImage(tmp), kernel1d(smooth)); 01028 separableConvolveY(srcImageRange(tmp), 01029 destIter(dupperlefty, day), kernel1d(deriv2)); 01030 separableConvolveX(srcIterRange(supperleft, slowerright, sa), 01031 destImage(tmp), kernel1d(deriv1)); 01032 separableConvolveY(srcImageRange(tmp), 01033 destIter(dupperleftxy, daxy), kernel1d(deriv1)); 01034 } 01035 01036 template <class SrcIterator, class SrcAccessor, 01037 class DestIteratorX, class DestAccessorX, 01038 class DestIteratorXY, class DestAccessorXY, 01039 class DestIteratorY, class DestAccessorY> 01040 inline void 01041 hessianMatrixOfGaussian(triple<SrcIterator, SrcIterator, SrcAccessor> src, 01042 pair<DestIteratorX, DestAccessorX> destx, 01043 pair<DestIteratorXY, DestAccessorXY> destxy, 01044 pair<DestIteratorY, DestAccessorY> desty, 01045 double scale) 01046 { 01047 hessianMatrixOfGaussian(src.first, src.second, src.third, 01048 destx.first, destx.second, 01049 destxy.first, destxy.second, 01050 desty.first, desty.second, 01051 scale); 01052 } 01053 01054 /********************************************************/ 01055 /* */ 01056 /* structureTensor */ 01057 /* */ 01058 /********************************************************/ 01059 01060 /** \brief Calculate the Structure Tensor for each pixel of 01061 and image, using Gaussian (derivative) filters. 01062 01063 The Structure Tensor is is a smoothed version of the Euclidean product 01064 of the gradient vector with itself. I.e. it's a symmetric matrix defined as: 01065 01066 \f[ 01067 \mbox{\rm StructurTensor}(I) = \left( 01068 \begin{array}{cc} 01069 G \ast (I_x I_x) & G \ast (I_x I_y) \\ 01070 G \ast (I_x I_y) & G \ast (I_y I_y) 01071 \end{array} \right) = \left( 01072 \begin{array}{cc} 01073 A & C \\ 01074 C & B 01075 \end{array} \right) 01076 \f] 01077 01078 where \f$G\f$ denotes Gaussian smoothing at the <i>outer scale</i>, 01079 \f$I_x, I_y\f$ are the gradient components taken at the <i>inner scale</i>, 01080 \f$\ast\f$ is the convolution symbol, and \f$I_x I_x\f$ etc. are pixelwise 01081 products of the 1st derivative images. This function calls 01082 \ref separableConvolveX() and \ref separableConvolveY() with the 01083 appropriate Gaussian kernels and puts the results in 01084 the three separate destination images (where the first one will 01085 contain \f$G \ast (I_x I_x)\f$, the second one \f$G \ast (I_x I_y)\f$, and the 01086 third one holds \f$G \ast (I_y I_y)\f$), or into a single 3-band image (where the bands 01087 hold the result in the same order as above). The latter form is also applicable when 01088 the source image is a multi-band image (e.g. RGB). In this case, tensors are 01089 first computed for each band separately, and then summed up to get a single result tensor. 01090 01091 <b> Declarations:</b> 01092 01093 pass arguments explicitly: 01094 \code 01095 namespace vigra { 01096 // create three separate destination images 01097 template <class SrcIterator, class SrcAccessor, 01098 class DestIteratorX, class DestAccessorX, 01099 class DestIteratorXY, class DestAccessorXY, 01100 class DestIteratorY, class DestAccessorY> 01101 void structureTensor(SrcIterator supperleft, 01102 SrcIterator slowerright, SrcAccessor sa, 01103 DestIteratorX dupperleftx, DestAccessorX dax, 01104 DestIteratorXY dupperleftxy, DestAccessorXY daxy, 01105 DestIteratorY dupperlefty, DestAccessorY day, 01106 double inner_scale, double outer_scale); 01107 01108 // create a single 3-band destination image 01109 template <class SrcIterator, class SrcAccessor, 01110 class DestIterator, class DestAccessor> 01111 void structureTensor(SrcIterator supperleft, 01112 SrcIterator slowerright, SrcAccessor sa, 01113 DestIterator dupperleft, DestAccessor da, 01114 double inner_scale, double outer_scale); 01115 } 01116 \endcode 01117 01118 01119 use argument objects in conjunction with \ref ArgumentObjectFactories : 01120 \code 01121 namespace vigra { 01122 // create three separate destination images 01123 template <class SrcIterator, class SrcAccessor, 01124 class DestIteratorX, class DestAccessorX, 01125 class DestIteratorXY, class DestAccessorXY, 01126 class DestIteratorY, class DestAccessorY> 01127 void 01128 structureTensor(triple<SrcIterator, SrcIterator, SrcAccessor> src, 01129 pair<DestIteratorX, DestAccessorX> destx, 01130 pair<DestIteratorXY, DestAccessorXY> destxy, 01131 pair<DestIteratorY, DestAccessorY> desty, 01132 double nner_scale, double outer_scale); 01133 01134 // create a single 3-band destination image 01135 template <class SrcIterator, class SrcAccessor, 01136 class DestIterator, class DestAccessor> 01137 void 01138 structureTensor(triple<SrcIterator, SrcIterator, SrcAccessor> src, 01139 pair<DestIterator, DestAccessor> dest, 01140 double nner_scale, double outer_scale); 01141 } 01142 \endcode 01143 01144 <b> Usage:</b> 01145 01146 <b>\#include</b> <<a href="convolution_8hxx-source.html">vigra/convolution.hxx</a>> 01147 01148 01149 \code 01150 vigra::FImage src(w,h), stxx(w,h), stxy(w,h), styy(w,h); 01151 vigra::BasicImage<TinyVector<float, 3> > st(w,h); 01152 ... 01153 01154 // calculate Structure Tensor at inner scale = 1.0 and outer scale = 3.0 01155 vigra::structureTensor(srcImageRange(src), 01156 destImage(stxx), destImage(stxy), destImage(styy), 1.0, 3.0); 01157 01158 // dto. with a single 3-band destination image 01159 vigra::structureTensor(srcImageRange(src), destImage(st), 1.0, 3.0); 01160 01161 \endcode 01162 01163 */ 01164 doxygen_overloaded_function(template <...> void structureTensor) 01165 01166 template <class SrcIterator, class SrcAccessor, 01167 class DestIteratorX, class DestAccessorX, 01168 class DestIteratorXY, class DestAccessorXY, 01169 class DestIteratorY, class DestAccessorY> 01170 void structureTensor(SrcIterator supperleft, 01171 SrcIterator slowerright, SrcAccessor sa, 01172 DestIteratorX dupperleftx, DestAccessorX dax, 01173 DestIteratorXY dupperleftxy, DestAccessorXY daxy, 01174 DestIteratorY dupperlefty, DestAccessorY day, 01175 double inner_scale, double outer_scale) 01176 { 01177 typedef typename 01178 NumericTraits<typename SrcAccessor::value_type>::RealPromote 01179 TmpType; 01180 BasicImage<TmpType> tmp(slowerright - supperleft), 01181 tmpx(slowerright - supperleft), 01182 tmpy(slowerright - supperleft); 01183 01184 gaussianGradient(srcIterRange(supperleft, slowerright, sa), 01185 destImage(tmpx), destImage(tmpy), inner_scale); 01186 combineTwoImages(srcImageRange(tmpx), srcImage(tmpx), 01187 destImage(tmp), std::multiplies<TmpType>()); 01188 gaussianSmoothing(srcImageRange(tmp), 01189 destIter(dupperleftx, dax), outer_scale); 01190 combineTwoImages(srcImageRange(tmpy), srcImage(tmpy), 01191 destImage(tmp), std::multiplies<TmpType>()); 01192 gaussianSmoothing(srcImageRange(tmp), 01193 destIter(dupperlefty, day), outer_scale); 01194 combineTwoImages(srcImageRange(tmpx), srcImage(tmpy), 01195 destImage(tmp), std::multiplies<TmpType>()); 01196 gaussianSmoothing(srcImageRange(tmp), 01197 destIter(dupperleftxy, daxy), outer_scale); 01198 } 01199 01200 template <class SrcIterator, class SrcAccessor, 01201 class DestIteratorX, class DestAccessorX, 01202 class DestIteratorXY, class DestAccessorXY, 01203 class DestIteratorY, class DestAccessorY> 01204 inline void 01205 structureTensor(triple<SrcIterator, SrcIterator, SrcAccessor> src, 01206 pair<DestIteratorX, DestAccessorX> destx, 01207 pair<DestIteratorXY, DestAccessorXY> destxy, 01208 pair<DestIteratorY, DestAccessorY> desty, 01209 double inner_scale, double outer_scale) 01210 { 01211 structureTensor(src.first, src.second, src.third, 01212 destx.first, destx.second, 01213 destxy.first, destxy.second, 01214 desty.first, desty.second, 01215 inner_scale, outer_scale); 01216 } 01217 01218 namespace detail { 01219 01220 template <class SrcIterator, class SrcAccessor, 01221 class DestIterator, class DestAccessor> 01222 void structureTensor(SrcIterator supperleft, 01223 SrcIterator slowerright, SrcAccessor src, 01224 DestIterator dupperleft, DestAccessor dest, 01225 double inner_scale, double outer_scale, 01226 VigraTrueType /* isScalar */) 01227 { 01228 typedef VectorElementAccessor<DestAccessor> DA; 01229 structureTensor(supperleft, slowerright, src, 01230 dupperleft, DA(0, dest), 01231 dupperleft, DA(1, dest), 01232 dupperleft, DA(2, dest), 01233 inner_scale, outer_scale); 01234 } 01235 01236 template <class SrcIterator, class SrcAccessor, 01237 class DestIterator, class DestAccessor> 01238 void structureTensor(SrcIterator supperleft, 01239 SrcIterator slowerright, SrcAccessor src, 01240 DestIterator dupperleft, DestAccessor dest, 01241 double inner_scale, double outer_scale, 01242 VigraFalseType /* isScalar */) 01243 { 01244 int bands = src.size(supperleft); 01245 typedef VectorElementAccessor<SrcAccessor> SA; 01246 01247 structureTensor(supperleft, slowerright, SA(0, src), 01248 dupperleft, dest, 01249 inner_scale, outer_scale, 01250 VigraTrueType() /* isScalar */); 01251 01252 BasicImage<typename DestAccessor::value_type> st(slowerright - supperleft); 01253 for(int k=1; k < bands; ++k) 01254 { 01255 structureTensor(supperleft, slowerright, SA(k, src), 01256 st.upperLeft(), st.accessor(), 01257 inner_scale, outer_scale, 01258 VigraTrueType() /* isScalar */); 01259 combineTwoImages(srcImageRange(st), srcIter(dupperleft, dest), destIter(dupperleft, dest), 01260 std::plus<typename DestAccessor::value_type>()); 01261 } 01262 } 01263 01264 } // namespace detail 01265 01266 template <class SrcIterator, class SrcAccessor, 01267 class DestIterator, class DestAccessor> 01268 void structureTensor(SrcIterator supperleft, 01269 SrcIterator slowerright, SrcAccessor src, 01270 DestIterator dupperleft, DestAccessor dest, 01271 double inner_scale, double outer_scale) 01272 { 01273 typedef typename 01274 NumericTraits<typename SrcAccessor::value_type>::isScalar isScalar; 01275 detail::structureTensor(supperleft, slowerright, src, 01276 dupperleft, dest, inner_scale, outer_scale, isScalar()); 01277 } 01278 01279 template <class SrcIterator, class SrcAccessor, 01280 class DestIterator, class DestAccessor> 01281 inline void 01282 structureTensor(triple<SrcIterator, SrcIterator, SrcAccessor> src, 01283 pair<DestIterator, DestAccessor> dest, 01284 double inner_scale, double outer_scale) 01285 { 01286 structureTensor(src.first, src.second, src.third, 01287 dest.first, dest.second, 01288 inner_scale, outer_scale); 01289 } 01290 01291 //@} 01292 01293 } // namespace vigra 01294 01295 #endif // VIGRA_CONVOLUTION_HXX
© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) |
html generated using doxygen and Python
|