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