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