[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]
00001 /************************************************************************/ 00002 /* */ 00003 /* Copyright 2003-2007 by Kasim Terzic, Christian-Dennis Rahn */ 00004 /* and Ullrich Koethe */ 00005 /* */ 00006 /* This file is part of the VIGRA computer vision library. */ 00007 /* The VIGRA Website is */ 00008 /* http://hci.iwr.uni-heidelberg.de/vigra/ */ 00009 /* Please direct questions, bug reports, and contributions to */ 00010 /* ullrich.koethe@iwr.uni-heidelberg.de or */ 00011 /* vigra@informatik.uni-hamburg.de */ 00012 /* */ 00013 /* Permission is hereby granted, free of charge, to any person */ 00014 /* obtaining a copy of this software and associated documentation */ 00015 /* files (the "Software"), to deal in the Software without */ 00016 /* restriction, including without limitation the rights to use, */ 00017 /* copy, modify, merge, publish, distribute, sublicense, and/or */ 00018 /* sell copies of the Software, and to permit persons to whom the */ 00019 /* Software is furnished to do so, subject to the following */ 00020 /* conditions: */ 00021 /* */ 00022 /* The above copyright notice and this permission notice shall be */ 00023 /* included in all copies or substantial portions of the */ 00024 /* Software. */ 00025 /* */ 00026 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */ 00027 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ 00028 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ 00029 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ 00030 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ 00031 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ 00032 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ 00033 /* OTHER DEALINGS IN THE SOFTWARE. */ 00034 /* */ 00035 /************************************************************************/ 00036 00037 #ifndef VIGRA_MULTI_MORPHOLOGY_HXX 00038 #define VIGRA_MULTI_MORPHOLOGY_HXX 00039 00040 #include <vector> 00041 #include <cmath> 00042 #include "multi_distance.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 #include "functorexpression.hxx" 00051 00052 namespace vigra 00053 { 00054 00055 namespace detail { 00056 00057 // this class simplfies the design, but more importantly, it makes sure 00058 // that the in-place code doesn't get compiled for boolean arrays 00059 // (were it would never executed anyway -- see the specializations below) 00060 template <class DestType, class TmpType> 00061 struct MultiBinaryMorphologyImpl 00062 { 00063 template <class SrcIterator, class SrcShape, class SrcAccessor, 00064 class DestIterator, class DestAccessor> 00065 static void 00066 exec( SrcIterator s, SrcShape const & shape, SrcAccessor src, 00067 DestIterator d, DestAccessor dest, 00068 double radius, bool dilation) 00069 { 00070 using namespace vigra::functor; 00071 00072 // Allocate a new temporary array if the distances squared wouldn't fit 00073 MultiArray<SrcShape::static_size, TmpType> tmpArray(shape); 00074 00075 separableMultiDistSquared(s, shape, src, 00076 tmpArray.traverser_begin(), typename AccessorTraits<TmpType>::default_accessor(), dilation ); 00077 00078 // threshold everything less than radius away from the edge 00079 double radius2 = radius * radius; 00080 DestType foreground = dilation 00081 ? NumericTraits<DestType>::zero() 00082 : NumericTraits<DestType>::one(), 00083 background = dilation 00084 ? NumericTraits<DestType>::one() 00085 : NumericTraits<DestType>::zero(); 00086 transformMultiArray( tmpArray.traverser_begin(), shape, StandardValueAccessor<double>(), 00087 d, dest, 00088 ifThenElse( Arg1() >= Param(radius2), 00089 Param(foreground), Param(background) ) ); 00090 } 00091 }; 00092 00093 template <class DestType> 00094 struct MultiBinaryMorphologyImpl<DestType, DestType> 00095 { 00096 template <class SrcIterator, class SrcShape, class SrcAccessor, 00097 class DestIterator, class DestAccessor> 00098 static void 00099 exec( SrcIterator s, SrcShape const & shape, SrcAccessor src, 00100 DestIterator d, DestAccessor dest, 00101 double radius, bool dilation) 00102 { 00103 using namespace vigra::functor; 00104 00105 separableMultiDistSquared( s, shape, src, d, dest, dilation ); 00106 00107 // threshold everything less than radius away from the edge 00108 DestType radius2 = detail::RequiresExplicitCast<DestType>::cast(radius * radius); 00109 DestType foreground = dilation 00110 ? NumericTraits<DestType>::zero() 00111 : NumericTraits<DestType>::one(), 00112 background = dilation 00113 ? NumericTraits<DestType>::one() 00114 : NumericTraits<DestType>::zero(); 00115 transformMultiArray( d, shape, dest, d, dest, 00116 ifThenElse( Arg1() > Param(radius2), 00117 Param(foreground), Param(background) ) ); 00118 } 00119 }; 00120 00121 template <> 00122 struct MultiBinaryMorphologyImpl<bool, bool> 00123 { 00124 template <class SrcIterator, class SrcShape, class SrcAccessor, 00125 class DestIterator, class DestAccessor> 00126 static void 00127 exec( SrcIterator s, SrcShape const & shape, SrcAccessor src, 00128 DestIterator d, DestAccessor dest, double radius, bool dilation) 00129 { 00130 vigra_fail("multiBinaryMorphology(): Internal error (this function should never be called)."); 00131 } 00132 }; 00133 00134 } // namespace detail 00135 00136 /** \addtogroup MultiArrayMorphology Morphological operators for multi-dimensional arrays. 00137 00138 These functions perform morphological operations on an arbitrary 00139 dimensional array that is specified by iterators (compatible to \ref MultiIteratorPage) 00140 and shape objects. It can therefore be applied to a wide range of data structures 00141 (\ref vigra::MultiArrayView, \ref vigra::MultiArray etc.). 00142 */ 00143 //@{ 00144 00145 /********************************************************/ 00146 /* */ 00147 /* multiBinaryErosion */ 00148 /* */ 00149 /********************************************************/ 00150 /** \brief Binary erosion on multi-dimensional arrays. 00151 00152 This function applies a flat circular erosion operator with a given radius. The 00153 operation is isotropic. The input is intepreted as a binary multi-dimensional 00154 array where non-zero pixels represent foreground and zero pixels represent 00155 background. In the output, foregound is always represented by ones 00156 (i.e. NumericTrais<typename DestAccessor::value_type>::one()). 00157 00158 This function may work in-place, which means that <tt>siter == diter</tt> is allowed. 00159 A temporary internal array is only allocated if working on the destination 00160 array directly would cause overflow errors (that is if 00161 <tt> NumericTraits<typename DestAccessor::value_type>::max() < squaredNorm(shape)</tt>, 00162 i.e. the squared length of the image diagonal doesn't fit into the destination type). 00163 00164 <b> Declarations:</b> 00165 00166 pass arguments explicitly: 00167 \code 00168 namespace vigra { 00169 template <class SrcIterator, class SrcShape, class SrcAccessor, 00170 class DestIterator, class DestAccessor> 00171 void 00172 multiBinaryErosion(SrcIterator siter, SrcShape const & shape, SrcAccessor src, 00173 DestIterator diter, DestAccessor dest, int radius); 00174 00175 } 00176 \endcode 00177 00178 use argument objects in conjunction with \ref ArgumentObjectFactories : 00179 \code 00180 namespace vigra { 00181 template <class SrcIterator, class SrcShape, class SrcAccessor, 00182 class DestIterator, class DestAccessor> 00183 void 00184 multiBinaryErosion(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00185 pair<DestIterator, DestAccessor> const & dest, 00186 int radius); 00187 00188 } 00189 \endcode 00190 00191 <b> Usage:</b> 00192 00193 <b>\#include</b> <<a href="multi__morphology_8hxx-source.html">vigra/multi_morphology.hxx</a>> 00194 00195 \code 00196 MultiArray<3, unsigned char>::size_type shape(width, height, depth); 00197 MultiArray<3, unsigned char> source(shape); 00198 MultiArray<3, unsigned char> dest(shape); 00199 ... 00200 00201 // perform isotropic binary erosion 00202 multiBinaryErosion(srcMultiArrayRange(source), destMultiArray(dest), 3); 00203 \endcode 00204 00205 \see vigra::discErosion() 00206 */ 00207 doxygen_overloaded_function(template <...> void multiBinaryErosion) 00208 00209 template <class SrcIterator, class SrcShape, class SrcAccessor, 00210 class DestIterator, class DestAccessor> 00211 void 00212 multiBinaryErosion( SrcIterator s, SrcShape const & shape, SrcAccessor src, 00213 DestIterator d, DestAccessor dest, double radius) 00214 { 00215 typedef typename DestAccessor::value_type DestType; 00216 typedef Int32 TmpType; 00217 00218 double dmax = squaredNorm(shape); 00219 00220 // Get the distance squared transform of the image 00221 if(dmax > NumericTraits<DestType>::toRealPromote(NumericTraits<DestType>::max())) 00222 { 00223 detail::MultiBinaryMorphologyImpl<DestType, TmpType>::exec(s, shape, src, d, dest, radius, false); 00224 } 00225 else // work directly on the destination array 00226 { 00227 detail::MultiBinaryMorphologyImpl<DestType, DestType>::exec(s, shape, src, d, dest, radius, false); 00228 } 00229 } 00230 00231 template <class SrcIterator, class SrcShape, class SrcAccessor, 00232 class DestIterator, class DestAccessor> 00233 inline 00234 void multiBinaryErosion( 00235 triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00236 pair<DestIterator, DestAccessor> const & dest, double radius) 00237 { 00238 multiBinaryErosion( source.first, source.second, source.third, 00239 dest.first, dest.second, radius ); 00240 } 00241 00242 00243 /********************************************************/ 00244 /* */ 00245 /* multiBinaryDilation */ 00246 /* */ 00247 /********************************************************/ 00248 00249 /** \brief Binary dilation on multi-dimensional arrays. 00250 00251 This function applies a flat circular dilation operator with a given radius. The 00252 operation is isotropic. The input is intepreted as a binary multi-dimensional 00253 array where non-zero pixels represent foreground and zero pixels represent 00254 background. In the output, foregound is always represented by ones 00255 (i.e. NumericTrais<typename DestAccessor::value_type>::one()). 00256 00257 This function may work in-place, which means that <tt>siter == diter</tt> is allowed. 00258 A temporary internal array is only allocated if working on the destination 00259 array directly would cause overflow errors (that is if 00260 <tt> NumericTraits<typename DestAccessor::value_type>::max() < squaredNorm(shape)</tt>, 00261 i.e. the squared length of the image diagonal doesn't fit into the destination type). 00262 00263 <b> Declarations:</b> 00264 00265 pass arguments explicitly: 00266 \code 00267 namespace vigra { 00268 template <class SrcIterator, class SrcShape, class SrcAccessor, 00269 class DestIterator, class DestAccessor> 00270 void 00271 multiBinaryDilation(SrcIterator siter, SrcShape const & shape, SrcAccessor src, 00272 DestIterator diter, DestAccessor dest, int radius); 00273 00274 } 00275 \endcode 00276 00277 use argument objects in conjunction with \ref ArgumentObjectFactories : 00278 \code 00279 namespace vigra { 00280 template <class SrcIterator, class SrcShape, class SrcAccessor, 00281 class DestIterator, class DestAccessor> 00282 void 00283 multiBinaryDilation(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00284 pair<DestIterator, DestAccessor> const & dest, 00285 int radius); 00286 00287 } 00288 \endcode 00289 00290 <b> Usage:</b> 00291 00292 <b>\#include</b> <<a href="multi__morphology_8hxx-source.html">vigra/multi_morphology.hxx</a>> 00293 00294 \code 00295 MultiArray<3, unsigned char>::size_type shape(width, height, depth); 00296 MultiArray<3, unsigned char> source(shape); 00297 MultiArray<3, unsigned char> dest(shape); 00298 ... 00299 00300 // perform isotropic binary erosion 00301 multiBinaryDilation(srcMultiArrayRange(source), destMultiArray(dest), 3); 00302 \endcode 00303 00304 \see vigra::discDilation() 00305 */ 00306 doxygen_overloaded_function(template <...> void multiBinaryDilation) 00307 00308 template <class SrcIterator, class SrcShape, class SrcAccessor, 00309 class DestIterator, class DestAccessor> 00310 void 00311 multiBinaryDilation( SrcIterator s, SrcShape const & shape, SrcAccessor src, 00312 DestIterator d, DestAccessor dest, double radius) 00313 { 00314 typedef typename DestAccessor::value_type DestType; 00315 typedef Int32 TmpType; 00316 00317 double dmax = squaredNorm(shape); 00318 00319 // Get the distance squared transform of the image 00320 if(dmax > NumericTraits<DestType>::toRealPromote(NumericTraits<DestType>::max())) 00321 { 00322 detail::MultiBinaryMorphologyImpl<DestType, TmpType>::exec(s, shape, src, d, dest, radius, true); 00323 } 00324 else // work directly on the destination array 00325 { 00326 detail::MultiBinaryMorphologyImpl<DestType, DestType>::exec(s, shape, src, d, dest, radius, true); 00327 } 00328 } 00329 00330 template <class SrcIterator, class SrcShape, class SrcAccessor, 00331 class DestIterator, class DestAccessor> 00332 inline 00333 void multiBinaryDilation( 00334 triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00335 pair<DestIterator, DestAccessor> const & dest, double radius) 00336 { 00337 multiBinaryDilation( source.first, source.second, source.third, 00338 dest.first, dest.second, radius ); 00339 } 00340 00341 /********************************************************/ 00342 /* */ 00343 /* multiGrayscaleErosion */ 00344 /* */ 00345 /********************************************************/ 00346 /** \brief Parabolic grayscale erosion on multi-dimensional arrays. 00347 00348 This function applies a parabolic erosion operator with a given spread (sigma) on 00349 a grayscale array. The operation is isotropic. 00350 The input is a grayscale multi-dimensional array. 00351 00352 This function may work in-place, which means that <tt>siter == diter</tt> is allowed. 00353 A full-sized internal array is only allocated if working on the destination 00354 array directly would cause overflow errors (i.e. if 00355 <tt> typeid(typename DestAccessor::value_type) < N * M*M</tt>, where M is the 00356 size of the largest dimension of the array. 00357 00358 <b> Declarations:</b> 00359 00360 pass arguments explicitly: 00361 \code 00362 namespace vigra { 00363 template <class SrcIterator, class SrcShape, class SrcAccessor, 00364 class DestIterator, class DestAccessor> 00365 void 00366 multiGrayscaleErosion(SrcIterator siter, SrcShape const & shape, SrcAccessor src, 00367 DestIterator diter, DestAccessor dest, double sigma); 00368 00369 } 00370 \endcode 00371 00372 use argument objects in conjunction with \ref ArgumentObjectFactories : 00373 \code 00374 namespace vigra { 00375 template <class SrcIterator, class SrcShape, class SrcAccessor, 00376 class DestIterator, class DestAccessor> 00377 void 00378 multiGrayscaleErosion(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00379 pair<DestIterator, DestAccessor> const & dest, 00380 double sigma); 00381 00382 } 00383 \endcode 00384 00385 <b> Usage:</b> 00386 00387 <b>\#include</b> <<a href="multi__morphology_8hxx-source.html">vigra/multi_morphology.hxx</a>> 00388 00389 \code 00390 MultiArray<3, unsigned char>::size_type shape(width, height, depth); 00391 MultiArray<3, unsigned char> source(shape); 00392 MultiArray<3, unsigned char> dest(shape); 00393 ... 00394 00395 // perform isotropic grayscale erosion 00396 multiGrayscaleErosion(srcMultiArrayRange(source), destMultiArray(dest), 3.0); 00397 \endcode 00398 00399 \see vigra::discErosion() 00400 */ 00401 doxygen_overloaded_function(template <...> void multiGrayscaleErosion) 00402 00403 template <class SrcIterator, class SrcShape, class SrcAccessor, 00404 class DestIterator, class DestAccessor> 00405 void 00406 multiGrayscaleErosion( SrcIterator s, SrcShape const & shape, SrcAccessor src, 00407 DestIterator d, DestAccessor dest, double sigma) 00408 { 00409 typedef typename NumericTraits<typename DestAccessor::value_type>::ValueType DestType; 00410 typedef typename NumericTraits<typename DestAccessor::value_type>::Promote TmpType; 00411 DestType MaxValue = NumericTraits<DestType>::max(); 00412 enum { N = 1 + SrcIterator::level }; 00413 00414 // temporay array to hold the current line to enable in-place operation 00415 ArrayVector<TmpType> tmp( shape[0] ); 00416 00417 typedef MultiArrayNavigator<SrcIterator, N> SNavigator; 00418 typedef MultiArrayNavigator<DestIterator, N> DNavigator; 00419 00420 int MaxDim = 0; 00421 for( int i=0; i<N; i++) 00422 if(MaxDim < shape[i]) MaxDim = shape[i]; 00423 00424 using namespace vigra::functor; 00425 00426 ArrayVector<double> sigmas(shape.size(), sigma); 00427 00428 // Allocate a new temporary array if the distances squared wouldn't fit 00429 if(N*MaxDim*MaxDim > MaxValue) 00430 { 00431 MultiArray<SrcShape::static_size, TmpType> tmpArray(shape); 00432 00433 detail::internalSeparableMultiArrayDistTmp( s, shape, src, tmpArray.traverser_begin(), 00434 typename AccessorTraits<TmpType>::default_accessor(), sigmas ); 00435 00436 transformMultiArray( tmpArray.traverser_begin(), shape, 00437 typename AccessorTraits<TmpType>::default_accessor(), d, dest, 00438 ifThenElse( Arg1() > Param(MaxValue), Param(MaxValue), Arg1() ) ); 00439 //copyMultiArray( tmpArray.traverser_begin(), shape, 00440 // typename AccessorTraits<TmpType>::default_accessor(), d, dest ); 00441 } 00442 else 00443 { 00444 detail::internalSeparableMultiArrayDistTmp( s, shape, src, d, dest, sigmas ); 00445 } 00446 00447 } 00448 00449 template <class SrcIterator, class SrcShape, class SrcAccessor, 00450 class DestIterator, class DestAccessor> 00451 inline 00452 void multiGrayscaleErosion( 00453 triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00454 pair<DestIterator, DestAccessor> const & dest, double sigma) 00455 { 00456 multiGrayscaleErosion( source.first, source.second, source.third, 00457 dest.first, dest.second, sigma); 00458 } 00459 00460 /********************************************************/ 00461 /* */ 00462 /* multiGrayscaleDilation */ 00463 /* */ 00464 /********************************************************/ 00465 /** \brief Parabolic grayscale dilation on multi-dimensional arrays. 00466 00467 This function applies a parabolic dilation operator with a given spread (sigma) on 00468 a grayscale array. The operation is isotropic. 00469 The input is a grayscale multi-dimensional array. 00470 00471 This function may work in-place, which means that <tt>siter == diter</tt> is allowed. 00472 A full-sized internal array is only allocated if working on the destination 00473 array directly would cause overflow errors (i.e. if 00474 <tt> typeid(typename DestAccessor::value_type) < N * M*M</tt>, where M is the 00475 size of the largest dimension of the array. 00476 00477 <b> Declarations:</b> 00478 00479 pass arguments explicitly: 00480 \code 00481 namespace vigra { 00482 template <class SrcIterator, class SrcShape, class SrcAccessor, 00483 class DestIterator, class DestAccessor> 00484 void 00485 multiGrayscaleDilation(SrcIterator siter, SrcShape const & shape, SrcAccessor src, 00486 DestIterator diter, DestAccessor dest, double sigma); 00487 00488 } 00489 \endcode 00490 00491 use argument objects in conjunction with \ref ArgumentObjectFactories : 00492 \code 00493 namespace vigra { 00494 template <class SrcIterator, class SrcShape, class SrcAccessor, 00495 class DestIterator, class DestAccessor> 00496 void 00497 multiGrayscaleDilation(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00498 pair<DestIterator, DestAccessor> const & dest, 00499 double sigma); 00500 00501 } 00502 \endcode 00503 00504 <b> Usage:</b> 00505 00506 <b>\#include</b> <<a href="multi__morphology_8hxx-source.html">vigra/multi_morphology.hxx</a>> 00507 00508 \code 00509 MultiArray<3, unsigned char>::size_type shape(width, height, depth); 00510 MultiArray<3, unsigned char> source(shape); 00511 MultiArray<3, unsigned char> dest(shape); 00512 ... 00513 00514 // perform isotropic grayscale erosion 00515 multiGrayscaleDilation(srcMultiArrayRange(source), destMultiArray(dest), 3.0); 00516 \endcode 00517 00518 \see vigra::discErosion() 00519 */ 00520 doxygen_overloaded_function(template <...> void multiGrayscaleDilation) 00521 00522 template <class SrcIterator, class SrcShape, class SrcAccessor, 00523 class DestIterator, class DestAccessor> 00524 void multiGrayscaleDilation( SrcIterator s, SrcShape const & shape, SrcAccessor src, 00525 DestIterator d, DestAccessor dest, double sigma) 00526 { 00527 typedef typename NumericTraits<typename DestAccessor::value_type>::ValueType DestType; 00528 typedef typename NumericTraits<typename DestAccessor::value_type>::Promote TmpType; 00529 DestType MinValue = NumericTraits<DestType>::min(); 00530 DestType MaxValue = NumericTraits<DestType>::max(); 00531 enum { N = 1 + SrcIterator::level }; 00532 00533 // temporay array to hold the current line to enable in-place operation 00534 ArrayVector<TmpType> tmp( shape[0] ); 00535 00536 typedef MultiArrayNavigator<SrcIterator, N> SNavigator; 00537 typedef MultiArrayNavigator<DestIterator, N> DNavigator; 00538 00539 int MaxDim = 0; 00540 for( int i=0; i<N; i++) 00541 if(MaxDim < shape[i]) MaxDim = shape[i]; 00542 00543 using namespace vigra::functor; 00544 00545 ArrayVector<double> sigmas(shape.size(), sigma); 00546 00547 // Allocate a new temporary array if the distances squared wouldn't fit 00548 if(-N*MaxDim*MaxDim < MinValue || N*MaxDim*MaxDim > MaxValue) 00549 { 00550 MultiArray<SrcShape::static_size, TmpType> tmpArray(shape); 00551 00552 detail::internalSeparableMultiArrayDistTmp( s, shape, src, tmpArray.traverser_begin(), 00553 typename AccessorTraits<TmpType>::default_accessor(), sigmas, true ); 00554 00555 transformMultiArray( tmpArray.traverser_begin(), shape, 00556 typename AccessorTraits<TmpType>::default_accessor(), d, dest, 00557 ifThenElse( Arg1() > Param(MaxValue), Param(MaxValue), 00558 ifThenElse( Arg1() < Param(MinValue), Param(MinValue), Arg1() ) ) ); 00559 } 00560 else 00561 { 00562 detail::internalSeparableMultiArrayDistTmp( s, shape, src, d, dest, sigmas, true ); 00563 } 00564 00565 } 00566 00567 00568 template <class SrcIterator, class SrcShape, class SrcAccessor, 00569 class DestIterator, class DestAccessor> 00570 inline 00571 void multiGrayscaleDilation( 00572 triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00573 pair<DestIterator, DestAccessor> const & dest, double sigma) 00574 { 00575 multiGrayscaleDilation( source.first, source.second, source.third, 00576 dest.first, dest.second, sigma); 00577 } 00578 00579 00580 //@} 00581 00582 } //-- namespace vigra 00583 00584 00585 #endif //-- VIGRA_MULTI_MORPHOLOGY_HXX
© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) |
html generated using doxygen and Python
|