[ VIGRA Homepage | Class Index | Function Index | File Index | Main Page ]
![]() |
vigra/inspectimage.hxx | ![]() |
---|
00001 /************************************************************************/ 00002 /* */ 00003 /* Copyright 1998-2002 by Ullrich Koethe */ 00004 /* Cognitive Systems Group, University of Hamburg, Germany */ 00005 /* */ 00006 /* This file is part of the VIGRA computer vision library. */ 00007 /* ( Version 1.5.0, Dec 07 2006 ) */ 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 /* koethe@informatik.uni-hamburg.de or */ 00012 /* vigra@kogs1.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 00039 #ifndef VIGRA_INSPECTIMAGE_HXX 00040 #define VIGRA_INSPECTIMAGE_HXX 00041 00042 #include <vector> 00043 #include <algorithm> 00044 #include "utilities.hxx" 00045 #include "numerictraits.hxx" 00046 #include "iteratortraits.hxx" 00047 #include "functortraits.hxx" 00048 #include "rgbvalue.hxx" 00049 00050 namespace vigra { 00051 00052 /** \addtogroup InspectAlgo Algorithms to Inspect Images 00053 00054 Apply read-only functor to every pixel 00055 */ 00056 //@{ 00057 00058 /********************************************************/ 00059 /* */ 00060 /* inspectLine */ 00061 /* */ 00062 /********************************************************/ 00063 00064 template <class SrcIterator, class SrcAccessor, class Functor> 00065 void 00066 inspectLine(SrcIterator s, 00067 SrcIterator send, SrcAccessor src, 00068 Functor & f) 00069 { 00070 for(; s != send; ++s) 00071 f(src(s)); 00072 } 00073 00074 template <class SrcIterator, class SrcAccessor, 00075 class MaskIterator, class MaskAccessor, 00076 class Functor> 00077 void 00078 inspectLineIf(SrcIterator s, 00079 SrcIterator send, SrcAccessor src, 00080 MaskIterator m, MaskAccessor mask, 00081 Functor & f) 00082 { 00083 for(; s != send; ++s, ++m) 00084 if(mask(m)) 00085 f(src(s)); 00086 } 00087 00088 template <class SrcIterator1, class SrcAccessor1, 00089 class SrcIterator2, class SrcAccessor2, 00090 class Functor> 00091 void 00092 inspectTwoLines(SrcIterator1 s1, 00093 SrcIterator1 s1end, SrcAccessor1 src1, 00094 SrcIterator2 s2, SrcAccessor2 src2, 00095 Functor & f) 00096 { 00097 for(; s1 != s1end; ++s1, ++s2) 00098 f(src1(s1), src2(s2)); 00099 } 00100 00101 template <class SrcIterator1, class SrcAccessor1, 00102 class SrcIterator2, class SrcAccessor2, 00103 class MaskIterator, class MaskAccessor, 00104 class Functor> 00105 void 00106 inspectTwoLinesIf(SrcIterator1 s1, 00107 SrcIterator1 s1end, SrcAccessor1 src1, 00108 SrcIterator2 s2, SrcAccessor2 src2, 00109 MaskIterator m, MaskAccessor mask, 00110 Functor & f) 00111 { 00112 for(; s1 != s1end; ++s1, ++s2, ++m) 00113 if(mask(m)) 00114 f(src1(s1), src2(s2)); 00115 } 00116 00117 /********************************************************/ 00118 /* */ 00119 /* inspectImage */ 00120 /* */ 00121 /********************************************************/ 00122 00123 /** \brief Apply read-only functor to every pixel in the image. 00124 00125 This function can be used to collect statistics of the image etc. 00126 The results must be stored in the functor, which serves as a return 00127 value. 00128 The function uses an accessor to access the pixel data. 00129 00130 <b> Declarations:</b> 00131 00132 pass arguments explicitly: 00133 \code 00134 namespace vigra { 00135 template <class ImageIterator, class Accessor, class Functor> 00136 void 00137 inspectImage(ImageIterator upperleft, ImageIterator lowerright, 00138 Accessor a, Functor & f) 00139 } 00140 \endcode 00141 00142 use argument objects in conjunction with \ref ArgumentObjectFactories: 00143 \code 00144 namespace vigra { 00145 template <class ImageIterator, class Accessor, class Functor> 00146 void 00147 inspectImage(triple<ImageIterator, ImageIterator, Accessor> img, 00148 Functor & f) 00149 } 00150 \endcode 00151 00152 <b> Usage:</b> 00153 00154 <b>\#include</b> "<a href="inspectimage_8hxx-source.html">vigra/inspectimage.hxx</a>"<br> 00155 Namespace: vigra 00156 00157 \code 00158 // init functor 00159 vigra::BImage img; 00160 00161 vigra::FindMinMax<vigra::BImage::PixelType> minmax; 00162 00163 vigra::inspectImage(srcImageRange(img), minmax); 00164 00165 cout << "Min: " << minmax.min << " Max: " << minmax.max; 00166 00167 \endcode 00168 00169 <b> Required Interface:</b> 00170 00171 \code 00172 ConstImageIterator upperleft, lowerright; 00173 ConstImageIterator::row_iterator ix = upperleft.rowIterator(); 00174 00175 Accessor accessor; 00176 Functor functor; 00177 00178 functor(accessor(ix)); // return not used 00179 \endcode 00180 00181 */ 00182 template <class ImageIterator, class Accessor, class Functor> 00183 void 00184 inspectImage(ImageIterator upperleft, ImageIterator lowerright, 00185 Accessor a, Functor & f) 00186 { 00187 int w = lowerright.x - upperleft.x; 00188 00189 for(; upperleft.y<lowerright.y; ++upperleft.y) 00190 { 00191 inspectLine(upperleft.rowIterator(), 00192 upperleft.rowIterator() + w, a, f); 00193 } 00194 } 00195 00196 template <class ImageIterator, class Accessor, class Functor> 00197 inline 00198 void 00199 inspectImage(triple<ImageIterator, ImageIterator, Accessor> img, 00200 Functor & f) 00201 { 00202 inspectImage(img.first, img.second, img.third, f); 00203 } 00204 00205 namespace functor 00206 { 00207 template <class T> class UnaryAnalyser; 00208 } 00209 00210 template <class ImageIterator, class Accessor, class Functor> 00211 inline 00212 void 00213 inspectImage(ImageIterator upperleft, ImageIterator lowerright, 00214 Accessor a, functor::UnaryAnalyser<Functor> const & f) 00215 { 00216 inspectImage(upperleft, lowerright, a, 00217 const_cast<functor::UnaryAnalyser<Functor> &>(f)); 00218 } 00219 00220 template <class ImageIterator, class Accessor, class Functor> 00221 inline 00222 void 00223 inspectImage(triple<ImageIterator, ImageIterator, Accessor> img, 00224 functor::UnaryAnalyser<Functor> const & f) 00225 { 00226 inspectImage(img.first, img.second, img.third, 00227 const_cast<functor::UnaryAnalyser<Functor> &>(f)); 00228 } 00229 00230 /********************************************************/ 00231 /* */ 00232 /* inspectImageIf */ 00233 /* */ 00234 /********************************************************/ 00235 00236 /** \brief Apply read-only functor to every pixel in the ROI. 00237 00238 This function can be used to collect statistics of the roi etc. 00239 The functor is called whenever the return value of the mask's 00240 accessor is not zero. 00241 The results must be stored in the functor, which serves as a return 00242 value. 00243 Accessors are used to access the pixel and mask data. 00244 00245 <b> Declarations:</b> 00246 00247 pass arguments explicitly: 00248 \code 00249 namespace vigra { 00250 template <class ImageIterator, class Accessor, 00251 class MaskImageIterator, class MaskAccessor, class Functor> 00252 void 00253 inspectImageIf(ImageIterator upperleft, ImageIterator lowerright, 00254 MaskImageIterator mask_upperleft, MaskAccessor ma, 00255 Functor & f) 00256 } 00257 \endcode 00258 00259 00260 use argument objects in conjunction with \ref ArgumentObjectFactories: 00261 \code 00262 namespace vigra { 00263 template <class ImageIterator, class Accessor, 00264 class MaskImageIterator, class MaskAccessor, class Functor> 00265 void 00266 inspectImageIf(triple<ImageIterator, ImageIterator, Accessor> img, 00267 pair<MaskImageIterator, MaskAccessor> mask, 00268 Functor & f) 00269 } 00270 \endcode 00271 00272 <b> Usage:</b> 00273 00274 <b>\#include</b> "<a href="inspectimage_8hxx-source.html">vigra/inspectimage.hxx</a>"<br> 00275 Namespace: vigra 00276 00277 \code 00278 vigra::BImage img(100, 100); 00279 vigra::BImage mask(100, 100); 00280 00281 // init functor 00282 vigra::FindMinMax<vigra::BImage::PixelType> minmax(); 00283 00284 vigra::inspectImageIf(srcImageRange(img), 00285 maskImage(mask), minmax); 00286 00287 cout << "Min: " << minmax.min << " Max: " << minmax.max; 00288 00289 \endcode 00290 00291 <b> Required Interface:</b> 00292 00293 \code 00294 ConstImageIterator upperleft, lowerright; 00295 MaskImageIterator mask_upperleft; 00296 ConstImageIterator::row_iterator ix = upperleft.rowIterator(); 00297 MaskImageIterator::row_iterator mx = mask_upperleft.rowIterator(); 00298 00299 Accessor accessor; 00300 MaskAccessor mask_accessor; 00301 00302 Functor functor; 00303 00304 if(mask_accessor(mx)) functor(accessor(ix)); 00305 \endcode 00306 00307 */ 00308 template <class ImageIterator, class Accessor, 00309 class MaskImageIterator, class MaskAccessor, class Functor> 00310 void 00311 inspectImageIf(ImageIterator upperleft, 00312 ImageIterator lowerright, Accessor a, 00313 MaskImageIterator mask_upperleft, MaskAccessor ma, 00314 Functor & f) 00315 { 00316 int w = lowerright.x - upperleft.x; 00317 00318 for(; upperleft.y<lowerright.y; ++upperleft.y, ++mask_upperleft.y) 00319 { 00320 inspectLineIf(upperleft.rowIterator(), 00321 upperleft.rowIterator() + w, a, 00322 mask_upperleft.rowIterator(), ma, f); 00323 } 00324 } 00325 00326 template <class ImageIterator, class Accessor, 00327 class MaskImageIterator, class MaskAccessor, class Functor> 00328 inline 00329 void 00330 inspectImageIf(triple<ImageIterator, ImageIterator, Accessor> img, 00331 pair<MaskImageIterator, MaskAccessor> mask, 00332 Functor & f) 00333 { 00334 inspectImageIf(img.first, img.second, img.third, 00335 mask.first, mask.second, f); 00336 } 00337 00338 /********************************************************/ 00339 /* */ 00340 /* inspectTwoImages */ 00341 /* */ 00342 /********************************************************/ 00343 00344 /** \brief Apply read-only functor to every pixel of both images. 00345 00346 This function can be used to collect statistics for each region of a 00347 labeled image, especially in conjunction with 00348 the \ref ArrayOfRegionStatistics functor. The results must be 00349 stored in the functor which serves as a return value. 00350 Accessors are used to access the pixel data. 00351 00352 <b> Declarations:</b> 00353 00354 pass arguments explicitly: 00355 \code 00356 namespace vigra { 00357 template <class ImageIterator1, class Accessor1, 00358 class ImageIterator2, class Accessor2, 00359 class Functor> 00360 void 00361 inspectTwoImages(ImageIterator1 upperleft1, ImageIterator1 lowerright1, Accessor1 a1, 00362 ImageIterator2 upperleft2, Accessor2 a2, 00363 Functor & f) 00364 } 00365 \endcode 00366 00367 00368 use argument objects in conjunction with \ref ArgumentObjectFactories: 00369 \code 00370 namespace vigra { 00371 template <class ImageIterator1, class Accessor1, 00372 class ImageIterator2, class Accessor2, 00373 class Functor> 00374 void 00375 inspectTwoImages(triple<ImageIterator1, ImageIterator1, Accessor1> img1, 00376 pair<ImageIterator2, Accessor2> img2, 00377 Functor & f) 00378 } 00379 \endcode 00380 00381 <b> Usage:</b> 00382 00383 <b>\#include</b> "<a href="inspectimage_8hxx-source.html">vigra/inspectimage.hxx</a>"<br> 00384 Namespace: vigra 00385 00386 \code 00387 vigra::BImage image1; 00388 vigra::BImage image2; 00389 00390 SomeStatisticsFunctor stats(...); // init functor 00391 00392 vigra::inspectTwoImages(srcImageRange(image1), srcImage(image2), 00393 stats); 00394 00395 00396 \endcode 00397 00398 <b> Required Interface:</b> 00399 00400 \code 00401 ImageIterator1 upperleft1, lowerright1; 00402 ImageIterator2 upperleft2; 00403 ImageIterator1::row_iterator ix1 = upperleft1.rowIterator(); 00404 ImageIterator2::row_iterator ix2 = upperleft2.rowIterator(); 00405 00406 Accessor1 accessor1; 00407 Accessor2 accessor2; 00408 00409 Functor functor; 00410 functor(accessor1(ix1), accessor2(ix2)); // return not used 00411 \endcode 00412 00413 */ 00414 template <class ImageIterator1, class Accessor1, 00415 class ImageIterator2, class Accessor2, 00416 class Functor> 00417 void 00418 inspectTwoImages(ImageIterator1 upperleft1, ImageIterator1 lowerright1, Accessor1 a1, 00419 ImageIterator2 upperleft2, Accessor2 a2, 00420 Functor & f) 00421 { 00422 int w = lowerright1.x - upperleft1.x; 00423 00424 for(; upperleft1.y<lowerright1.y; ++upperleft1.y, ++upperleft2.y) 00425 { 00426 inspectTwoLines(upperleft1.rowIterator(), 00427 upperleft1.rowIterator() + w, a1, 00428 upperleft2.rowIterator(), a2, f); 00429 } 00430 } 00431 00432 template <class ImageIterator1, class Accessor1, 00433 class ImageIterator2, class Accessor2, 00434 class Functor> 00435 inline 00436 void 00437 inspectTwoImages(triple<ImageIterator1, ImageIterator1, Accessor1> img1, 00438 pair<ImageIterator2, Accessor2> img2, 00439 Functor & f) 00440 { 00441 inspectTwoImages(img1.first, img1.second, img1.third, 00442 img2.first, img2.second, f); 00443 } 00444 00445 /********************************************************/ 00446 /* */ 00447 /* inspectTwoImagesIf */ 00448 /* */ 00449 /********************************************************/ 00450 00451 /** \brief Apply read-only functor to those pixels of both images where 00452 the mask image is non-zero. 00453 00454 This function can be used to collect statistics for selected regions of a 00455 labeled image, especially in conjunction with 00456 the \ref ArrayOfRegionStatistics functor. The results must be 00457 stored in the functor which serves as a return value. 00458 Accessors are used to access the pixel data. 00459 00460 <b> Declarations:</b> 00461 00462 pass arguments explicitly: 00463 \code 00464 namespace vigra { 00465 template <class ImageIterator1, class Accessor1, 00466 class ImageIterator2, class Accessor2, 00467 class MaskImageIterator, class MaskAccessor, 00468 class Functor> 00469 void 00470 inspectTwoImagesIf(ImageIterator1 upperleft1, ImageIterator1 lowerright1, Accessor1 a1, 00471 ImageIterator2 upperleft2, Accessor2 a2, 00472 MaskImageIterator mupperleft, MaskAccessor mask, 00473 Functor & f) 00474 } 00475 \endcode 00476 00477 00478 use argument objects in conjunction with \ref ArgumentObjectFactories: 00479 \code 00480 namespace vigra { 00481 template <class ImageIterator1, class Accessor1, 00482 class ImageIterator2, class Accessor2, 00483 class MaskImageIterator, class MaskAccessor, 00484 class Functor> 00485 void 00486 inspectTwoImagesIf(triple<ImageIterator1, ImageIterator1, Accessor1> img1, 00487 pair<ImageIterator2, Accessor2> img2, 00488 pair<MaskImageIterator, MaskAccessor> mimg, 00489 Functor & f) 00490 } 00491 \endcode 00492 00493 <b> Usage:</b> 00494 00495 <b>\#include</b> "<a href="inspectimage_8hxx-source.html">vigra/inspectimage.hxx</a>"<br> 00496 Namespace: vigra 00497 00498 \code 00499 vigra::BImage image1; 00500 vigra::BImage image2; 00501 vigra::BImage maskimage; 00502 00503 SomeStatisticsFunctor stats(...); // init functor 00504 00505 vigra::inspectTwoImagesIf(srcImageRange(image1), srcImage(image2), 00506 srcImage(maskimage), region_stats); 00507 00508 \endcode 00509 00510 <b> Required Interface:</b> 00511 00512 \code 00513 ImageIterator1 upperleft1, lowerright1; 00514 ImageIterator2 upperleft2; 00515 MaskImageIterator upperleftm; 00516 ImageIterator1::row_iterator ix1 = upperleft1.rowIterator(); 00517 ImageIterator2::row_iterator ix2 = upperleft2.rowIterator(); 00518 MaskImageIterator::row_iterator mx = mupperleft.rowIterator(); 00519 00520 Accessor1 accessor1; 00521 Accessor2 accessor2; 00522 MaskAccessor mask; 00523 00524 Functor functor; 00525 if(mask(mx)) 00526 functor(accessor1(ix1), accessor2(ix2)); 00527 \endcode 00528 00529 */ 00530 template <class ImageIterator1, class Accessor1, 00531 class ImageIterator2, class Accessor2, 00532 class MaskImageIterator, class MaskAccessor, 00533 class Functor> 00534 void 00535 inspectTwoImagesIf(ImageIterator1 upperleft1, ImageIterator1 lowerright1, Accessor1 a1, 00536 ImageIterator2 upperleft2, Accessor2 a2, 00537 MaskImageIterator mupperleft, MaskAccessor mask, 00538 Functor & f) 00539 { 00540 int w = lowerright1.x - upperleft1.x; 00541 00542 for(; upperleft1.y<lowerright1.y; ++upperleft1.y, ++upperleft2.y, ++mupperleft.y) 00543 { 00544 inspectTwoLinesIf(upperleft1.rowIterator(), 00545 upperleft1.rowIterator() + w, a1, 00546 upperleft2.rowIterator(), a2, 00547 mupperleft.rowIterator(), mask, f); 00548 } 00549 } 00550 00551 template <class ImageIterator1, class Accessor1, 00552 class ImageIterator2, class Accessor2, 00553 class MaskImageIterator, class MaskAccessor, 00554 class Functor> 00555 inline 00556 void 00557 inspectTwoImagesIf(triple<ImageIterator1, ImageIterator1, Accessor1> img1, 00558 pair<ImageIterator2, Accessor2> img2, 00559 pair<MaskImageIterator, MaskAccessor> m, 00560 Functor & f) 00561 { 00562 inspectTwoImagesIf(img1.first, img1.second, img1.third, 00563 img2.first, img2.second, 00564 m.first, m.second, 00565 f); 00566 } 00567 00568 //@} 00569 00570 /** \addtogroup InspectFunctor Functors To Inspect Images 00571 Functors which report image statistics 00572 */ 00573 //@{ 00574 00575 /********************************************************/ 00576 /* */ 00577 /* FindMinMax */ 00578 /* */ 00579 /********************************************************/ 00580 00581 /** \brief Find the minimum and maximum pixel value in an image or ROI. 00582 00583 In addition the size of the ROI is calculated. 00584 These functors can also be used in conjunction with 00585 \ref ArrayOfRegionStatistics to find the extremes of all regions in 00586 a labeled image. 00587 00588 <b> Traits defined:</b> 00589 00590 <tt>FunctorTraits::isUnaryAnalyser</tt> is true (<tt>VigraTrueType<tt>) 00591 00592 <b> Usage:</b> 00593 00594 <b>\#include</b> "<a href="inspectimage_8hxx-source.html">vigra/inspectimage.hxx</a>"<br> 00595 Namespace: vigra 00596 00597 \code 00598 vigra::BImage img; 00599 00600 vigra::FindMinMax<vigra::BImage::PixelType> minmax; // init functor 00601 00602 vigra::inspectImage(srcImageRange(img), minmax); 00603 00604 cout << "Min: " << minmax.min << " Max: " << minmax.max; 00605 00606 \endcode 00607 00608 <b> Required Interface:</b> 00609 00610 \code 00611 VALUETYPE v1, v2(v1); 00612 00613 v1 < v2; 00614 v1 = v2; 00615 \endcode 00616 00617 */ 00618 template <class VALUETYPE> 00619 class FindMinMax 00620 { 00621 public: 00622 00623 /** the functor's argument type 00624 */ 00625 typedef VALUETYPE argument_type; 00626 00627 /** the functor's result type 00628 */ 00629 typedef VALUETYPE result_type; 00630 00631 /** \deprecated use argument_type 00632 */ 00633 typedef VALUETYPE value_type; 00634 00635 /** init min and max 00636 */ 00637 FindMinMax() 00638 : count(0) 00639 {} 00640 00641 /** (re-)init functor (clear min, max) 00642 */ 00643 void reset() 00644 { 00645 count = 0; 00646 } 00647 00648 /** update min and max 00649 */ 00650 void operator()(argument_type const & v) 00651 { 00652 if(count) 00653 { 00654 if(v < min) min = v; 00655 if(max < v) max = v; 00656 } 00657 else 00658 { 00659 min = v; 00660 max = v; 00661 } 00662 ++count; 00663 } 00664 00665 /** update min and max with components of RGBValue<VALUETYPE> 00666 */ 00667 void operator()(RGBValue<VALUETYPE> const & v) 00668 { 00669 operator()(v.red()); 00670 operator()(v.green()); 00671 operator()(v.blue()); 00672 } 00673 00674 /** merge two statistics 00675 */ 00676 void operator()(FindMinMax const & v) 00677 { 00678 if(v.count) 00679 { 00680 if(count) 00681 { 00682 if(v.min < min) min = v.min; 00683 if((this->max) < v.max) max = v.max; 00684 } 00685 else 00686 { 00687 min = v.min; 00688 max = v.max; 00689 } 00690 } 00691 count += v.count; 00692 } 00693 00694 /** the current min 00695 */ 00696 VALUETYPE min; 00697 00698 /** the current max 00699 */ 00700 VALUETYPE max; 00701 00702 /** the number of values processed so far 00703 */ 00704 unsigned int count; 00705 00706 }; 00707 00708 template <class VALUETYPE> 00709 class FunctorTraits<FindMinMax<VALUETYPE> > 00710 : public FunctorTraitsBase<FindMinMax<VALUETYPE> > 00711 { 00712 public: 00713 typedef VigraTrueType isUnaryAnalyser; 00714 }; 00715 00716 /********************************************************/ 00717 /* */ 00718 /* FindAverage */ 00719 /* */ 00720 /********************************************************/ 00721 00722 /** \brief Find the average pixel value in an image or ROI. 00723 00724 In addition the size of the ROI is calculated. 00725 This Functor can also be used in conjunction with 00726 \ref ArrayOfRegionStatistics to find the average of all regions in 00727 a labeled image. 00728 00729 <b> Traits defined:</b> 00730 00731 <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitializer</tt> 00732 are true (<tt>VigraTrueType<tt>) 00733 00734 <b> Usage:</b> 00735 00736 <b>\#include</b> "<a href="inspectimage_8hxx-source.html">vigra/inspectimage.hxx</a>"<br> 00737 Namespace: vigra 00738 00739 \code 00740 vigra::BImage img; 00741 00742 vigra::FindAverage<vigra::BImage::PixelType> average; // init functor 00743 00744 vigra::inspectImage(srcImageRange(img), average); 00745 00746 cout << "Average: " << average(); 00747 00748 \endcode 00749 00750 <b> Required Interface:</b> 00751 00752 \code 00753 VALUETYPE v1, v2(v1); 00754 00755 v1 < v2; 00756 v1 = v2; 00757 \endcode 00758 00759 */ 00760 template <class VALUETYPE> 00761 class FindAverage 00762 { 00763 public: 00764 00765 /** the functor's argument type 00766 */ 00767 typedef VALUETYPE argument_type; 00768 00769 /** the functor's result type 00770 */ 00771 typedef typename NumericTraits<VALUETYPE>::RealPromote result_type; 00772 00773 /** \deprecated use argument_type and result_type 00774 */ 00775 typedef typename NumericTraits<VALUETYPE>::RealPromote value_type; 00776 00777 /** init average 00778 */ 00779 FindAverage() 00780 : count(0), sum(NumericTraits<result_type>::zero()) 00781 {} 00782 00783 /** (re-)init average 00784 */ 00785 void reset() 00786 { 00787 count = 0; 00788 sum = NumericTraits<result_type>::zero(); 00789 } 00790 00791 /** update average 00792 */ 00793 void operator()(argument_type const & v) 00794 { 00795 sum += v; 00796 ++count; 00797 } 00798 00799 /** merge two statistics 00800 */ 00801 void operator()(FindAverage const & v) 00802 { 00803 sum += v.sum; 00804 count += v.count; 00805 } 00806 00807 /** return current average 00808 */ 00809 result_type average() const 00810 { 00811 return sum / (double)count; 00812 } 00813 00814 /** return current average 00815 */ 00816 result_type operator()() const 00817 { 00818 return sum / (double)count; 00819 } 00820 00821 unsigned int count; 00822 result_type sum; 00823 00824 }; 00825 00826 template <class VALUETYPE> 00827 class FunctorTraits<FindAverage<VALUETYPE> > 00828 : public FunctorTraitsBase<FindAverage<VALUETYPE> > 00829 { 00830 public: 00831 typedef VigraTrueType isInitializer; 00832 typedef VigraTrueType isUnaryAnalyser; 00833 }; 00834 00835 /********************************************************/ 00836 /* */ 00837 /* FindROISize */ 00838 /* */ 00839 /********************************************************/ 00840 00841 /** \brief Calculate the size of an ROI in an image. 00842 00843 This Functor is often used in conjunction with 00844 \ref ArrayOfRegionStatistics to find the sizes of all regions in 00845 a labeled image. 00846 00847 <b> Traits defined:</b> 00848 00849 <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitializer</tt> 00850 are true (<tt>VigraTrueType<tt>) 00851 00852 <b> Usage:</b> 00853 00854 <b>\#include</b> "<a href="inspectimage_8hxx-source.html">vigra/inspectimage.hxx</a>"<br> 00855 Namespace: vigra 00856 00857 \code 00858 vigra::BImage img, mask; 00859 00860 vigra::FindROISize<vigra::BImage::PixelType> roisize; // init functor 00861 00862 vigra::inspectImageIf(srcImageRange(img), srcImage(mask), roisize); 00863 00864 cout << "Size of ROI: " << roisize.count; 00865 00866 \endcode 00867 00868 */ 00869 template <class VALUETYPE> 00870 class FindROISize 00871 { 00872 public: 00873 00874 /** the functor's argument type 00875 */ 00876 typedef VALUETYPE argument_type; 00877 00878 /** the functor's result type 00879 */ 00880 typedef unsigned int result_type; 00881 00882 /** \deprecated use argument_type and result_type 00883 */ 00884 typedef VALUETYPE value_type; 00885 00886 /** init counter to 0 00887 */ 00888 FindROISize() 00889 : count(0) 00890 {} 00891 00892 /** (re-)init ROI size with 0 00893 */ 00894 void reset() 00895 { 00896 count = 0; 00897 } 00898 00899 /** update counter 00900 */ 00901 void operator()(argument_type const &) 00902 { 00903 ++count; 00904 } 00905 00906 /** return current size 00907 */ 00908 result_type operator()() const 00909 { 00910 return count; 00911 } 00912 00913 /** return current size 00914 */ 00915 result_type size() const 00916 { 00917 return count; 00918 } 00919 00920 /** merge two statistics 00921 */ 00922 void operator()(FindROISize const & o) 00923 { 00924 count += o.count; 00925 } 00926 00927 /** the current counter 00928 */ 00929 result_type count; 00930 00931 }; 00932 00933 template <class VALUETYPE> 00934 class FunctorTraits<FindROISize<VALUETYPE> > 00935 : public FunctorTraitsBase<FindROISize<VALUETYPE> > 00936 { 00937 public: 00938 typedef VigraTrueType isInitializer; 00939 typedef VigraTrueType isUnaryAnalyser; 00940 }; 00941 00942 /********************************************************/ 00943 /* */ 00944 /* FindBoundingRectangle */ 00945 /* */ 00946 /********************************************************/ 00947 00948 /** \brief Calculate the bounding rectangle of an ROI in an image. 00949 00950 As always in VIGRA, <TT>roiRect.lowerRight</TT> is <em> just outside the rectangle</em>. 00951 That is, the last pixel actually in the rectangle is <TT>roiRect.lowerRight - Diff2D(1,1)</TT>. 00952 This Functor is often used in conjunction with 00953 \ref ArrayOfRegionStatistics to find the bounding rectangles 00954 of all regions in a labeled image. 00955 00956 <b> Traits defined:</b> 00957 00958 <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitializer</tt> 00959 are true (<tt>VigraTrueType<tt>) 00960 00961 <b> Usage:</b> 00962 00963 <b>\#include</b> "<a href="inspectimage_8hxx-source.html">vigra/inspectimage.hxx</a>"<br> 00964 Namespace: vigra 00965 00966 \code 00967 vigra::BImage img, mask; 00968 ... 00969 00970 vigra::FindBoundingRectangle roiRect; // init functor 00971 00972 // Diff2D is used as the iterator for the source image. This 00973 // simulates an image where each pixel value equals that pixel's 00974 // coordinates. Tha image 'mask' determines the ROI. 00975 vigra::inspectImageIf(srcIterRange(Diff2D(0,0), img.size()), 00976 srcImage(mask), roiRect); 00977 00978 cout << "Upper left of ROI: " << 00979 roiRect.upperLeft.x << ", " << roiRect.upperLeft.y << endl; 00980 cout << "Lower right of ROI: " << 00981 roiRect.lowerRight.x << ", " << roiRect.lowerRight.y << endl; 00982 00983 \endcode 00984 00985 */ 00986 class FindBoundingRectangle 00987 { 00988 public: 00989 00990 /** the functor's argument type 00991 */ 00992 typedef Diff2D argument_type; 00993 00994 /** the functors result type 00995 */ 00996 typedef Rect2D result_type; 00997 00998 /** \deprecated use argument_type 00999 */ 01000 typedef Diff2D value_type; 01001 01002 /** Upper left of the region as seen so far 01003 */ 01004 Point2D upperLeft; 01005 01006 /** Lower right of the region as seen so far 01007 */ 01008 Point2D lowerRight; 01009 01010 /** are the functors contents valid ? 01011 */ 01012 bool valid; 01013 01014 /** init rectangle to invalid values 01015 */ 01016 FindBoundingRectangle() 01017 : valid(false) 01018 {} 01019 01020 /** (re-)init functor to find other bounds 01021 */ 01022 void reset() 01023 { 01024 valid = false; 01025 } 01026 01027 /** update rectangle by including the coordinate coord 01028 */ 01029 void operator()(argument_type const & coord) 01030 { 01031 if(!valid) 01032 { 01033 upperLeft = Point2D(coord); 01034 lowerRight = Point2D(coord + Diff2D(1,1)); 01035 valid = true; 01036 } 01037 else 01038 { 01039 upperLeft.x = std::min(upperLeft.x, coord.x); 01040 upperLeft.y = std::min(upperLeft.y, coord.y); 01041 lowerRight.x = std::max(lowerRight.x, coord.x + 1); 01042 lowerRight.y = std::max(lowerRight.y, coord.y + 1); 01043 } 01044 } 01045 01046 /** update rectangle by merging it with another rectangle 01047 */ 01048 void operator()(FindBoundingRectangle const & otherRegion) 01049 { 01050 if(!valid) 01051 { 01052 upperLeft = otherRegion.upperLeft; 01053 lowerRight = otherRegion.lowerRight; 01054 valid = otherRegion.valid; 01055 } 01056 else if(otherRegion.valid) 01057 { 01058 upperLeft.x = std::min(upperLeft.x, otherRegion.upperLeft.x); 01059 upperLeft.y = std::min(upperLeft.y, otherRegion.upperLeft.y); 01060 lowerRight.x = std::max(lowerRight.x, otherRegion.lowerRight.x); 01061 lowerRight.y = std::max(lowerRight.y, otherRegion.lowerRight.y); 01062 } 01063 } 01064 01065 /** Get size of current rectangle. 01066 */ 01067 Size2D size() const 01068 { 01069 return lowerRight - upperLeft; 01070 } 01071 01072 /** Get current rectangle. <TT>result_type::first</TT> is the upper 01073 left corner of the rectangle, <TT>result_type::second</TT> 01074 the lower right. 01075 */ 01076 result_type operator()() const 01077 { 01078 return result_type(upperLeft, lowerRight); 01079 } 01080 }; 01081 01082 template <> 01083 class FunctorTraits<FindBoundingRectangle> 01084 : public FunctorTraitsBase<FindBoundingRectangle> 01085 { 01086 public: 01087 typedef VigraTrueType isInitializer; 01088 typedef VigraTrueType isUnaryAnalyser; 01089 }; 01090 01091 /********************************************************/ 01092 /* */ 01093 /* LastValueFunctor */ 01094 /* */ 01095 /********************************************************/ 01096 01097 /** \brief Stores and returns the last value it has seen. 01098 01099 This Functor is best used in conjunction with 01100 \ref ArrayOfRegionStatistics to realize a look-up table. 01101 01102 <b> Traits defined:</b> 01103 01104 <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitializer</tt> 01105 are true (<tt>VigraTrueType<tt>) 01106 01107 <b> Usage:</b> 01108 01109 <b>\#include</b> "<a href="inspectimage_8hxx-source.html">vigra/inspectimage.hxx</a>"<br> 01110 Namespace: vigra 01111 01112 \code 01113 vigra::BImage img; 01114 01115 vigra::ArrayOfRegionStatistics<LastValueFunctor<unsigned char> > lut(255); 01116 01117 for(int i=0; i<256; ++i) 01118 { 01119 lut[i] = ...; // init look-up table 01120 } 01121 01122 vigra::transformImage(srcImageRange(img), destImage(img), lut); 01123 01124 \endcode 01125 01126 */ 01127 template <class VALUETYPE> 01128 class LastValueFunctor 01129 { 01130 public: 01131 01132 /** the functor's argument type 01133 */ 01134 typedef VALUETYPE argument_type; 01135 01136 /** the functor's result type 01137 */ 01138 typedef VALUETYPE result_type; 01139 01140 /** \deprecated use argument_type and result_type 01141 */ 01142 typedef VALUETYPE value_type; 01143 01144 /** default initialization of value 01145 */ 01146 LastValueFunctor() 01147 {} 01148 01149 /** replace value 01150 */ 01151 void operator=(argument_type const & v) { value = v; } 01152 01153 /** reset to initia÷ value 01154 */ 01155 void reset() { value = VALUETYPE(); } 01156 01157 /** replace value 01158 */ 01159 void operator()(argument_type const & v) { value = v; } 01160 01161 /** return current value 01162 */ 01163 result_type const & operator()() const { return value; } 01164 01165 /** the current value 01166 */ 01167 VALUETYPE value; 01168 01169 }; 01170 01171 template <class VALUETYPE> 01172 class FunctorTraits<LastValueFunctor<VALUETYPE> > 01173 : public FunctorTraitsBase<LastValueFunctor<VALUETYPE> > 01174 { 01175 public: 01176 typedef VigraTrueType isInitializer; 01177 typedef VigraTrueType isUnaryAnalyser; 01178 }; 01179 01180 /********************************************************/ 01181 /* */ 01182 /* ReduceFunctor */ 01183 /* */ 01184 /********************************************************/ 01185 01186 /** \brief Apply a functor to reduce the dimensionality of an array. 01187 01188 This functor can be used to emulate the <tt>reduce</tt> standard function of 01189 functional programming using <tt>std::for_each()</tt> or <tt>inspectImage()</tt> 01190 and similar functions. This functor is initialized with a functor encoding 01191 the expression to be applied, and an accumulator storing the current state 01192 of the reduction. For each element of the array, the embedded functor is called 01193 with the accumulator and the current element(s) of the array. The result 01194 of the reduction is available by calling <tt>reduceFunctor()</tt>. 01195 01196 <b> Traits defined:</b> 01197 01198 <tt>FunctorTraits::isUnaryAnalyser</tt>, <tt>FunctorTraits::isBinaryAnalyser</tt> 01199 and <tt>FunctorTraits::isInitializer</tt> 01200 are true (<tt>VigraTrueType<tt>) 01201 01202 <b> Usage:</b> 01203 01204 <b>\#include</b> "<a href="inspectimage_8hxx-source.html">vigra/inspectimage.hxx</a>"<br> 01205 Namespace: vigra 01206 01207 \code 01208 vigra::BImage img; 01209 ... // fill the image 01210 01211 // create a functor to sum the elements of the image 01212 vigra::ReduceFunctor<std::plus<int>, int> sumElements(std::plus<int>, 0); 01213 01214 vigra::inspectImage(srcImageRange(img), sumElements); 01215 01216 cout << "The sum of the elements " << sumElements() << endl; 01217 01218 \endcode 01219 01220 <b> Required Interface:</b> 01221 01222 \code 01223 FUNCTOR f; 01224 VALUETYPE accumulator, current1, current2; 01225 01226 f(accumulator, current1); // for inspectImage() 01227 f(accumulator, current1, current2); // for inspectTwoImages() 01228 \endcode 01229 */ 01230 template <class FUNCTOR, class VALUETYPE> 01231 class ReduceFunctor 01232 { 01233 FUNCTOR f_; 01234 VALUETYPE start_, accumulator_; 01235 public: 01236 01237 /** the functor's argument type 01238 when used as a unary inspector. 01239 (This is not strictly correct since the argument type 01240 is actuall a template parameter.) 01241 */ 01242 typedef VALUETYPE argument_type; 01243 01244 /** the functor's first argument type 01245 when used as a binary inspector. 01246 (This is not strictly correct since the argument type 01247 is actuall a template parameter.) 01248 */ 01249 typedef VALUETYPE first_argument_type; 01250 01251 /** the functor's second argument type 01252 when used as a binary inspector. 01253 (This is not strictly correct since the argument type 01254 is actuall a template parameter.) 01255 */ 01256 typedef VALUETYPE second_argument_type; 01257 01258 /** the functor's result type 01259 */ 01260 typedef VALUETYPE result_type; 01261 01262 /** create with the given functor and initial value \a initial 01263 for the accumulator. 01264 */ 01265 ReduceFunctor(FUNCTOR const & f, VALUETYPE const & initial) 01266 : f_(f), 01267 start_(initial), 01268 accumulator_(initial) 01269 {} 01270 01271 /** Reset accumulator to the initial value. 01272 */ 01273 void reset() 01274 { accumulator_ = start_; } 01275 01276 /** Use binary functor to connect given value with the accumulator. 01277 The accumulator is used as the first argument, the value \a v 01278 as the second. 01279 */ 01280 template <class T> 01281 void operator()(T const & v) 01282 { 01283 accumulator_ = f_(accumulator_, v); 01284 } 01285 01286 /** Use ternary functor to connect given values with accumulator. 01287 The accumulator is used as the first argument, the values \a v1 01288 ans \a v2 as the second and third. 01289 */ 01290 template <class T1, class T2> 01291 void operator()(T1 const & v1, T2 const & v2) 01292 { 01293 accumulator_ = f_(accumulator_, v1, v2); 01294 } 01295 01296 /** return current value 01297 */ 01298 result_type const & operator()() const 01299 { return accumulator_; } 01300 }; 01301 01302 template <class FUNCTOR, class VALUETYPE> 01303 ReduceFunctor<FUNCTOR, VALUETYPE> 01304 reduceFunctor(FUNCTOR const & f, VALUETYPE const & initial) 01305 { 01306 return ReduceFunctor<FUNCTOR, VALUETYPE>(f, initial); 01307 } 01308 01309 template <class FUNCTOR, class VALUETYPE> 01310 class FunctorTraits<ReduceFunctor<FUNCTOR, VALUETYPE> > 01311 : public FunctorTraitsBase<ReduceFunctor<FUNCTOR, VALUETYPE> > 01312 { 01313 public: 01314 typedef VigraTrueType isInitializer; 01315 typedef VigraTrueType isUnaryAnalyser; 01316 typedef VigraTrueType isBinaryAnalyser; 01317 }; 01318 01319 /********************************************************/ 01320 /* */ 01321 /* ArrayOfRegionStatistics */ 01322 /* */ 01323 /********************************************************/ 01324 01325 /** \brief Calculate statistics for all regions of a labeled image. 01326 01327 This Functor encapsulates an array of statistics functors, one 01328 for each label, and selects the one to be updated according to the 01329 pixel's label. 01330 01331 <b> Traits defined:</b> 01332 01333 <tt>FunctorTraits::isBinaryAnalyser</tt> and <tt>FunctorTraits::isUnaryFunctor</tt> 01334 are true (<tt>VigraTrueType<tt>) 01335 01336 <b> Usage:</b> 01337 01338 <b>\#include</b> "<a href="inspectimage_8hxx-source.html">vigra/inspectimage.hxx</a>"<br> 01339 Namespace: vigra 01340 01341 \code 01342 vigra::BImage img; 01343 vigra::IImage labels; 01344 int max_label; 01345 ... 01346 01347 // init functor as an array of 'max_label' FindMinMax-Functors 01348 vigra::ArrayOfRegionStatistics<vigra::FindMinMax<vigra::BImage::PixelType> > 01349 minmax(max_label); 01350 01351 vigra::inspectTwoImages(srcImageRange(img), srcImage(labels), minmax); 01352 01353 for(int i=0; i<= max_label; ++i) 01354 { 01355 cout << "Max gray lavel of region " << i << ": " 01356 << minmax.region[i].max << endl; 01357 } 01358 01359 // init functor as an array of 'max_label' FindAverage-Functors 01360 vigra::ArrayOfRegionStatistics<vigra::FindAverage<vigra::BImage::PixelType> > 01361 average(max_label); 01362 01363 vigra::inspectTwoImages(srcImageRange(img), srcImage(labels), average); 01364 01365 // write back the average of each region into the original image 01366 vigra::transformImage(srcImageRange(labels), destImage(img), average); 01367 01368 \endcode 01369 01370 <b> Required Interface:</b> 01371 01372 \code 01373 RegionStatistics region; 01374 RegionStatistics::argument_type a; 01375 RegionStatistics::result_type r; 01376 01377 region(a); // update statistics 01378 r = region(); // return statistics 01379 01380 \endcode 01381 */ 01382 template <class RegionStatistics, class LabelType = int> 01383 class ArrayOfRegionStatistics 01384 { 01385 typedef std::vector<RegionStatistics> RegionArray; 01386 01387 public: 01388 /** argument type of the contained statistics object 01389 becomes first argument of the analyser 01390 */ 01391 typedef typename RegionStatistics::argument_type first_argument_type; 01392 01393 /** label type is used to determine the region to be updated 01394 */ 01395 typedef LabelType second_argument_type; 01396 01397 /** label type is also used to determine the region to be 01398 returned by the 1 argument operator() 01399 */ 01400 typedef LabelType argument_type; 01401 01402 /** result type of the contained statistics object 01403 becomes result type of the analyser 01404 */ 01405 typedef typename RegionStatistics::result_type result_type; 01406 01407 /** the value type of the array: the contained statistics object. 01408 <b>Note:</b> this definition was different in older 01409 VIGRA versions. The old definition was wrong. 01410 */ 01411 typedef RegionStatistics value_type; 01412 01413 /** the array's reference type 01414 */ 01415 typedef RegionStatistics & reference; 01416 01417 /** the array's const reference type 01418 */ 01419 typedef RegionStatistics const & const_reference; 01420 01421 /** type to iterate over the statistics array 01422 */ 01423 typedef typename RegionArray::iterator iterator; 01424 01425 /** type to iterate over a const statistics array 01426 */ 01427 typedef typename RegionArray::const_iterator const_iterator; 01428 01429 /** init array of RegionStatistics with default size 0. 01430 */ 01431 ArrayOfRegionStatistics() 01432 {} 01433 01434 /** init array of RegionStatistics with index domain 01435 0...max_region_label. 01436 */ 01437 ArrayOfRegionStatistics(unsigned int max_region_label) 01438 : regions(max_region_label+1) 01439 {} 01440 01441 /** resize array to new index domain 0...max_region_label. 01442 All bin are re-initialized. 01443 */ 01444 void resize(unsigned int max_region_label) 01445 { 01446 RegionArray newRegions(max_region_label+1); 01447 regions.swap(newRegions); 01448 } 01449 01450 /** reset the contained functors to their initial state. 01451 */ 01452 void reset() 01453 { 01454 RegionArray newRegions(regions.size()); 01455 regions.swap(newRegions); 01456 } 01457 01458 /** update regions statistics for region <TT>label</TT>. The label type 01459 is converted to <TT>unsigned int</TT>. 01460 */ 01461 void operator()(first_argument_type const & v, second_argument_type label) { 01462 regions[static_cast<unsigned int>(label)](v); 01463 } 01464 01465 /** merge second region into first 01466 */ 01467 void merge(argument_type label1, argument_type label2) { 01468 regions[static_cast<unsigned int>(label1)](regions[static_cast<unsigned int>(label2)]); 01469 } 01470 01471 /** ask for maximal index (label) allowed 01472 */ 01473 unsigned int maxRegionLabel() const 01474 { return size() - 1; } 01475 01476 /** ask for array size (i.e. maxRegionLabel() + 1) 01477 */ 01478 unsigned int size() const 01479 { return regions.size(); } 01480 01481 /** access the statistics for a region via its label. The label type 01482 is converted to <TT>unsigned int</TT>. 01483 */ 01484 result_type operator()(argument_type label) const 01485 { return regions[static_cast<unsigned int>(label)](); } 01486 01487 /** read the statistics functor for a region via its label 01488 */ 01489 const_reference operator[](argument_type label) const 01490 { return regions[static_cast<unsigned int>(label)]; } 01491 01492 /** access the statistics functor for a region via its label 01493 */ 01494 reference operator[](argument_type label) 01495 { return regions[static_cast<unsigned int>(label)]; } 01496 01497 /** iterator to the begin of the region array 01498 */ 01499 iterator begin() 01500 { return regions.begin(); } 01501 01502 /** const iterator to the begin of the region array 01503 */ 01504 const_iterator begin() const 01505 { return regions.begin(); } 01506 01507 /** iterator to the end of the region array 01508 */ 01509 iterator end() 01510 { return regions.end(); } 01511 01512 /** const iterator to the end of the region array 01513 */ 01514 const_iterator end() const 01515 { return regions.end(); } 01516 01517 private: 01518 std::vector<RegionStatistics> regions; 01519 }; 01520 01521 template <class RegionStatistics, class LabelType> 01522 class FunctorTraits<ArrayOfRegionStatistics<RegionStatistics, LabelType> > 01523 : public FunctorTraitsBase<ArrayOfRegionStatistics<RegionStatistics, LabelType> > 01524 { 01525 public: 01526 typedef VigraTrueType isUnaryFunctor; 01527 typedef VigraTrueType isBinaryAnalyser; 01528 }; 01529 01530 //@} 01531 01532 } // namespace vigra 01533 01534 #endif // VIGRA_INSPECTIMAGE_HXX
© Ullrich Köthe (koethe@informatik.uni-hamburg.de) |
html generated using doxygen and Python
|