[ VIGRA Homepage | Class Index | Function Index | File Index | Main Page ]
![]() |
vigra/multi_convolution.hxx | ![]() |
---|
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.4.0, Dec 21 2005 ) */ 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 /* koethe@informatik.uni-hamburg.de or */ 00014 /* vigra@kogs1.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 <vigra/separableconvolution.hxx> 00044 #include <vigra/array_vector.hxx> 00045 #include <vigra/multi_array.hxx> 00046 #include <vigra/accessor.hxx> 00047 #include <vigra/numerictraits.hxx> 00048 #include <vigra/navigator.hxx> 00049 #include <vigra/metaprogramming.hxx> 00050 #include <vigra/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 00217 // perform Gaussian smoothing on all dimensions 00218 separableConvolveMultiArray(srcMultiArrayRange(source), destMultiArray(dest), gauss); 00219 \endcode 00220 00221 \see vigra::Kernel1D, convolveLine() 00222 */ 00223 template <class SrcIterator, class SrcShape, class SrcAccessor, 00224 class DestIterator, class DestAccessor, class KernelIterator> 00225 void 00226 separableConvolveMultiArray( SrcIterator s, SrcShape const & shape, SrcAccessor src, 00227 DestIterator d, DestAccessor dest, KernelIterator kernels ) 00228 { 00229 typedef typename NumericTraits<typename DestAccessor::value_type>::RealPromote TmpType; 00230 00231 if(!IsSameType<TmpType, typename DestAccessor::value_type>::boolResult) 00232 { 00233 // need a temporary array to avoid rounding errors 00234 MultiArray<SrcShape::static_size, TmpType> tmpArray(shape); 00235 detail::internalSeparableConvolveMultiArrayTmp( s, shape, src, 00236 tmpArray.traverser_begin(), typename AccessorTraits<TmpType>::default_accessor(), kernels ); 00237 copyMultiArray(srcMultiArrayRange(tmpArray), destIter(d, dest)); 00238 } 00239 else 00240 { 00241 // work directly on the destination array 00242 detail::internalSeparableConvolveMultiArrayTmp( s, shape, src, d, dest, kernels ); 00243 } 00244 } 00245 00246 template <class SrcIterator, class SrcShape, class SrcAccessor, 00247 class DestIterator, class DestAccessor, class KernelIterator> 00248 inline 00249 void separableConvolveMultiArray( 00250 triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00251 pair<DestIterator, DestAccessor> const & dest, KernelIterator kit ) 00252 { 00253 separableConvolveMultiArray( source.first, source.second, source.third, 00254 dest.first, dest.second, kit ); 00255 } 00256 00257 template <class SrcIterator, class SrcShape, class SrcAccessor, 00258 class DestIterator, class DestAccessor, class T> 00259 inline void 00260 separableConvolveMultiArray( SrcIterator s, SrcShape const & shape, SrcAccessor src, 00261 DestIterator d, DestAccessor dest, 00262 Kernel1D<T> const & kernel ) 00263 { 00264 ArrayVector<Kernel1D<T> > kernels(shape.size(), kernel); 00265 00266 separableConvolveMultiArray( s, shape, src, d, dest, kernels.begin() ); 00267 } 00268 00269 template <class SrcIterator, class SrcShape, class SrcAccessor, 00270 class DestIterator, class DestAccessor, class T> 00271 inline void 00272 separableConvolveMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00273 pair<DestIterator, DestAccessor> const & dest, 00274 Kernel1D<T> const & kernel ) 00275 { 00276 ArrayVector<Kernel1D<T> > kernels(source.second.size(), kernel); 00277 00278 separableConvolveMultiArray( source.first, source.second, source.third, 00279 dest.first, dest.second, kernels.begin() ); 00280 } 00281 00282 /********************************************************/ 00283 /* */ 00284 /* convolveMultiArrayOneDimension */ 00285 /* */ 00286 /********************************************************/ 00287 00288 /** \brief Convolution along a single dimension of a multi-dimensional arrays. 00289 00290 This function computes a convolution along one dimension (specified by 00291 the parameter <tt>dim</tt> of the given multi-dimensional array with the given 00292 <tt>kernel</tt>. Both source and destination arrays are represented by 00293 iterators, shape objects and accessors. The destination array is required to 00294 already have the correct size. 00295 00296 This function may work in-place, which means that <tt>siter == diter</tt> is allowed. 00297 00298 <b> Declarations:</b> 00299 00300 pass arguments explicitly: 00301 \code 00302 namespace vigra { 00303 template <class SrcIterator, class SrcShape, class SrcAccessor, 00304 class DestIterator, class DestAccessor, class T> 00305 void 00306 convolveMultiArrayOneDimension(SrcIterator siter, SrcShape const & shape, SrcAccessor src, 00307 DestIterator diter, DestAccessor dest, 00308 unsigned int dim, vigra::Kernel1D<T> const & kernel); 00309 } 00310 \endcode 00311 00312 use argument objects in conjunction with \ref ArgumentObjectFactories: 00313 \code 00314 namespace vigra { 00315 template <class SrcIterator, class SrcShape, class SrcAccessor, 00316 class DestIterator, class DestAccessor, class T> 00317 void 00318 convolveMultiArrayOneDimension(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00319 pair<DestIterator, DestAccessor> const & dest, 00320 unsigned int dim, vigra::Kernel1D<T> const & kernel); 00321 } 00322 \endcode 00323 00324 <b> Usage:</b> 00325 00326 <b>\#include</b> "<a href="multi__convolution_8hxx-source.html">vigra/multi_convolution.hxx</a>" 00327 00328 \code 00329 MultiArray<3, unsigned char>::size_type shape(width, height, depth); 00330 MultiArray<3, unsigned char> source(shape); 00331 MultiArray<3, float> dest(shape); 00332 ... 00333 Kernel1D<float> gauss; 00334 gauss.initGaussian(sigma); 00335 00336 // perform Gaussian smoothing along dimensions 1 (height) 00337 convolveMultiArrayOneDimension(srcMultiArrayRange(source), destMultiArray(dest), 1, gauss); 00338 \endcode 00339 00340 \see separableConvolveMultiArray() 00341 */ 00342 template <class SrcIterator, class SrcShape, class SrcAccessor, 00343 class DestIterator, class DestAccessor, class T> 00344 void 00345 convolveMultiArrayOneDimension(SrcIterator s, SrcShape const & shape, SrcAccessor src, 00346 DestIterator d, DestAccessor dest, 00347 unsigned int dim, vigra::Kernel1D<T> const & kernel ) 00348 { 00349 enum { N = 1 + SrcIterator::level }; 00350 vigra_precondition( dim < N, 00351 "convolveMultiArrayOneDimension(): The dimension number to convolve must be smaller " 00352 "than the data dimensionality" ); 00353 00354 typedef typename NumericTraits<typename DestAccessor::value_type>::RealPromote TmpType; 00355 ArrayVector<TmpType> tmp( shape[dim] ); 00356 00357 typedef MultiArrayNavigator<SrcIterator, N> SNavigator; 00358 typedef MultiArrayNavigator<DestIterator, N> DNavigator; 00359 00360 SNavigator snav( s, shape, dim ); 00361 DNavigator dnav( d, shape, dim ); 00362 00363 for( ; snav.hasMore(); snav++, dnav++ ) 00364 { 00365 // first copy source to temp for maximum cache efficiency 00366 copyLine( snav.begin(), snav.end(), src, 00367 tmp.begin(), typename AccessorTraits<TmpType>::default_accessor() ); 00368 00369 convolveLine( srcIterRange( tmp.begin(), tmp.end(), typename AccessorTraits<TmpType>::default_const_accessor()), 00370 destIter( dnav.begin(), dest ), 00371 kernel1d( kernel ) ); 00372 } 00373 } 00374 00375 template <class SrcIterator, class SrcShape, class SrcAccessor, 00376 class DestIterator, class DestAccessor, class T> 00377 inline void 00378 convolveMultiArrayOneDimension(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00379 pair<DestIterator, DestAccessor> const & dest, 00380 unsigned int dim, vigra::Kernel1D<T> const & kernel ) 00381 { 00382 convolveMultiArrayOneDimension( source.first, source.second, source.third, 00383 dest.first, dest.second, dim, kernel ); 00384 } 00385 00386 /********************************************************/ 00387 /* */ 00388 /* gaussianSmoothMultiArray */ 00389 /* */ 00390 /********************************************************/ 00391 00392 /** \brief Isotropic Gaussian smoothing of a multi-dimensional arrays. 00393 00394 This function computes an isotropic convolution of the given multi-dimensional 00395 array with a Gaussian filter at the given standard deviation <tt>sigma</tt>. 00396 Both source and destination arrays are represented by 00397 iterators, shape objects and accessors. The destination array is required to 00398 already have the correct size. This function may work in-place, which means 00399 that <tt>siter == diter</tt> is allowed. It is implemented by a call to 00400 \ref separableConvolveMultiArray() with the appropriate kernel. 00401 If the data are anisotropic (different pixel size along different dimensions) 00402 you should call \ref separableConvolveMultiArray() directly with the appropriate 00403 anisotropic Gaussians. 00404 00405 <b> Declarations:</b> 00406 00407 pass arguments explicitly: 00408 \code 00409 namespace vigra { 00410 template <class SrcIterator, class SrcShape, class SrcAccessor, 00411 class DestIterator, class DestAccessor> 00412 void 00413 gaussianSmoothMultiArray(SrcIterator siter, SrcShape const & shape, SrcAccessor src, 00414 DestIterator diter, DestAccessor dest, 00415 double sigma); 00416 } 00417 \endcode 00418 00419 use argument objects in conjunction with \ref ArgumentObjectFactories: 00420 \code 00421 namespace vigra { 00422 template <class SrcIterator, class SrcShape, class SrcAccessor, 00423 class DestIterator, class DestAccessor> 00424 void 00425 gaussianSmoothMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00426 pair<DestIterator, DestAccessor> const & dest, 00427 double sigma); 00428 } 00429 \endcode 00430 00431 <b> Usage:</b> 00432 00433 <b>\#include</b> "<a href="multi__convolution_8hxx-source.html">vigra/multi_convolution.hxx</a>" 00434 00435 \code 00436 MultiArray<3, unsigned char>::size_type shape(width, height, depth); 00437 MultiArray<3, unsigned char> source(shape); 00438 MultiArray<3, float> dest(shape); 00439 ... 00440 // perform isotropic Gaussian smoothing at scale `sigma³ 00441 gaussianSmoothMultiArray(srcMultiArrayRange(source), destMultiArray(dest), sigma); 00442 \endcode 00443 00444 \see separableConvolveMultiArray() 00445 */ 00446 template <class SrcIterator, class SrcShape, class SrcAccessor, 00447 class DestIterator, class DestAccessor> 00448 void 00449 gaussianSmoothMultiArray( SrcIterator s, SrcShape const & shape, SrcAccessor src, 00450 DestIterator d, DestAccessor dest, double sigma ) 00451 { 00452 typedef typename NumericTraits<typename DestAccessor::value_type>::RealPromote kernel_type; 00453 Kernel1D<kernel_type> gauss; 00454 gauss.initGaussian( sigma ); 00455 00456 separableConvolveMultiArray( s, shape, src, d, dest, gauss); 00457 } 00458 00459 template <class SrcIterator, class SrcShape, class SrcAccessor, 00460 class DestIterator, class DestAccessor> 00461 inline void 00462 gaussianSmoothMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00463 pair<DestIterator, DestAccessor> const & dest, 00464 double sigma ) 00465 { 00466 gaussianSmoothMultiArray( source.first, source.second, source.third, 00467 dest.first, dest.second, sigma ); 00468 } 00469 00470 /********************************************************/ 00471 /* */ 00472 /* gaussianGradientMultiArray */ 00473 /* */ 00474 /********************************************************/ 00475 00476 /** \brief Calculate Gaussian gradient of a multi-dimensional arrays. 00477 00478 This function computes the Gaussian gradient of the given multi-dimensional 00479 array with a sequence of first-derivative-of-Gaussian filters at the given 00480 standard deviation <tt>sigma</tt> (differentiation is applied to each dimension 00481 in turn, starting with the innermost dimension). Both source and destination arrays 00482 are represented by iterators, shape objects and accessors. The destination array is 00483 required to have a vector valued pixel type with as many elements as the number of 00484 dimensions. This function is implemented by calls to 00485 \ref separableConvolveMultiArray() with the appropriate kernels. 00486 If the data are anisotropic (different pixel size along different dimensions) 00487 you should call \ref separableConvolveMultiArray() directly with the appropriate 00488 anisotropic Gaussian derivatives. 00489 00490 <b> Declarations:</b> 00491 00492 pass arguments explicitly: 00493 \code 00494 namespace vigra { 00495 template <class SrcIterator, class SrcShape, class SrcAccessor, 00496 class DestIterator, class DestAccessor> 00497 void 00498 gaussianGradientMultiArray(SrcIterator siter, SrcShape const & shape, SrcAccessor src, 00499 DestIterator diter, DestAccessor dest, 00500 double sigma); 00501 } 00502 \endcode 00503 00504 use argument objects in conjunction with \ref ArgumentObjectFactories: 00505 \code 00506 namespace vigra { 00507 template <class SrcIterator, class SrcShape, class SrcAccessor, 00508 class DestIterator, class DestAccessor> 00509 void 00510 gaussianGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00511 pair<DestIterator, DestAccessor> const & dest, 00512 double sigma); 00513 } 00514 \endcode 00515 00516 <b> Usage:</b> 00517 00518 <b>\#include</b> "<a href="multi__convolution_8hxx-source.html">vigra/multi_convolution.hxx</a>" 00519 00520 \code 00521 MultiArray<3, unsigned char>::size_type shape(width, height, depth); 00522 MultiArray<3, unsigned char> source(shape); 00523 MultiArray<3, TinyVector<float, 3> > dest(shape); 00524 ... 00525 // compute Gaussian gradient at scale sigma 00526 gaussianGradientMultiArray(srcMultiArrayRange(source), destMultiArray(dest), sigma); 00527 \endcode 00528 00529 <b> Required Interface:</b> 00530 00531 see \ref convolveImage(), in addition: 00532 00533 \code 00534 int dimension = 0; 00535 VectorElementAccessor<DestAccessor> elementAccessor(0, dest); 00536 \endcode 00537 00538 \see separableConvolveMultiArray() 00539 */ 00540 template <class SrcIterator, class SrcShape, class SrcAccessor, 00541 class DestIterator, class DestAccessor> 00542 void 00543 gaussianGradientMultiArray( SrcIterator si, SrcShape const & shape, SrcAccessor src, 00544 DestIterator di, DestAccessor dest, double sigma ) 00545 { 00546 typedef typename DestAccessor::value_type DestType; 00547 typedef typename NumericTraits<typename DestType::value_type>::RealPromote kernel_type; 00548 00549 Kernel1D<kernel_type> gauss, derivative; 00550 gauss.initGaussian(sigma); 00551 derivative.initGaussianDerivative(sigma, 1); 00552 00553 typedef VectorElementAccessor<DestAccessor> ElementAccessor; 00554 00555 // compute gradient components 00556 for(unsigned int d = 0; d < shape.size(); ++d ) 00557 { 00558 ArrayVector<Kernel1D<kernel_type> > kernels(shape.size(), gauss); 00559 kernels[d] = derivative; 00560 separableConvolveMultiArray( si, shape, src, di, ElementAccessor(d, dest), kernels.begin()); 00561 } 00562 } 00563 00564 template <class SrcIterator, class SrcShape, class SrcAccessor, 00565 class DestIterator, class DestAccessor> 00566 inline void 00567 gaussianGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00568 pair<DestIterator, DestAccessor> const & dest, double sigma ) 00569 { 00570 gaussianGradientMultiArray( source.first, source.second, source.third, 00571 dest.first, dest.second, sigma ); 00572 } 00573 00574 /********************************************************/ 00575 /* */ 00576 /* symmetricGradientMultiArray */ 00577 /* */ 00578 /********************************************************/ 00579 00580 /** \brief Calculate gradient of a multi-dimensional arrays using symmetric difference filters. 00581 00582 This function computes the gradient of the given multi-dimensional 00583 array with a sequence of symmetric difference filters a (differentiation is applied 00584 to each dimension in turn, starting with the innermost dimension). Both source and 00585 destination arrays are represented by iterators, shape objects and accessors. 00586 The destination array is required to have a vector valued pixel type with as many 00587 elements as the number of dimensions. This function is implemented by calls to 00588 \ref convolveMultiArrayOneDimension() with the symmetric difference kernel. 00589 00590 <b> Declarations:</b> 00591 00592 pass arguments explicitly: 00593 \code 00594 namespace vigra { 00595 template <class SrcIterator, class SrcShape, class SrcAccessor, 00596 class DestIterator, class DestAccessor> 00597 void 00598 symmetricGradientMultiArray(SrcIterator siter, SrcShape const & shape, SrcAccessor src, 00599 DestIterator diter, DestAccessor dest); 00600 } 00601 \endcode 00602 00603 use argument objects in conjunction with \ref ArgumentObjectFactories: 00604 \code 00605 namespace vigra { 00606 template <class SrcIterator, class SrcShape, class SrcAccessor, 00607 class DestIterator, class DestAccessor> 00608 void 00609 symmetricGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00610 pair<DestIterator, DestAccessor> const & dest); 00611 } 00612 \endcode 00613 00614 <b> Usage:</b> 00615 00616 <b>\#include</b> "<a href="multi__convolution_8hxx-source.html">vigra/multi_convolution.hxx</a>" 00617 00618 \code 00619 MultiArray<3, unsigned char>::size_type shape(width, height, depth); 00620 MultiArray<3, unsigned char> source(shape); 00621 MultiArray<3, TinyVector<float, 3> > dest(shape); 00622 ... 00623 // compute gradient 00624 symmetricGradientMultiArray(srcMultiArrayRange(source), destMultiArray(dest)); 00625 \endcode 00626 00627 <b> Required Interface:</b> 00628 00629 see \ref convolveImage(), in addition: 00630 00631 \code 00632 int dimension = 0; 00633 VectorElementAccessor<DestAccessor> elementAccessor(0, dest); 00634 \endcode 00635 00636 \see convolveMultiArrayOneDimension() 00637 */ 00638 template <class SrcIterator, class SrcShape, class SrcAccessor, 00639 class DestIterator, class DestAccessor> 00640 void 00641 symmetricGradientMultiArray(SrcIterator si, SrcShape const & shape, SrcAccessor src, 00642 DestIterator di, DestAccessor dest) 00643 { 00644 typedef typename DestAccessor::value_type DestType; 00645 typedef typename NumericTraits<typename DestType::value_type>::RealPromote kernel_type; 00646 00647 Kernel1D<kernel_type> filter; 00648 filter.initSymmetricGradient(); 00649 00650 typedef VectorElementAccessor<DestAccessor> ElementAccessor; 00651 00652 // compute gradient components 00653 for(unsigned int d = 0; d < shape.size(); ++d ) 00654 { 00655 convolveMultiArrayOneDimension(si, shape, src, 00656 di, ElementAccessor(d, dest), 00657 d, filter); 00658 } 00659 } 00660 00661 template <class SrcIterator, class SrcShape, class SrcAccessor, 00662 class DestIterator, class DestAccessor> 00663 inline void 00664 symmetricGradientMultiArray(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00665 pair<DestIterator, DestAccessor> const & dest ) 00666 { 00667 symmetricGradientMultiArray(source.first, source.second, source.third, 00668 dest.first, dest.second); 00669 } 00670 00671 //@} 00672 00673 } //-- namespace vigra 00674 00675 00676 #endif //-- VIGRA_MULTI_CONVOLUTION_H
© Ullrich Köthe (koethe@informatik.uni-hamburg.de) |
html generated using doxygen and Python
|