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