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