[ 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 /* Cognitive Systems Group, University of Hamburg, Germany */ 00006 /* */ 00007 /* This file is part of the VIGRA computer vision library. */ 00008 /* ( Version 1.6.0, Aug 13 2008 ) */ 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_MORPHOLOGY_HXX 00040 #define VIGRA_MULTI_MORPHOLOGY_HXX 00041 00042 #include <vector> 00043 #include <cmath> 00044 #include "multi_distance.hxx" 00045 #include "array_vector.hxx" 00046 #include "multi_array.hxx" 00047 #include "accessor.hxx" 00048 #include "numerictraits.hxx" 00049 #include "navigator.hxx" 00050 #include "metaprogramming.hxx" 00051 #include "multi_pointoperators.hxx" 00052 #include "functorexpression.hxx" 00053 00054 namespace vigra 00055 { 00056 00057 /** \addtogroup MultiArrayMorphology Morphological operators for multi-dimensional arrays. 00058 00059 These functions perform morphological operations on an arbitrary 00060 dimensional array that is specified by iterators (compatible to \ref MultiIteratorPage) 00061 and shape objects. It can therefore be applied to a wide range of data structures 00062 (\ref vigra::MultiArrayView, \ref vigra::MultiArray etc.). 00063 */ 00064 //@{ 00065 00066 /********************************************************/ 00067 /* */ 00068 /* multiBinaryErosion */ 00069 /* */ 00070 /********************************************************/ 00071 /** \brief Binary erosion on multi-dimensional arrays. 00072 00073 This function applies a flat circular erosion operator with a given radius. The 00074 operation is isotropic. 00075 The input is a binary multi-dimensional array where non-zero pixels represent 00076 foreground and zero pixels represent background. 00077 00078 This function may work in-place, which means that <tt>siter == diter</tt> is allowed. 00079 A full-sized internal array is only allocated if working on the destination 00080 array directly would cause overflow errors (i.e. if 00081 <tt> typeid(typename DestAccessor::value_type) < N * M*M</tt>, where M is the 00082 size of the largest dimension of the array. 00083 00084 <b> Declarations:</b> 00085 00086 pass arguments explicitly: 00087 \code 00088 namespace vigra { 00089 template <class SrcIterator, class SrcShape, class SrcAccessor, 00090 class DestIterator, class DestAccessor> 00091 void 00092 multiBinaryErosion(SrcIterator siter, SrcShape const & shape, SrcAccessor src, 00093 DestIterator diter, DestAccessor dest, int radius); 00094 00095 } 00096 \endcode 00097 00098 use argument objects in conjunction with \ref ArgumentObjectFactories : 00099 \code 00100 namespace vigra { 00101 template <class SrcIterator, class SrcShape, class SrcAccessor, 00102 class DestIterator, class DestAccessor> 00103 void 00104 multiBinaryErosion(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00105 pair<DestIterator, DestAccessor> const & dest, 00106 int radius); 00107 00108 } 00109 \endcode 00110 00111 <b> Usage:</b> 00112 00113 <b>\#include</b> <<a href="multi__morphology_8hxx-source.html">vigra/multi_morphology.hxx</a>> 00114 00115 \code 00116 MultiArray<3, unsigned char>::size_type shape(width, height, depth); 00117 MultiArray<3, unsigned char> source(shape); 00118 MultiArray<3, unsigned char> dest(shape); 00119 ... 00120 00121 // perform isotropic binary erosion 00122 multiBinaryErosion(srcMultiArrayRange(source), destMultiArray(dest), 3); 00123 \endcode 00124 00125 \see vigra::discErosion() 00126 */ 00127 doxygen_overloaded_function(template <...> void multiBinaryErosion) 00128 00129 template <class SrcIterator, class SrcShape, class SrcAccessor, 00130 class DestIterator, class DestAccessor> 00131 void 00132 multiBinaryErosion( SrcIterator s, SrcShape const & shape, SrcAccessor src, 00133 DestIterator d, DestAccessor dest, float radius) 00134 { 00135 typedef typename NumericTraits<typename DestAccessor::value_type>::ValueType DestType; 00136 typedef typename NumericTraits<typename DestAccessor::value_type>::Promote TmpType; 00137 DestType MaxValue = NumericTraits<DestType>::max(); 00138 float radius2 = (float) radius * radius; 00139 enum { N = 1 + SrcIterator::level }; 00140 00141 int MaxDim = 0; 00142 for( int i=0; i<N; i++) 00143 if(MaxDim < shape[i]) MaxDim = shape[i]; 00144 00145 using namespace vigra::functor; 00146 00147 // Get the distance squared transform of the image 00148 if(N*MaxDim*MaxDim > MaxValue) 00149 { 00150 // Allocate a new temporary array if the distances squared wouldn't fit 00151 MultiArray<SrcShape::static_size, TmpType> tmpArray(shape); 00152 //detail::internalSeparableMultiArrayDistTmp( s, shape, src, tmpArray.traverser_begin(), 00153 // typename AccessorTraits<TmpType>::default_accessor()/*, false*/ ); 00154 00155 separableMultiDistSquared(s, shape, src, tmpArray.traverser_begin(), 00156 typename AccessorTraits<TmpType>::default_accessor(), false ); 00157 00158 // threshold everything less than radius away from the edge 00159 // std::cerr << "Thresholding!!!!!" << std::endl; 00160 transformMultiArray( tmpArray.traverser_begin(), shape, 00161 typename AccessorTraits<TmpType>::default_accessor(), d, dest, 00162 ifThenElse( Arg1() > Param(radius2), 00163 Param(MaxValue), Param(0) ) ); 00164 } 00165 else // work directly on the destination array 00166 { 00167 //detail::internalSeparableMultiArrayDistTmp( s, shape, src, d, dest/*, false*/ ); 00168 separableMultiDistSquared( s, shape, src, d, dest, false ); 00169 00170 // threshold everything less than radius away from the edge 00171 transformMultiArray( d, shape, dest, d, dest, 00172 ifThenElse( Arg1() > Param(radius2), 00173 Param(MaxValue), Param(0) ) ); 00174 } 00175 } 00176 00177 template <class SrcIterator, class SrcShape, class SrcAccessor, 00178 class DestIterator, class DestAccessor> 00179 inline 00180 void multiBinaryErosion( 00181 triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00182 pair<DestIterator, DestAccessor> const & dest, int radius) 00183 { 00184 multiBinaryErosion( source.first, source.second, source.third, 00185 dest.first, dest.second, radius ); 00186 } 00187 00188 00189 /********************************************************/ 00190 /* */ 00191 /* multiBinaryDilation */ 00192 /* */ 00193 /********************************************************/ 00194 00195 /** \brief Binary dilation on multi-dimensional arrays. 00196 00197 This function applies a flat circular dilation operator with a given radius. The 00198 operation is isotropic. 00199 The input is a binary multi-dimensional array where non-zero pixels represent 00200 foreground and zero pixels represent background. 00201 00202 This function may work in-place, which means that <tt>siter == diter</tt> is allowed. 00203 A full-sized internal array is only allocated if working on the destination 00204 array directly would cause overflow errors (i.e. if 00205 <tt> typeid(typename DestAccessor::value_type) < N * M*M</tt>, where M is the 00206 size of the largest dimension of the array. 00207 00208 <b> Declarations:</b> 00209 00210 pass arguments explicitly: 00211 \code 00212 namespace vigra { 00213 template <class SrcIterator, class SrcShape, class SrcAccessor, 00214 class DestIterator, class DestAccessor> 00215 void 00216 multiBinaryDilation(SrcIterator siter, SrcShape const & shape, SrcAccessor src, 00217 DestIterator diter, DestAccessor dest, int radius); 00218 00219 } 00220 \endcode 00221 00222 use argument objects in conjunction with \ref ArgumentObjectFactories : 00223 \code 00224 namespace vigra { 00225 template <class SrcIterator, class SrcShape, class SrcAccessor, 00226 class DestIterator, class DestAccessor> 00227 void 00228 multiBinaryDilation(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00229 pair<DestIterator, DestAccessor> const & dest, 00230 int radius); 00231 00232 } 00233 \endcode 00234 00235 <b> Usage:</b> 00236 00237 <b>\#include</b> <<a href="multi__morphology_8hxx-source.html">vigra/multi_morphology.hxx</a>> 00238 00239 \code 00240 MultiArray<3, unsigned char>::size_type shape(width, height, depth); 00241 MultiArray<3, unsigned char> source(shape); 00242 MultiArray<3, unsigned char> dest(shape); 00243 ... 00244 00245 // perform isotropic binary erosion 00246 multiBinaryDilation(srcMultiArrayRange(source), destMultiArray(dest), 3); 00247 \endcode 00248 00249 \see vigra::discDilation() 00250 */ 00251 doxygen_overloaded_function(template <...> void multiBinaryDilation) 00252 00253 template <class SrcIterator, class SrcShape, class SrcAccessor, 00254 class DestIterator, class DestAccessor> 00255 void 00256 multiBinaryDilation( SrcIterator s, SrcShape const & shape, SrcAccessor src, 00257 DestIterator d, DestAccessor dest, float radius) 00258 { 00259 typedef typename NumericTraits<typename DestAccessor::value_type>::ValueType DestType; 00260 typedef typename NumericTraits<typename DestAccessor::value_type>::Promote TmpType; 00261 DestType MaxValue = NumericTraits<DestType>::max(); 00262 float radius2 = (float) radius * radius; 00263 enum { N = 1 + SrcIterator::level }; 00264 00265 int MaxDim = 0; 00266 for( int i=0; i<N; i++) 00267 if(MaxDim < shape[i]) MaxDim = shape[i]; 00268 00269 using namespace vigra::functor; 00270 00271 // Get the distance squared transform of the image 00272 if(N*MaxDim*MaxDim > MaxValue) 00273 { 00274 // Allocate a new temporary array if the distances squared wouldn't fit 00275 MultiArray<SrcShape::static_size, TmpType> tmpArray(shape); 00276 //detail::internalSeparableMultiArrayDistTmp( s, shape, src, tmpArray.traverser_begin(), 00277 // typename AccessorTraits<TmpType>::default_accessor(), true ); 00278 00279 separableMultiDistSquared(s, shape, src, tmpArray.traverser_begin(), 00280 typename AccessorTraits<TmpType>::default_accessor(), true ); 00281 00282 // threshold everything less than radius away from the edge 00283 transformMultiArray( tmpArray.traverser_begin(), shape, 00284 typename AccessorTraits<TmpType>::default_accessor(), d, dest, 00285 ifThenElse( Arg1() > Param(radius2), 00286 Param(0), Param(MaxValue) ) ); 00287 } 00288 else // work directly on the destination array 00289 { 00290 //detail::internalSeparableMultiArrayDistTmp( s, shape, src, d, dest, true ); 00291 separableMultiDistSquared( s, shape, src, d, dest, true ); 00292 00293 // threshold everything less than radius away from the edge 00294 transformMultiArray( d, shape, dest, d, dest, 00295 ifThenElse( Arg1() > Param(radius2), 00296 Param(0), Param(MaxValue) ) ); 00297 } 00298 } 00299 00300 template <class SrcIterator, class SrcShape, class SrcAccessor, 00301 class DestIterator, class DestAccessor> 00302 inline 00303 void multiBinaryDilation( 00304 triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00305 pair<DestIterator, DestAccessor> const & dest, int radius) 00306 { 00307 multiBinaryDilation( source.first, source.second, source.third, 00308 dest.first, dest.second, radius ); 00309 } 00310 00311 /********************************************************/ 00312 /* */ 00313 /* multiGrayscaleErosion */ 00314 /* */ 00315 /********************************************************/ 00316 /** \brief Parabolic grayscale erosion on multi-dimensional arrays. 00317 00318 This function applies a parabolic erosion operator with a given spread (sigma) on 00319 a grayscale array. The operation is isotropic. 00320 The input is a grayscale multi-dimensional array. 00321 00322 This function may work in-place, which means that <tt>siter == diter</tt> is allowed. 00323 A full-sized internal array is only allocated if working on the destination 00324 array directly would cause overflow errors (i.e. if 00325 <tt> typeid(typename DestAccessor::value_type) < N * M*M</tt>, where M is the 00326 size of the largest dimension of the array. 00327 00328 <b> Declarations:</b> 00329 00330 pass arguments explicitly: 00331 \code 00332 namespace vigra { 00333 template <class SrcIterator, class SrcShape, class SrcAccessor, 00334 class DestIterator, class DestAccessor> 00335 void 00336 multiGrayscaleErosion(SrcIterator siter, SrcShape const & shape, SrcAccessor src, 00337 DestIterator diter, DestAccessor dest, float sigma); 00338 00339 } 00340 \endcode 00341 00342 use argument objects in conjunction with \ref ArgumentObjectFactories : 00343 \code 00344 namespace vigra { 00345 template <class SrcIterator, class SrcShape, class SrcAccessor, 00346 class DestIterator, class DestAccessor> 00347 void 00348 multiGrayscaleErosion(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00349 pair<DestIterator, DestAccessor> const & dest, 00350 float sigma); 00351 00352 } 00353 \endcode 00354 00355 <b> Usage:</b> 00356 00357 <b>\#include</b> <<a href="multi__morphology_8hxx-source.html">vigra/multi_morphology.hxx</a>> 00358 00359 \code 00360 MultiArray<3, unsigned char>::size_type shape(width, height, depth); 00361 MultiArray<3, unsigned char> source(shape); 00362 MultiArray<3, unsigned char> dest(shape); 00363 ... 00364 00365 // perform isotropic grayscale erosion 00366 multiGrayscaleErosion(srcMultiArrayRange(source), destMultiArray(dest), 3.0); 00367 \endcode 00368 00369 \see vigra::discErosion() 00370 */ 00371 doxygen_overloaded_function(template <...> void multiGrayscaleErosion) 00372 00373 template <class SrcIterator, class SrcShape, class SrcAccessor, 00374 class DestIterator, class DestAccessor> 00375 void 00376 multiGrayscaleErosion( SrcIterator s, SrcShape const & shape, SrcAccessor src, 00377 DestIterator d, DestAccessor dest, float sigma) 00378 { 00379 typedef typename NumericTraits<typename DestAccessor::value_type>::ValueType DestType; 00380 typedef typename NumericTraits<typename DestAccessor::value_type>::Promote TmpType; 00381 DestType MaxValue = NumericTraits<DestType>::max(); 00382 enum { N = 1 + SrcIterator::level }; 00383 00384 // temporay array to hold the current line to enable in-place operation 00385 ArrayVector<TmpType> tmp( shape[0] ); 00386 00387 typedef MultiArrayNavigator<SrcIterator, N> SNavigator; 00388 typedef MultiArrayNavigator<DestIterator, N> DNavigator; 00389 00390 int MaxDim = 0; 00391 for( int i=0; i<N; i++) 00392 if(MaxDim < shape[i]) MaxDim = shape[i]; 00393 00394 using namespace vigra::functor; 00395 00396 // Allocate a new temporary array if the distances squared wouldn't fit 00397 if(N*MaxDim*MaxDim > MaxValue) 00398 { 00399 MultiArray<SrcShape::static_size, TmpType> tmpArray(shape); 00400 00401 detail::internalSeparableMultiArrayDistTmp( s, shape, src, tmpArray.traverser_begin(), 00402 typename AccessorTraits<TmpType>::default_accessor(), sigma ); 00403 00404 transformMultiArray( tmpArray.traverser_begin(), shape, 00405 typename AccessorTraits<TmpType>::default_accessor(), d, dest, 00406 ifThenElse( Arg1() > Param(MaxValue), Param(MaxValue), Arg1() ) ); 00407 //copyMultiArray( tmpArray.traverser_begin(), shape, 00408 // typename AccessorTraits<TmpType>::default_accessor(), d, dest ); 00409 } 00410 else 00411 { 00412 detail::internalSeparableMultiArrayDistTmp( s, shape, src, d, dest, sigma ); 00413 } 00414 00415 } 00416 00417 template <class SrcIterator, class SrcShape, class SrcAccessor, 00418 class DestIterator, class DestAccessor> 00419 inline 00420 void multiGrayscaleErosion( 00421 triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00422 pair<DestIterator, DestAccessor> const & dest, float sigma) 00423 { 00424 multiGrayscaleErosion( source.first, source.second, source.third, 00425 dest.first, dest.second, sigma); 00426 } 00427 00428 /********************************************************/ 00429 /* */ 00430 /* multiGrayscaleDilation */ 00431 /* */ 00432 /********************************************************/ 00433 /** \brief Parabolic grayscale dilation on multi-dimensional arrays. 00434 00435 This function applies a parabolic dilation operator with a given spread (sigma) on 00436 a grayscale array. The operation is isotropic. 00437 The input is a grayscale multi-dimensional array. 00438 00439 This function may work in-place, which means that <tt>siter == diter</tt> is allowed. 00440 A full-sized internal array is only allocated if working on the destination 00441 array directly would cause overflow errors (i.e. if 00442 <tt> typeid(typename DestAccessor::value_type) < N * M*M</tt>, where M is the 00443 size of the largest dimension of the array. 00444 00445 <b> Declarations:</b> 00446 00447 pass arguments explicitly: 00448 \code 00449 namespace vigra { 00450 template <class SrcIterator, class SrcShape, class SrcAccessor, 00451 class DestIterator, class DestAccessor> 00452 void 00453 multiGrayscaleDilation(SrcIterator siter, SrcShape const & shape, SrcAccessor src, 00454 DestIterator diter, DestAccessor dest, float sigma); 00455 00456 } 00457 \endcode 00458 00459 use argument objects in conjunction with \ref ArgumentObjectFactories : 00460 \code 00461 namespace vigra { 00462 template <class SrcIterator, class SrcShape, class SrcAccessor, 00463 class DestIterator, class DestAccessor> 00464 void 00465 multiGrayscaleDilation(triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00466 pair<DestIterator, DestAccessor> const & dest, 00467 float sigma); 00468 00469 } 00470 \endcode 00471 00472 <b> Usage:</b> 00473 00474 <b>\#include</b> <<a href="multi__morphology_8hxx-source.html">vigra/multi_morphology.hxx</a>> 00475 00476 \code 00477 MultiArray<3, unsigned char>::size_type shape(width, height, depth); 00478 MultiArray<3, unsigned char> source(shape); 00479 MultiArray<3, unsigned char> dest(shape); 00480 ... 00481 00482 // perform isotropic grayscale erosion 00483 multiGrayscaleDilation(srcMultiArrayRange(source), destMultiArray(dest), 3.0); 00484 \endcode 00485 00486 \see vigra::discErosion() 00487 */ 00488 doxygen_overloaded_function(template <...> void multiGrayscaleDilation) 00489 00490 template <class SrcIterator, class SrcShape, class SrcAccessor, 00491 class DestIterator, class DestAccessor> 00492 void multiGrayscaleDilation( SrcIterator s, SrcShape const & shape, SrcAccessor src, 00493 DestIterator d, DestAccessor dest, float sigma) 00494 { 00495 typedef typename NumericTraits<typename DestAccessor::value_type>::ValueType DestType; 00496 typedef typename NumericTraits<typename DestAccessor::value_type>::Promote TmpType; 00497 DestType MinValue = NumericTraits<DestType>::min(); 00498 DestType MaxValue = NumericTraits<DestType>::max(); 00499 enum { N = 1 + SrcIterator::level }; 00500 00501 // temporay array to hold the current line to enable in-place operation 00502 ArrayVector<TmpType> tmp( shape[0] ); 00503 00504 typedef MultiArrayNavigator<SrcIterator, N> SNavigator; 00505 typedef MultiArrayNavigator<DestIterator, N> DNavigator; 00506 00507 int MaxDim = 0; 00508 for( int i=0; i<N; i++) 00509 if(MaxDim < shape[i]) MaxDim = shape[i]; 00510 00511 using namespace vigra::functor; 00512 00513 // Allocate a new temporary array if the distances squared wouldn't fit 00514 if(-N*MaxDim*MaxDim < MinValue || N*MaxDim*MaxDim > MaxValue) 00515 { 00516 MultiArray<SrcShape::static_size, TmpType> tmpArray(shape); 00517 00518 detail::internalSeparableMultiArrayDistTmp( s, shape, src, tmpArray.traverser_begin(), 00519 typename AccessorTraits<TmpType>::default_accessor(), sigma, true ); 00520 00521 transformMultiArray( tmpArray.traverser_begin(), shape, 00522 typename AccessorTraits<TmpType>::default_accessor(), d, dest, 00523 ifThenElse( Arg1() > Param(MaxValue), Param(MaxValue), 00524 ifThenElse( Arg1() < Param(MinValue), Param(MinValue), Arg1() ) ) ); 00525 } 00526 else 00527 { 00528 detail::internalSeparableMultiArrayDistTmp( s, shape, src, d, dest, sigma, true ); 00529 } 00530 00531 } 00532 00533 00534 template <class SrcIterator, class SrcShape, class SrcAccessor, 00535 class DestIterator, class DestAccessor> 00536 inline 00537 void multiGrayscaleDilation( 00538 triple<SrcIterator, SrcShape, SrcAccessor> const & source, 00539 pair<DestIterator, DestAccessor> const & dest, float sigma) 00540 { 00541 multiGrayscaleDilation( source.first, source.second, source.third, 00542 dest.first, dest.second, sigma); 00543 } 00544 00545 00546 //@} 00547 00548 } //-- namespace vigra 00549 00550 00551 #endif //-- VIGRA_MULTI_MORPHOLOGY_HXX
© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) |
html generated using doxygen and Python
|