[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]
00001 //-- -*- c++ -*- 00002 /************************************************************************/ 00003 /* */ 00004 /* Copyright 2003 by Christian-Dennis Rahn */ 00005 /* and Ullrich Koethe */ 00006 /* Cognitive Systems Group, University of Hamburg, Germany */ 00007 /* */ 00008 /* This file is part of the VIGRA computer vision library. */ 00009 /* ( Version 1.6.0, Aug 13 2008 ) */ 00010 /* The VIGRA Website is */ 00011 /* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ 00012 /* Please direct questions, bug reports, and contributions to */ 00013 /* ullrich.koethe@iwr.uni-heidelberg.de or */ 00014 /* vigra@informatik.uni-hamburg.de */ 00015 /* */ 00016 /* Permission is hereby granted, free of charge, to any person */ 00017 /* obtaining a copy of this software and associated documentation */ 00018 /* files (the "Software"), to deal in the Software without */ 00019 /* restriction, including without limitation the rights to use, */ 00020 /* copy, modify, merge, publish, distribute, sublicense, and/or */ 00021 /* sell copies of the Software, and to permit persons to whom the */ 00022 /* Software is furnished to do so, subject to the following */ 00023 /* conditions: */ 00024 /* */ 00025 /* The above copyright notice and this permission notice shall be */ 00026 /* included in all copies or substantial portions of the */ 00027 /* Software. */ 00028 /* */ 00029 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */ 00030 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ 00031 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ 00032 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ 00033 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ 00034 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ 00035 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ 00036 /* OTHER DEALINGS IN THE SOFTWARE. */ 00037 /* */ 00038 /************************************************************************/ 00039 00040 #ifndef VIGRA_MULTI_CONVOLUTION_H 00041 #define VIGRA_MULTI_CONVOLUTION_H 00042 00043 #include "separableconvolution.hxx" 00044 #include "array_vector.hxx" 00045 #include "multi_array.hxx" 00046 #include "accessor.hxx" 00047 #include "numerictraits.hxx" 00048 #include "navigator.hxx" 00049 #include "metaprogramming.hxx" 00050 #include "multi_pointoperators.hxx" 00051 00052 00053 namespace vigra 00054 { 00055 00056 00057 namespace detail 00058 { 00059 00060 /********************************************************/ 00061 /* */ 00062 /* internalSeparableConvolveMultiArray */ 00063 /* */ 00064 /********************************************************/ 00065 00066 template <class SrcIterator, class SrcShape, class SrcAccessor, 00067 class DestIterator, class DestAccessor, class KernelIterator> 00068 void 00069 internalSeparableConvolveMultiArrayTmp( 00070 SrcIterator si, SrcShape const & shape, SrcAccessor src, 00071 DestIterator di, DestAccessor dest, KernelIterator kit) 00072 { 00073 enum { N = 1 + SrcIterator::level }; 00074 00075 typedef typename NumericTraits<typename DestAccessor::value_type>::RealPromote TmpType; 00076 00077 // temporay array to hold the current line to enable in-place operation 00078 ArrayVector<TmpType> tmp( shape[0] ); 00079 00080 typedef MultiArrayNavigator<SrcIterator, N> SNavigator; 00081 typedef MultiArrayNavigator<DestIterator, N> DNavigator; 00082 00083 { // only operate on first dimension here 00084 SNavigator snav( si, shape, 0 ); 00085 DNavigator dnav( di, shape, 0 ); 00086 00087 for( ; snav.hasMore(); snav++, dnav++ ) 00088 { 00089 // first copy source to temp for maximum cache efficiency 00090 copyLine( snav.begin(), snav.end(), src, 00091 tmp.begin(), typename AccessorTraits<TmpType>::default_accessor() ); 00092 00093 convolveLine( srcIterRange(tmp.begin(), tmp.end(), 00094 typename AccessorTraits<TmpType>::default_const_accessor()), 00095 destIter( dnav.begin(), dest ), 00096 kernel1d( *kit ) ); 00097 } 00098 ++kit; 00099 } 00100 00101 // operate on further dimensions 00102 for( int d = 1; d < N; ++d, ++kit ) 00103 { 00104 DNavigator dnav( di, shape, d ); 00105 00106 tmp.resize( shape[d] ); 00107 00108 for( ; dnav.hasMore(); dnav++ ) 00109 { 00110 // first copy source to temp for maximum cache efficiency 00111 copyLine( dnav.begin(), dnav.end(), dest, 00112 tmp.begin(), typename AccessorTraits<TmpType>::default_accessor() ); 00113 00114 convolveLine( srcIterRange(tmp.begin(), tmp.end(), 00115 typename AccessorTraits<TmpType>::default_const_accessor()), 00116 destIter( dnav.begin(), dest ), 00117 kernel1d( *kit ) ); 00118 } 00119 } 00120 } 00121 00122 00123 } // namespace detail 00124 00125 /** \addtogroup MultiArrayConvolutionFilters Convolution filters for multi-dimensional arrays. 00126 00127 These functions realize a separable convolution on an arbitrary dimensional 00128 array that is specified by iterators (compatible to \ref MultiIteratorPage) 00129 and shape objects. It can therefore be applied to a wide range of data structures 00130 (\ref vigra::MultiArrayView, \ref vigra::MultiArray etc.). 00131 */ 00132 //@{ 00133 00134 /********************************************************/ 00135 /* */ 00136 /* separableConvolveMultiArray */ 00137 /* */ 00138 /********************************************************/ 00139 00140 /** \brief Separated convolution on multi-dimensional arrays. 00141 00142 This function computes a separated convolution on all dimensions 00143 of the given multi-dimensional array. Both source and destination 00144 arrays are represented by iterators, shape objects and accessors. 00145 The destination array is required to already have the correct size. 00146 00147 There are two variants of this functions: one takes a single kernel 00148 of type \ref vigra::Kernel1D which is then applied to all dimensions, 00149 whereas the other requires an iterator referencing a sequence of 00150 \ref vigra::Kernel1D objects, one for every dimension of the data. 00151 Then the first kernel in this sequence is applied to the innermost 00152 dimension (e.g. the x-dimension of an image), while the last is applied to the 00153 outermost dimension (e.g. the z-dimension in a 3D image). 00154 00155 This function may work in-place, which means that <tt>siter == diter</tt> is allowed. 00156 A full-sized internal array is only allocated if working on the destination 00157 array directly would cause round-off errors (i.e. if 00158 <tt>typeid(typename NumericTraits<typename DestAccessor::value_type>::RealPromote) 00159 != typeid(typename DestAccessor::value_type)</tt>. 00160 00161 <b> Declarations:</b> 00162 00163 pass arguments explicitly: 00164 \code 00165 namespace vigra { 00166 // apply the same kernel to all dimensions 00167 template <class SrcIterator, class SrcShape, class SrcAccessor, 00168 class DestIterator, class DestAccessor, class T> 00169 void 00170 separableConvolveMultiArray(SrcIterator siter, SrcShape const & shape, SrcAccessor src, 00171 DestIterator diter, DestAccessor dest, 00172 Kernel1D<T> const & kernel); 00173 00174 // apply each kernel from the sequence `kernels³ in turn 00175 template <class SrcIterator, class SrcShape, class SrcAccessor, 00176 class DestIterator, class DestAccessor, class KernelIterator> 00177 void 00178 separableConvolveMultiArray(SrcIterator siter, SrcShape const & shape, SrcAccessor src, 00179 DestIterator diter, DestAccessor dest, 00180 KernelIterator kernels); 00181 } 00182 \endcode 00183 00184 use argument objects in conjunction with \ref ArgumentObjectFactories : 00185 \code 00186 namespace vigra { 00187 // apply the same kernel to all dimensions 00188 template <class SrcIterator, class SrcShape, class SrcAccessor, 00189 class DestIterator, class DestAccessor, class T> 00190 void 00191 separableConvolveMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00192 pair<DestIterator, DestAccessor> const & dest, 00193 Kernel1D<T> const & kernel); 00194 00195 // apply each kernel from the sequence `kernels³ in turn 00196 template <class SrcIterator, class SrcShape, class SrcAccessor, 00197 class DestIterator, class DestAccessor, class KernelIterator> 00198 void 00199 separableConvolveMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00200 pair<DestIterator, DestAccessor> const & dest, 00201 KernelIterator kernels); 00202 } 00203 \endcode 00204 00205 <b> Usage:</b> 00206 00207 <b>\#include</b> <<a href="multi__convolution_8hxx-source.html">vigra/multi_convolution.hxx</a>> 00208 00209 \code 00210 MultiArray<3, unsigned char>::size_type shape(width, height, depth); 00211 MultiArray<3, unsigned char> source(shape); 00212 MultiArray<3, float> dest(shape); 00213 ... 00214 Kernel1D<float> gauss; 00215 gauss.initGaussian(sigma); 00216 // create 3 Gauss kernels, one for each dimension 00217 ArrayVector<Kernel1D<float> > kernels(3, gauss); 00218 00219 // perform Gaussian smoothing on all dimensions 00220 separableConvolveMultiArray(srcMultiArrayRange(source), destMultiArray(dest), 00221 kernels.begin()); 00222 \endcode 00223 00224 \see vigra::Kernel1D, convolveLine() 00225 */ 00226 doxygen_overloaded_function(template <...> void separableConvolveMultiArray) 00227 00228 template <class SrcIterator, class SrcShape, class SrcAccessor, 00229 class DestIterator, class DestAccessor, class KernelIterator> 00230 void 00231 separableConvolveMultiArray( SrcIterator s, SrcShape const & shape, SrcAccessor src, 00232 DestIterator d, DestAccessor dest, KernelIterator kernels ) 00233 { 00234 typedef typename NumericTraits<typename DestAccessor::value_type>::RealPromote TmpType; 00235 00236 if(!IsSameType<TmpType, typename DestAccessor::value_type>::boolResult) 00237 { 00238 // need a temporary array to avoid rounding errors 00239 MultiArray<SrcShape::static_size, TmpType> tmpArray(shape); 00240 detail::internalSeparableConvolveMultiArrayTmp( s, shape, src, 00241 tmpArray.traverser_begin(), typename AccessorTraits<TmpType>::default_accessor(), kernels ); 00242 copyMultiArray(srcMultiArrayRange(tmpArray), destIter(d, dest)); 00243 } 00244 else 00245 { 00246 // work directly on the destination array 00247 detail::internalSeparableConvolveMultiArrayTmp( s, shape, src, d, dest, kernels ); 00248 } 00249 } 00250 00251 template <class SrcIterator, class SrcShape, class SrcAccessor, 00252 class DestIterator, class DestAccessor, class KernelIterator> 00253 inline 00254 void separableConvolveMultiArray( 00255 triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00256 pair<DestIterator, DestAccessor> const & dest, KernelIterator kit ) 00257 { 00258 separableConvolveMultiArray( source.first, source.second, source.third, 00259 dest.first, dest.second, kit ); 00260 } 00261 00262 template <class SrcIterator, class SrcShape, class SrcAccessor, 00263 class DestIterator, class DestAccessor, class T> 00264 inline void 00265 separableConvolveMultiArray( SrcIterator s, SrcShape const & shape, SrcAccessor src, 00266 DestIterator d, DestAccessor dest, 00267 Kernel1D<T> const & kernel ) 00268 { 00269 ArrayVector<Kernel1D<T> > kernels(shape.size(), kernel); 00270 00271 separableConvolveMultiArray( s, shape, src, d, dest, kernels.begin() ); 00272 } 00273 00274 template <class SrcIterator, class SrcShape, class SrcAccessor, 00275 class DestIterator, class DestAccessor, class T> 00276 inline void 00277 separableConvolveMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00278 pair<DestIterator, DestAccessor> const & dest, 00279 Kernel1D<T> const & kernel ) 00280 { 00281 ArrayVector<Kernel1D<T> > kernels(source.second.size(), kernel); 00282 00283 separableConvolveMultiArray( source.first, source.second, source.third, 00284 dest.first, dest.second, kernels.begin() ); 00285 } 00286 00287 /********************************************************/ 00288 /* */ 00289 /* convolveMultiArrayOneDimension */ 00290 /* */ 00291 /********************************************************/ 00292 00293 /** \brief Convolution along a single dimension of a multi-dimensional arrays. 00294 00295 This function computes a convolution along one dimension (specified by 00296 the parameter <tt>dim</tt> of the given multi-dimensional array with the given 00297 <tt>kernel</tt>. Both source and destination arrays are represented by 00298 iterators, shape objects and accessors. The destination array is required to 00299 already have the correct size. 00300 00301 This function may work in-place, which means that <tt>siter == diter</tt> is allowed. 00302 00303 <b> Declarations:</b> 00304 00305 pass arguments explicitly: 00306 \code 00307 namespace vigra { 00308 template <class SrcIterator, class SrcShape, class SrcAccessor, 00309 class DestIterator, class DestAccessor, class T> 00310 void 00311 convolveMultiArrayOneDimension(SrcIterator siter, SrcShape const & shape, SrcAccessor src, 00312 DestIterator diter, DestAccessor dest, 00313 unsigned int dim, vigra::Kernel1D<T> const & kernel); 00314 } 00315 \endcode 00316 00317 use argument objects in conjunction with \ref ArgumentObjectFactories : 00318 \code 00319 namespace vigra { 00320 template <class SrcIterator, class SrcShape, class SrcAccessor, 00321 class DestIterator, class DestAccessor, class T> 00322 void 00323 convolveMultiArrayOneDimension(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00324 pair<DestIterator, DestAccessor> const & dest, 00325 unsigned int dim, vigra::Kernel1D<T> const & kernel); 00326 } 00327 \endcode 00328 00329 <b> Usage:</b> 00330 00331 <b>\#include</b> <<a href="multi__convolution_8hxx-source.html">vigra/multi_convolution.hxx</a>> 00332 00333 \code 00334 MultiArray<3, unsigned char>::size_type shape(width, height, depth); 00335 MultiArray<3, unsigned char> source(shape); 00336 MultiArray<3, float> dest(shape); 00337 ... 00338 Kernel1D<float> gauss; 00339 gauss.initGaussian(sigma); 00340 00341 // perform Gaussian smoothing along dimensions 1 (height) 00342 convolveMultiArrayOneDimension(srcMultiArrayRange(source), destMultiArray(dest), 1, gauss); 00343 \endcode 00344 00345 \see separableConvolveMultiArray() 00346 */ 00347 doxygen_overloaded_function(template <...> void convolveMultiArrayOneDimension) 00348 00349 template <class SrcIterator, class SrcShape, class SrcAccessor, 00350 class DestIterator, class DestAccessor, class T> 00351 void 00352 convolveMultiArrayOneDimension(SrcIterator s, SrcShape const & shape, SrcAccessor src, 00353 DestIterator d, DestAccessor dest, 00354 unsigned int dim, vigra::Kernel1D<T> const & kernel ) 00355 { 00356 enum { N = 1 + SrcIterator::level }; 00357 vigra_precondition( dim < N, 00358 "convolveMultiArrayOneDimension(): The dimension number to convolve must be smaller " 00359 "than the data dimensionality" ); 00360 00361 typedef typename NumericTraits<typename DestAccessor::value_type>::RealPromote TmpType; 00362 ArrayVector<TmpType> tmp( shape[dim] ); 00363 00364 typedef MultiArrayNavigator<SrcIterator, N> SNavigator; 00365 typedef MultiArrayNavigator<DestIterator, N> DNavigator; 00366 00367 SNavigator snav( s, shape, dim ); 00368 DNavigator dnav( d, shape, dim ); 00369 00370 for( ; snav.hasMore(); snav++, dnav++ ) 00371 { 00372 // first copy source to temp for maximum cache efficiency 00373 copyLine( snav.begin(), snav.end(), src, 00374 tmp.begin(), typename AccessorTraits<TmpType>::default_accessor() ); 00375 00376 convolveLine( srcIterRange( tmp.begin(), tmp.end(), typename AccessorTraits<TmpType>::default_const_accessor()), 00377 destIter( dnav.begin(), dest ), 00378 kernel1d( kernel ) ); 00379 } 00380 } 00381 00382 template <class SrcIterator, class SrcShape, class SrcAccessor, 00383 class DestIterator, class DestAccessor, class T> 00384 inline void 00385 convolveMultiArrayOneDimension(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00386 pair<DestIterator, DestAccessor> const & dest, 00387 unsigned int dim, vigra::Kernel1D<T> const & kernel ) 00388 { 00389 convolveMultiArrayOneDimension( source.first, source.second, source.third, 00390 dest.first, dest.second, dim, kernel ); 00391 } 00392 00393 /********************************************************/ 00394 /* */ 00395 /* gaussianSmoothMultiArray */ 00396 /* */ 00397 /********************************************************/ 00398 00399 /** \brief Isotropic Gaussian smoothing of a multi-dimensional arrays. 00400 00401 This function computes an isotropic convolution of the given multi-dimensional 00402 array with a Gaussian filter at the given standard deviation <tt>sigma</tt>. 00403 Both source and destination arrays are represented by 00404 iterators, shape objects and accessors. The destination array is required to 00405 already have the correct size. This function may work in-place, which means 00406 that <tt>siter == diter</tt> is allowed. It is implemented by a call to 00407 \ref separableConvolveMultiArray() with the appropriate kernel. 00408 If the data are anisotropic (different pixel size along different dimensions) 00409 you should call \ref separableConvolveMultiArray() directly with the appropriate 00410 anisotropic Gaussians. 00411 00412 <b> Declarations:</b> 00413 00414 pass arguments explicitly: 00415 \code 00416 namespace vigra { 00417 template <class SrcIterator, class SrcShape, class SrcAccessor, 00418 class DestIterator, class DestAccessor> 00419 void 00420 gaussianSmoothMultiArray(SrcIterator siter, SrcShape const & shape, SrcAccessor src, 00421 DestIterator diter, DestAccessor dest, 00422 double sigma); 00423 } 00424 \endcode 00425 00426 use argument objects in conjunction with \ref ArgumentObjectFactories : 00427 \code 00428 namespace vigra { 00429 template <class SrcIterator, class SrcShape, class SrcAccessor, 00430 class DestIterator, class DestAccessor> 00431 void 00432 gaussianSmoothMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00433 pair<DestIterator, DestAccessor> const & dest, 00434 double sigma); 00435 } 00436 \endcode 00437 00438 <b> Usage:</b> 00439 00440 <b>\#include</b> <<a href="multi__convolution_8hxx-source.html">vigra/multi_convolution.hxx</a>> 00441 00442 \code 00443 MultiArray<3, unsigned char>::size_type shape(width, height, depth); 00444 MultiArray<3, unsigned char> source(shape); 00445 MultiArray<3, float> dest(shape); 00446 ... 00447 // perform isotropic Gaussian smoothing at scale `sigma³ 00448 gaussianSmoothMultiArray(srcMultiArrayRange(source), destMultiArray(dest), sigma); 00449 \endcode 00450 00451 \see separableConvolveMultiArray() 00452 */ 00453 doxygen_overloaded_function(template <...> void gaussianSmoothMultiArray) 00454 00455 template <class SrcIterator, class SrcShape, class SrcAccessor, 00456 class DestIterator, class DestAccessor> 00457 void 00458 gaussianSmoothMultiArray( SrcIterator s, SrcShape const & shape, SrcAccessor src, 00459 DestIterator d, DestAccessor dest, double sigma ) 00460 { 00461 typedef typename NumericTraits<typename DestAccessor::value_type>::RealPromote kernel_type; 00462 Kernel1D<kernel_type> gauss; 00463 gauss.initGaussian( sigma ); 00464 00465 separableConvolveMultiArray( s, shape, src, d, dest, gauss); 00466 } 00467 00468 template <class SrcIterator, class SrcShape, class SrcAccessor, 00469 class DestIterator, class DestAccessor> 00470 inline void 00471 gaussianSmoothMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00472 pair<DestIterator, DestAccessor> const & dest, 00473 double sigma ) 00474 { 00475 gaussianSmoothMultiArray( source.first, source.second, source.third, 00476 dest.first, dest.second, sigma ); 00477 } 00478 00479 /********************************************************/ 00480 /* */ 00481 /* gaussianGradientMultiArray */ 00482 /* */ 00483 /********************************************************/ 00484 00485 /** \brief Calculate Gaussian gradient of a multi-dimensional arrays. 00486 00487 This function computes the Gaussian gradient of the given multi-dimensional 00488 array with a sequence of first-derivative-of-Gaussian filters at the given 00489 standard deviation <tt>sigma</tt> (differentiation is applied to each dimension 00490 in turn, starting with the innermost dimension). Both source and destination arrays 00491 are represented by iterators, shape objects and accessors. The destination array is 00492 required to have a vector valued pixel type with as many elements as the number of 00493 dimensions. This function is implemented by calls to 00494 \ref separableConvolveMultiArray() with the appropriate kernels. 00495 If the data are anisotropic (different pixel size along different dimensions) 00496 you should call \ref separableConvolveMultiArray() directly with the appropriate 00497 anisotropic Gaussian derivatives. 00498 00499 <b> Declarations:</b> 00500 00501 pass arguments explicitly: 00502 \code 00503 namespace vigra { 00504 template <class SrcIterator, class SrcShape, class SrcAccessor, 00505 class DestIterator, class DestAccessor> 00506 void 00507 gaussianGradientMultiArray(SrcIterator siter, SrcShape const & shape, SrcAccessor src, 00508 DestIterator diter, DestAccessor dest, 00509 double sigma); 00510 } 00511 \endcode 00512 00513 use argument objects in conjunction with \ref ArgumentObjectFactories : 00514 \code 00515 namespace vigra { 00516 template <class SrcIterator, class SrcShape, class SrcAccessor, 00517 class DestIterator, class DestAccessor> 00518 void 00519 gaussianGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00520 pair<DestIterator, DestAccessor> const & dest, 00521 double sigma); 00522 } 00523 \endcode 00524 00525 <b> Usage:</b> 00526 00527 <b>\#include</b> <<a href="multi__convolution_8hxx-source.html">vigra/multi_convolution.hxx</a>> 00528 00529 \code 00530 MultiArray<3, unsigned char>::size_type shape(width, height, depth); 00531 MultiArray<3, unsigned char> source(shape); 00532 MultiArray<3, TinyVector<float, 3> > dest(shape); 00533 ... 00534 // compute Gaussian gradient at scale sigma 00535 gaussianGradientMultiArray(srcMultiArrayRange(source), destMultiArray(dest), sigma); 00536 \endcode 00537 00538 <b> Required Interface:</b> 00539 00540 see \ref convolveImage(), in addition: 00541 00542 \code 00543 int dimension = 0; 00544 VectorElementAccessor<DestAccessor> elementAccessor(0, dest); 00545 \endcode 00546 00547 \see separableConvolveMultiArray() 00548 */ 00549 doxygen_overloaded_function(template <...> void gaussianGradientMultiArray) 00550 00551 template <class SrcIterator, class SrcShape, class SrcAccessor, 00552 class DestIterator, class DestAccessor> 00553 void 00554 gaussianGradientMultiArray( SrcIterator si, SrcShape const & shape, SrcAccessor src, 00555 DestIterator di, DestAccessor dest, double sigma ) 00556 { 00557 typedef typename DestAccessor::value_type DestType; 00558 typedef typename NumericTraits<typename DestType::value_type>::RealPromote kernel_type; 00559 00560 Kernel1D<kernel_type> gauss, derivative; 00561 gauss.initGaussian(sigma); 00562 derivative.initGaussianDerivative(sigma, 1); 00563 00564 typedef VectorElementAccessor<DestAccessor> ElementAccessor; 00565 00566 // compute gradient components 00567 for(unsigned int d = 0; d < shape.size(); ++d ) 00568 { 00569 ArrayVector<Kernel1D<kernel_type> > kernels(shape.size(), gauss); 00570 kernels[d] = derivative; 00571 separableConvolveMultiArray( si, shape, src, di, ElementAccessor(d, dest), kernels.begin()); 00572 } 00573 } 00574 00575 template <class SrcIterator, class SrcShape, class SrcAccessor, 00576 class DestIterator, class DestAccessor> 00577 inline void 00578 gaussianGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00579 pair<DestIterator, DestAccessor> const & dest, double sigma ) 00580 { 00581 gaussianGradientMultiArray( source.first, source.second, source.third, 00582 dest.first, dest.second, sigma ); 00583 } 00584 00585 /********************************************************/ 00586 /* */ 00587 /* symmetricGradientMultiArray */ 00588 /* */ 00589 /********************************************************/ 00590 00591 /** \brief Calculate gradient of a multi-dimensional arrays using symmetric difference filters. 00592 00593 This function computes the gradient of the given multi-dimensional 00594 array with a sequence of symmetric difference filters a (differentiation is applied 00595 to each dimension in turn, starting with the innermost dimension). Both source and 00596 destination arrays are represented by iterators, shape objects and accessors. 00597 The destination array is required to have a vector valued pixel type with as many 00598 elements as the number of dimensions. This function is implemented by calls to 00599 \ref convolveMultiArrayOneDimension() with the symmetric difference kernel. 00600 00601 <b> Declarations:</b> 00602 00603 pass arguments explicitly: 00604 \code 00605 namespace vigra { 00606 template <class SrcIterator, class SrcShape, class SrcAccessor, 00607 class DestIterator, class DestAccessor> 00608 void 00609 symmetricGradientMultiArray(SrcIterator siter, SrcShape const & shape, SrcAccessor src, 00610 DestIterator diter, DestAccessor dest); 00611 } 00612 \endcode 00613 00614 use argument objects in conjunction with \ref ArgumentObjectFactories : 00615 \code 00616 namespace vigra { 00617 template <class SrcIterator, class SrcShape, class SrcAccessor, 00618 class DestIterator, class DestAccessor> 00619 void 00620 symmetricGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00621 pair<DestIterator, DestAccessor> const & dest); 00622 } 00623 \endcode 00624 00625 <b> Usage:</b> 00626 00627 <b>\#include</b> <<a href="multi__convolution_8hxx-source.html">vigra/multi_convolution.hxx</a>> 00628 00629 \code 00630 MultiArray<3, unsigned char>::size_type shape(width, height, depth); 00631 MultiArray<3, unsigned char> source(shape); 00632 MultiArray<3, TinyVector<float, 3> > dest(shape); 00633 ... 00634 // compute gradient 00635 symmetricGradientMultiArray(srcMultiArrayRange(source), destMultiArray(dest)); 00636 \endcode 00637 00638 <b> Required Interface:</b> 00639 00640 see \ref convolveImage(), in addition: 00641 00642 \code 00643 int dimension = 0; 00644 VectorElementAccessor<DestAccessor> elementAccessor(0, dest); 00645 \endcode 00646 00647 \see convolveMultiArrayOneDimension() 00648 */ 00649 doxygen_overloaded_function(template <...> void symmetricGradientMultiArray) 00650 00651 template <class SrcIterator, class SrcShape, class SrcAccessor, 00652 class DestIterator, class DestAccessor> 00653 void 00654 symmetricGradientMultiArray(SrcIterator si, SrcShape const & shape, SrcAccessor src, 00655 DestIterator di, DestAccessor dest) 00656 { 00657 typedef typename DestAccessor::value_type DestType; 00658 typedef typename NumericTraits<typename DestType::value_type>::RealPromote kernel_type; 00659 00660 Kernel1D<kernel_type> filter; 00661 filter.initSymmetricGradient(); 00662 00663 typedef VectorElementAccessor<DestAccessor> ElementAccessor; 00664 00665 // compute gradient components 00666 for(unsigned int d = 0; d < shape.size(); ++d ) 00667 { 00668 convolveMultiArrayOneDimension(si, shape, src, 00669 di, ElementAccessor(d, dest), 00670 d, filter); 00671 } 00672 } 00673 00674 template <class SrcIterator, class SrcShape, class SrcAccessor, 00675 class DestIterator, class DestAccessor> 00676 inline void 00677 symmetricGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00678 pair<DestIterator, DestAccessor> const & dest ) 00679 { 00680 symmetricGradientMultiArray(source.first, source.second, source.third, 00681 dest.first, dest.second); 00682 } 00683 00684 //@} 00685 00686 } //-- namespace vigra 00687 00688 00689 #endif //-- VIGRA_MULTI_CONVOLUTION_H
© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) |
html generated using doxygen and Python
|