[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]
vigra/inspectimage.hxx | ![]() |
00001 /************************************************************************/ 00002 /* */ 00003 /* Copyright 1998-2002 by Ullrich Koethe */ 00004 /* */ 00005 /* This file is part of the VIGRA computer vision library. */ 00006 /* The VIGRA Website is */ 00007 /* http://hci.iwr.uni-heidelberg.de/vigra/ */ 00008 /* Please direct questions, bug reports, and contributions to */ 00009 /* ullrich.koethe@iwr.uni-heidelberg.de or */ 00010 /* vigra@informatik.uni-hamburg.de */ 00011 /* */ 00012 /* Permission is hereby granted, free of charge, to any person */ 00013 /* obtaining a copy of this software and associated documentation */ 00014 /* files (the "Software"), to deal in the Software without */ 00015 /* restriction, including without limitation the rights to use, */ 00016 /* copy, modify, merge, publish, distribute, sublicense, and/or */ 00017 /* sell copies of the Software, and to permit persons to whom the */ 00018 /* Software is furnished to do so, subject to the following */ 00019 /* conditions: */ 00020 /* */ 00021 /* The above copyright notice and this permission notice shall be */ 00022 /* included in all copies or substantial portions of the */ 00023 /* Software. */ 00024 /* */ 00025 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */ 00026 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ 00027 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ 00028 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ 00029 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ 00030 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ 00031 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ 00032 /* OTHER DEALINGS IN THE SOFTWARE. */ 00033 /* */ 00034 /************************************************************************/ 00035 00036 00037 #ifndef VIGRA_INSPECTIMAGE_HXX 00038 #define VIGRA_INSPECTIMAGE_HXX 00039 00040 #include <vector> 00041 #include <algorithm> 00042 #include "utilities.hxx" 00043 #include "numerictraits.hxx" 00044 #include "iteratortraits.hxx" 00045 #include "functortraits.hxx" 00046 #include "rgbvalue.hxx" 00047 #include "inspector_passes.hxx" 00048 00049 namespace vigra { 00050 00051 /** \addtogroup InspectAlgo Algorithms to Inspect Images 00052 00053 Apply read-only functor to every pixel 00054 */ 00055 //@{ 00056 00057 /********************************************************/ 00058 /* */ 00059 /* inspectLine */ 00060 /* */ 00061 /********************************************************/ 00062 00063 template <class SrcIterator, class SrcAccessor, class Functor> 00064 void 00065 inspectLine(SrcIterator s, 00066 SrcIterator send, SrcAccessor src, 00067 Functor & f) 00068 { 00069 for(; s != send; ++s) 00070 f(src(s)); 00071 } 00072 00073 template <class SrcIterator, class SrcAccessor, 00074 class MaskIterator, class MaskAccessor, 00075 class Functor> 00076 void 00077 inspectLineIf(SrcIterator s, 00078 SrcIterator send, SrcAccessor src, 00079 MaskIterator m, MaskAccessor mask, 00080 Functor & f) 00081 { 00082 for(; s != send; ++s, ++m) 00083 if(mask(m)) 00084 f(src(s)); 00085 } 00086 00087 template <class SrcIterator1, class SrcAccessor1, 00088 class SrcIterator2, class SrcAccessor2, 00089 class Functor> 00090 void 00091 inspectTwoLines(SrcIterator1 s1, 00092 SrcIterator1 s1end, SrcAccessor1 src1, 00093 SrcIterator2 s2, SrcAccessor2 src2, 00094 Functor & f) 00095 { 00096 for(; s1 != s1end; ++s1, ++s2) 00097 f(src1(s1), src2(s2)); 00098 } 00099 00100 template <class SrcIterator1, class SrcAccessor1, 00101 class SrcIterator2, class SrcAccessor2, 00102 class MaskIterator, class MaskAccessor, 00103 class Functor> 00104 void 00105 inspectTwoLinesIf(SrcIterator1 s1, 00106 SrcIterator1 s1end, SrcAccessor1 src1, 00107 SrcIterator2 s2, SrcAccessor2 src2, 00108 MaskIterator m, MaskAccessor mask, 00109 Functor & f) 00110 { 00111 for(; s1 != s1end; ++s1, ++s2, ++m) 00112 if(mask(m)) 00113 f(src1(s1), src2(s2)); 00114 } 00115 00116 /********************************************************/ 00117 /* */ 00118 /* inspectImage */ 00119 /* */ 00120 /********************************************************/ 00121 00122 /** \brief Apply read-only functor to every pixel in the image. 00123 00124 This function can be used to collect statistics of the image etc. 00125 The results must be stored in the functor, which serves as a return 00126 value. 00127 The function uses an accessor to access the pixel data. 00128 00129 <b> Declarations:</b> 00130 00131 pass arguments explicitly: 00132 \code 00133 namespace vigra { 00134 template <class ImageIterator, class Accessor, class Functor> 00135 void 00136 inspectImage(ImageIterator upperleft, ImageIterator lowerright, 00137 Accessor a, Functor & f) 00138 } 00139 \endcode 00140 00141 use argument objects in conjunction with \ref ArgumentObjectFactories : 00142 \code 00143 namespace vigra { 00144 template <class ImageIterator, class Accessor, class Functor> 00145 void 00146 inspectImage(triple<ImageIterator, ImageIterator, Accessor> img, 00147 Functor & f) 00148 } 00149 \endcode 00150 00151 <b> Usage:</b> 00152 00153 <b>\#include</b> <vigra/inspectimage.hxx><br> 00154 Namespace: vigra 00155 00156 \code 00157 // init functor 00158 vigra::BImage img; 00159 00160 vigra::FindMinMax<vigra::BImage::PixelType> minmax; 00161 00162 vigra::inspectImage(srcImageRange(img), minmax); 00163 00164 cout << "Min: " << minmax.min << " Max: " << minmax.max; 00165 00166 \endcode 00167 00168 <b> Required Interface:</b> 00169 00170 \code 00171 ConstImageIterator upperleft, lowerright; 00172 ConstImageIterator::row_iterator ix = upperleft.rowIterator(); 00173 00174 Accessor accessor; 00175 Functor functor; 00176 00177 functor(accessor(ix)); // return not used 00178 \endcode 00179 00180 */ 00181 doxygen_overloaded_function(template <...> void inspectImage) 00182 00183 template <class ImageIterator, class Accessor> 00184 struct inspectImage_binder 00185 { 00186 ImageIterator upperleft; 00187 ImageIterator lowerright; 00188 Accessor a; 00189 00190 inspectImage_binder(ImageIterator ul, ImageIterator lr, Accessor ac) 00191 : upperleft(ul), lowerright(lr), a(ac) {} 00192 template <class Functor> 00193 void operator()(Functor & f) 00194 { 00195 int w = lowerright.x - upperleft.x; 00196 00197 for (ImageIterator t = upperleft; t.y < lowerright.y; ++t.y) 00198 { 00199 inspectLine(t.rowIterator(), t.rowIterator() + w, a, f); 00200 } 00201 } 00202 }; 00203 00204 template <class ImageIterator, class Accessor, class Functor> 00205 void 00206 inspectImage(ImageIterator upperleft, ImageIterator lowerright, 00207 Accessor a, Functor & f) 00208 { 00209 inspectImage_binder<ImageIterator, Accessor> g(upperleft, lowerright, a); 00210 detail::extra_passes_select(g, f); 00211 } 00212 00213 template <class ImageIterator, class Accessor, class Functor> 00214 inline 00215 void 00216 inspectImage(triple<ImageIterator, ImageIterator, Accessor> img, 00217 Functor & f) 00218 { 00219 inspectImage(img.first, img.second, img.third, f); 00220 } 00221 00222 namespace functor 00223 { 00224 template <class T> class UnaryAnalyser; 00225 } 00226 00227 template <class ImageIterator, class Accessor, class Functor> 00228 inline 00229 void 00230 inspectImage(ImageIterator upperleft, ImageIterator lowerright, 00231 Accessor a, functor::UnaryAnalyser<Functor> const & f) 00232 { 00233 inspectImage(upperleft, lowerright, a, 00234 const_cast<functor::UnaryAnalyser<Functor> &>(f)); 00235 } 00236 00237 template <class ImageIterator, class Accessor, class Functor> 00238 inline 00239 void 00240 inspectImage(triple<ImageIterator, ImageIterator, Accessor> img, 00241 functor::UnaryAnalyser<Functor> const & f) 00242 { 00243 inspectImage(img.first, img.second, img.third, 00244 const_cast<functor::UnaryAnalyser<Functor> &>(f)); 00245 } 00246 00247 /********************************************************/ 00248 /* */ 00249 /* inspectImageIf */ 00250 /* */ 00251 /********************************************************/ 00252 00253 /** \brief Apply read-only functor to every pixel in the ROI. 00254 00255 This function can be used to collect statistics of the roi etc. 00256 The functor is called whenever the return value of the mask's 00257 accessor is not zero. 00258 The results must be stored in the functor, which serves as a return 00259 value. 00260 Accessors are used to access the pixel and mask data. 00261 00262 <b> Declarations:</b> 00263 00264 pass arguments explicitly: 00265 \code 00266 namespace vigra { 00267 template <class ImageIterator, class Accessor, 00268 class MaskImageIterator, class MaskAccessor, class Functor> 00269 void 00270 inspectImageIf(ImageIterator upperleft, ImageIterator lowerright, 00271 MaskImageIterator mask_upperleft, MaskAccessor ma, 00272 Functor & f) 00273 } 00274 \endcode 00275 00276 00277 use argument objects in conjunction with \ref ArgumentObjectFactories : 00278 \code 00279 namespace vigra { 00280 template <class ImageIterator, class Accessor, 00281 class MaskImageIterator, class MaskAccessor, class Functor> 00282 void 00283 inspectImageIf(triple<ImageIterator, ImageIterator, Accessor> img, 00284 pair<MaskImageIterator, MaskAccessor> mask, 00285 Functor & f) 00286 } 00287 \endcode 00288 00289 <b> Usage:</b> 00290 00291 <b>\#include</b> <vigra/inspectimage.hxx><br> 00292 Namespace: vigra 00293 00294 \code 00295 vigra::BImage img(100, 100); 00296 vigra::BImage mask(100, 100); 00297 00298 // init functor 00299 vigra::FindMinMax<vigra::BImage::PixelType> minmax; 00300 00301 vigra::inspectImageIf(srcImageRange(img), 00302 maskImage(mask), minmax); 00303 00304 cout << "Min: " << minmax.min << " Max: " << minmax.max; 00305 00306 \endcode 00307 00308 <b> Required Interface:</b> 00309 00310 \code 00311 ConstImageIterator upperleft, lowerright; 00312 MaskImageIterator mask_upperleft; 00313 ConstImageIterator::row_iterator ix = upperleft.rowIterator(); 00314 MaskImageIterator::row_iterator mx = mask_upperleft.rowIterator(); 00315 00316 Accessor accessor; 00317 MaskAccessor mask_accessor; 00318 00319 Functor functor; 00320 00321 if(mask_accessor(mx)) functor(accessor(ix)); 00322 \endcode 00323 00324 */ 00325 doxygen_overloaded_function(template <...> void inspectImageIf) 00326 00327 template <class ImageIterator, class Accessor, 00328 class MaskImageIterator, class MaskAccessor> 00329 struct inspectImageIf_binder 00330 { 00331 ImageIterator upperleft; 00332 ImageIterator lowerright; 00333 Accessor a; 00334 MaskImageIterator mask_upperleft; 00335 MaskAccessor ma; 00336 00337 inspectImageIf_binder(ImageIterator ul, ImageIterator lr, Accessor ac, 00338 MaskImageIterator m_ul, MaskAccessor m_ac) 00339 : upperleft(ul), lowerright(lr), a(ac), mask_upperleft(m_ul), ma(m_ac) 00340 {} 00341 template <class Functor> 00342 void operator()(Functor & f) 00343 { 00344 int w = lowerright.x - upperleft.x; 00345 00346 MaskImageIterator mt = mask_upperleft; 00347 for (ImageIterator t = upperleft; t.y < lowerright.y; ++t.y, ++mt.y) 00348 { 00349 inspectLineIf(t.rowIterator(), 00350 t.rowIterator() + w, a, 00351 mt.rowIterator(), ma, f); 00352 } 00353 } 00354 }; 00355 00356 template <class ImageIterator, class Accessor, 00357 class MaskImageIterator, class MaskAccessor, class Functor> 00358 void 00359 inspectImageIf(ImageIterator upperleft, 00360 ImageIterator lowerright, Accessor a, 00361 MaskImageIterator mask_upperleft, MaskAccessor ma, 00362 Functor & f) 00363 { 00364 inspectImageIf_binder<ImageIterator, Accessor, MaskImageIterator, 00365 MaskAccessor> 00366 g(upperleft, lowerright, a, mask_upperleft, ma); 00367 detail::extra_passes_select(g, f); 00368 } 00369 00370 template <class ImageIterator, class Accessor, 00371 class MaskImageIterator, class MaskAccessor, class Functor> 00372 inline 00373 void 00374 inspectImageIf(triple<ImageIterator, ImageIterator, Accessor> img, 00375 pair<MaskImageIterator, MaskAccessor> mask, 00376 Functor & f) 00377 { 00378 inspectImageIf(img.first, img.second, img.third, 00379 mask.first, mask.second, f); 00380 } 00381 00382 template <class ImageIterator, class Accessor, 00383 class MaskImageIterator, class MaskAccessor, class Functor> 00384 inline void 00385 inspectImageIf(ImageIterator upperleft, 00386 ImageIterator lowerright, Accessor a, 00387 MaskImageIterator mask_upperleft, MaskAccessor ma, 00388 functor::UnaryAnalyser<Functor> const & f) 00389 { 00390 inspectImageIf(upperleft, lowerright, a, 00391 mask_upperleft, ma, const_cast<functor::UnaryAnalyser<Functor> &>(f)); 00392 } 00393 00394 template <class ImageIterator, class Accessor, 00395 class MaskImageIterator, class MaskAccessor, class Functor> 00396 inline void 00397 inspectImageIf(triple<ImageIterator, ImageIterator, Accessor> img, 00398 pair<MaskImageIterator, MaskAccessor> mask, 00399 functor::UnaryAnalyser<Functor> const & f) 00400 { 00401 inspectImageIf(img.first, img.second, img.third, 00402 mask.first, mask.second, const_cast<functor::UnaryAnalyser<Functor> &>(f)); 00403 } 00404 00405 /********************************************************/ 00406 /* */ 00407 /* inspectTwoImages */ 00408 /* */ 00409 /********************************************************/ 00410 00411 /** \brief Apply read-only functor to every pixel of both images. 00412 00413 This function can be used to collect statistics for each region of a 00414 labeled image, especially in conjunction with 00415 the \ref ArrayOfRegionStatistics functor. The results must be 00416 stored in the functor which serves as a return value. 00417 Accessors are used to access the pixel data. 00418 00419 <b> Declarations:</b> 00420 00421 pass arguments explicitly: 00422 \code 00423 namespace vigra { 00424 template <class ImageIterator1, class Accessor1, 00425 class ImageIterator2, class Accessor2, 00426 class Functor> 00427 void 00428 inspectTwoImages(ImageIterator1 upperleft1, ImageIterator1 lowerright1, Accessor1 a1, 00429 ImageIterator2 upperleft2, Accessor2 a2, 00430 Functor & f) 00431 } 00432 \endcode 00433 00434 00435 use argument objects in conjunction with \ref ArgumentObjectFactories : 00436 \code 00437 namespace vigra { 00438 template <class ImageIterator1, class Accessor1, 00439 class ImageIterator2, class Accessor2, 00440 class Functor> 00441 void 00442 inspectTwoImages(triple<ImageIterator1, ImageIterator1, Accessor1> img1, 00443 pair<ImageIterator2, Accessor2> img2, 00444 Functor & f) 00445 } 00446 \endcode 00447 00448 <b> Usage:</b> 00449 00450 <b>\#include</b> <vigra/inspectimage.hxx><br> 00451 Namespace: vigra 00452 00453 \code 00454 vigra::BImage image1; 00455 vigra::BImage image2; 00456 00457 SomeStatisticsFunctor stats(...); // init functor 00458 00459 vigra::inspectTwoImages(srcImageRange(image1), srcImage(image2), 00460 stats); 00461 00462 00463 \endcode 00464 00465 <b> Required Interface:</b> 00466 00467 \code 00468 ImageIterator1 upperleft1, lowerright1; 00469 ImageIterator2 upperleft2; 00470 ImageIterator1::row_iterator ix1 = upperleft1.rowIterator(); 00471 ImageIterator2::row_iterator ix2 = upperleft2.rowIterator(); 00472 00473 Accessor1 accessor1; 00474 Accessor2 accessor2; 00475 00476 Functor functor; 00477 functor(accessor1(ix1), accessor2(ix2)); // return not used 00478 \endcode 00479 00480 */ 00481 doxygen_overloaded_function(template <...> void inspectTwoImages) 00482 00483 template <class ImageIterator1, class Accessor1, 00484 class ImageIterator2, class Accessor2> 00485 struct inspectTwoImages_binder 00486 { 00487 ImageIterator1 upperleft1; 00488 ImageIterator1 lowerright1; 00489 Accessor1 a1; 00490 ImageIterator2 upperleft2; 00491 Accessor2 a2; 00492 inspectTwoImages_binder(ImageIterator1 u1, ImageIterator1 l1, Accessor1 a1_, 00493 ImageIterator2 u2, Accessor2 a2_) 00494 : upperleft1(u1), lowerright1(l1), a1(a1_), upperleft2(u2), a2(a2_) {} 00495 template <class Functor> 00496 void operator()(Functor & f) 00497 { 00498 int w = lowerright1.x - upperleft1.x; 00499 00500 ImageIterator1 t1 = upperleft1; 00501 ImageIterator2 t2 = upperleft2; 00502 for (; t1.y < lowerright1.y; ++t1.y, ++t2.y) 00503 { 00504 inspectTwoLines(t1.rowIterator(), 00505 t1.rowIterator() + w, a1, 00506 t2.rowIterator(), a2, f); 00507 } 00508 } 00509 }; 00510 00511 template <class ImageIterator1, class Accessor1, 00512 class ImageIterator2, class Accessor2, 00513 class Functor> 00514 void 00515 inspectTwoImages(ImageIterator1 upperleft1, ImageIterator1 lowerright1, 00516 Accessor1 a1, 00517 ImageIterator2 upperleft2, Accessor2 a2, 00518 Functor & f) 00519 { 00520 inspectTwoImages_binder<ImageIterator1, Accessor1, 00521 ImageIterator2, Accessor2> 00522 g(upperleft1, lowerright1, a1, upperleft2, a2); 00523 detail::extra_passes_select(g, f); 00524 } 00525 00526 template <class ImageIterator1, class Accessor1, 00527 class ImageIterator2, class Accessor2, 00528 class Functor> 00529 inline 00530 void 00531 inspectTwoImages(triple<ImageIterator1, ImageIterator1, Accessor1> img1, 00532 pair<ImageIterator2, Accessor2> img2, 00533 Functor & f) 00534 { 00535 inspectTwoImages(img1.first, img1.second, img1.third, 00536 img2.first, img2.second, f); 00537 } 00538 00539 template <class ImageIterator1, class Accessor1, 00540 class ImageIterator2, class Accessor2, 00541 class Functor> 00542 inline void 00543 inspectTwoImages(ImageIterator1 upperleft1, ImageIterator1 lowerright1, Accessor1 a1, 00544 ImageIterator2 upperleft2, Accessor2 a2, 00545 functor::UnaryAnalyser<Functor> const & f) 00546 { 00547 inspectTwoImages(upperleft1, lowerright1, a1, 00548 upperleft2, a2, const_cast<functor::UnaryAnalyser<Functor> &>(f)); 00549 } 00550 00551 template <class ImageIterator1, class Accessor1, 00552 class ImageIterator2, class Accessor2, 00553 class Functor> 00554 inline 00555 void 00556 inspectTwoImages(triple<ImageIterator1, ImageIterator1, Accessor1> img1, 00557 pair<ImageIterator2, Accessor2> img2, 00558 functor::UnaryAnalyser<Functor> const & f) 00559 { 00560 inspectTwoImages(img1.first, img1.second, img1.third, 00561 img2.first, img2.second, const_cast<functor::UnaryAnalyser<Functor> &>(f)); 00562 } 00563 00564 /********************************************************/ 00565 /* */ 00566 /* inspectTwoImagesIf */ 00567 /* */ 00568 /********************************************************/ 00569 00570 /** \brief Apply read-only functor to those pixels of both images where 00571 the mask image is non-zero. 00572 00573 This function can be used to collect statistics for selected regions of a 00574 labeled image, especially in conjunction with 00575 the \ref ArrayOfRegionStatistics functor. The results must be 00576 stored in the functor which serves as a return value. 00577 Accessors are used to access the pixel data. 00578 00579 <b> Declarations:</b> 00580 00581 pass arguments explicitly: 00582 \code 00583 namespace vigra { 00584 template <class ImageIterator1, class Accessor1, 00585 class ImageIterator2, class Accessor2, 00586 class MaskImageIterator, class MaskAccessor, 00587 class Functor> 00588 void 00589 inspectTwoImagesIf(ImageIterator1 upperleft1, ImageIterator1 lowerright1, Accessor1 a1, 00590 ImageIterator2 upperleft2, Accessor2 a2, 00591 MaskImageIterator mupperleft, MaskAccessor mask, 00592 Functor & f) 00593 } 00594 \endcode 00595 00596 00597 use argument objects in conjunction with \ref ArgumentObjectFactories : 00598 \code 00599 namespace vigra { 00600 template <class ImageIterator1, class Accessor1, 00601 class ImageIterator2, class Accessor2, 00602 class MaskImageIterator, class MaskAccessor, 00603 class Functor> 00604 void 00605 inspectTwoImagesIf(triple<ImageIterator1, ImageIterator1, Accessor1> img1, 00606 pair<ImageIterator2, Accessor2> img2, 00607 pair<MaskImageIterator, MaskAccessor> mimg, 00608 Functor & f) 00609 } 00610 \endcode 00611 00612 <b> Usage:</b> 00613 00614 <b>\#include</b> <vigra/inspectimage.hxx><br> 00615 Namespace: vigra 00616 00617 \code 00618 vigra::BImage image1; 00619 vigra::BImage image2; 00620 vigra::BImage maskimage; 00621 00622 SomeStatisticsFunctor stats(...); // init functor 00623 00624 vigra::inspectTwoImagesIf(srcImageRange(image1), srcImage(image2), 00625 srcImage(maskimage), region_stats); 00626 00627 \endcode 00628 00629 <b> Required Interface:</b> 00630 00631 \code 00632 ImageIterator1 upperleft1, lowerright1; 00633 ImageIterator2 upperleft2; 00634 MaskImageIterator upperleftm; 00635 ImageIterator1::row_iterator ix1 = upperleft1.rowIterator(); 00636 ImageIterator2::row_iterator ix2 = upperleft2.rowIterator(); 00637 MaskImageIterator::row_iterator mx = mupperleft.rowIterator(); 00638 00639 Accessor1 accessor1; 00640 Accessor2 accessor2; 00641 MaskAccessor mask; 00642 00643 Functor functor; 00644 if(mask(mx)) 00645 functor(accessor1(ix1), accessor2(ix2)); 00646 \endcode 00647 00648 */ 00649 doxygen_overloaded_function(template <...> void inspectTwoImagesIf) 00650 00651 template <class ImageIterator1, class Accessor1, 00652 class ImageIterator2, class Accessor2, 00653 class MaskImageIterator, class MaskAccessor> 00654 struct inspectTwoImagesIf_binder 00655 { 00656 ImageIterator1 upperleft1; 00657 ImageIterator1 lowerright1; 00658 Accessor1 a1; 00659 ImageIterator2 upperleft2; 00660 Accessor2 a2; 00661 MaskImageIterator mupperleft; 00662 MaskAccessor mask; 00663 inspectTwoImagesIf_binder(ImageIterator1 u1, ImageIterator1 l1, 00664 Accessor1 a1_, ImageIterator2 u2, Accessor2 a2_, 00665 MaskImageIterator mu, MaskAccessor ma) 00666 : upperleft1(u1), lowerright1(l1), a1(a1_), upperleft2(u2), a2(a2_), 00667 mupperleft(mu), mask(ma) {} 00668 template <class Functor> 00669 void operator()(Functor & f) 00670 { 00671 int w = lowerright1.x - upperleft1.x; 00672 00673 ImageIterator1 t1 = upperleft1; 00674 ImageIterator2 t2 = upperleft2; 00675 MaskImageIterator mu = mupperleft; 00676 for(; t1.y < lowerright1.y; ++t1.y, ++t2.y, ++mu.y) 00677 { 00678 inspectTwoLinesIf(t1.rowIterator(), 00679 t1.rowIterator() + w, a1, 00680 t2.rowIterator(), a2, 00681 mu.rowIterator(), mask, f); 00682 } 00683 } 00684 }; 00685 00686 template <class ImageIterator1, class Accessor1, 00687 class ImageIterator2, class Accessor2, 00688 class MaskImageIterator, class MaskAccessor, 00689 class Functor> 00690 void 00691 inspectTwoImagesIf(ImageIterator1 upperleft1, ImageIterator1 lowerright1, 00692 Accessor1 a1, 00693 ImageIterator2 upperleft2, Accessor2 a2, 00694 MaskImageIterator mupperleft, MaskAccessor mask, 00695 Functor & f) 00696 { 00697 inspectTwoImagesIf_binder<ImageIterator1, Accessor1, 00698 ImageIterator2, Accessor2, 00699 MaskImageIterator, MaskAccessor> 00700 g(upperleft1, lowerright1, a1, upperleft2, a2, mupperleft, mask); 00701 detail::extra_passes_select(g, f); 00702 } 00703 00704 template <class ImageIterator1, class Accessor1, 00705 class ImageIterator2, class Accessor2, 00706 class MaskImageIterator, class MaskAccessor, 00707 class Functor> 00708 inline 00709 void 00710 inspectTwoImagesIf(triple<ImageIterator1, ImageIterator1, Accessor1> img1, 00711 pair<ImageIterator2, Accessor2> img2, 00712 pair<MaskImageIterator, MaskAccessor> m, 00713 Functor & f) 00714 { 00715 inspectTwoImagesIf(img1.first, img1.second, img1.third, 00716 img2.first, img2.second, 00717 m.first, m.second, 00718 f); 00719 } 00720 00721 template <class ImageIterator1, class Accessor1, 00722 class ImageIterator2, class Accessor2, 00723 class MaskImageIterator, class MaskAccessor, 00724 class Functor> 00725 inline void 00726 inspectTwoImagesIf(ImageIterator1 upperleft1, ImageIterator1 lowerright1, Accessor1 a1, 00727 ImageIterator2 upperleft2, Accessor2 a2, 00728 MaskImageIterator mupperleft, MaskAccessor mask, 00729 functor::UnaryAnalyser<Functor> const & f) 00730 { 00731 inspectTwoImagesIf(upperleft1, lowerright1, a1, 00732 upperleft2, a2, 00733 mupperleft, mask, 00734 const_cast<functor::UnaryAnalyser<Functor> &>(f)); 00735 } 00736 00737 template <class ImageIterator1, class Accessor1, 00738 class ImageIterator2, class Accessor2, 00739 class MaskImageIterator, class MaskAccessor, 00740 class Functor> 00741 inline 00742 void 00743 inspectTwoImagesIf(triple<ImageIterator1, ImageIterator1, Accessor1> img1, 00744 pair<ImageIterator2, Accessor2> img2, 00745 pair<MaskImageIterator, MaskAccessor> m, 00746 functor::UnaryAnalyser<Functor> const & f) 00747 { 00748 inspectTwoImagesIf(img1.first, img1.second, img1.third, 00749 img2.first, img2.second, 00750 m.first, m.second, 00751 const_cast<functor::UnaryAnalyser<Functor> &>(f)); 00752 } 00753 00754 //@} 00755 00756 /** \addtogroup InspectFunctor Functors To Inspect Images 00757 Functors which report image statistics 00758 */ 00759 //@{ 00760 00761 /********************************************************/ 00762 /* */ 00763 /* FindMinMax */ 00764 /* */ 00765 /********************************************************/ 00766 00767 /** \brief Find the minimum and maximum pixel value in an image or ROI. 00768 00769 In addition the size of the ROI is calculated. 00770 These functors can also be used in conjunction with 00771 \ref ArrayOfRegionStatistics to find the extremes of all regions in 00772 a labeled image. 00773 00774 <b> Traits defined:</b> 00775 00776 <tt>FunctorTraits::isUnaryAnalyser</tt> is true (<tt>VigraTrueType</tt>) 00777 00778 <b> Usage:</b> 00779 00780 <b>\#include</b> <vigra/inspectimage.hxx><br> 00781 Namespace: vigra 00782 00783 \code 00784 vigra::BImage img; 00785 00786 vigra::FindMinMax<vigra::BImage::PixelType> minmax; // init functor 00787 00788 vigra::inspectImage(srcImageRange(img), minmax); 00789 00790 cout << "Min: " << minmax.min << " Max: " << minmax.max; 00791 00792 \endcode 00793 00794 <b> Required Interface:</b> 00795 00796 \code 00797 VALUETYPE v1, v2(v1); 00798 00799 v1 < v2; 00800 v1 = v2; 00801 \endcode 00802 00803 */ 00804 template <class VALUETYPE> 00805 class FindMinMax 00806 { 00807 public: 00808 00809 /** the functor's argument type 00810 */ 00811 typedef VALUETYPE argument_type; 00812 00813 /** the functor's result type 00814 */ 00815 typedef VALUETYPE result_type; 00816 00817 /** \deprecated use argument_type 00818 */ 00819 typedef VALUETYPE value_type; 00820 00821 /** init min and max 00822 */ 00823 FindMinMax() 00824 : min( NumericTraits<value_type>::max() ), 00825 max( NumericTraits<value_type>::min() ), 00826 count(0) 00827 {} 00828 00829 /** (re-)init functor (clear min, max) 00830 */ 00831 void reset() 00832 { 00833 count = 0; 00834 } 00835 00836 /** update min and max 00837 */ 00838 void operator()(argument_type const & v) 00839 { 00840 if(count) 00841 { 00842 if(v < min) min = v; 00843 if(max < v) max = v; 00844 } 00845 else 00846 { 00847 min = v; 00848 max = v; 00849 } 00850 ++count; 00851 } 00852 00853 /** update min and max with components of RGBValue<VALUETYPE> 00854 */ 00855 void operator()(RGBValue<VALUETYPE> const & v) 00856 { 00857 operator()(v.red()); 00858 operator()(v.green()); 00859 operator()(v.blue()); 00860 } 00861 00862 /** merge two statistics 00863 */ 00864 void operator()(FindMinMax const & v) 00865 { 00866 if(v.count) 00867 { 00868 if(count) 00869 { 00870 if(v.min < min) min = v.min; 00871 if((this->max) < v.max) max = v.max; 00872 } 00873 else 00874 { 00875 min = v.min; 00876 max = v.max; 00877 } 00878 } 00879 count += v.count; 00880 } 00881 00882 /** the current min 00883 */ 00884 VALUETYPE min; 00885 00886 /** the current max 00887 */ 00888 VALUETYPE max; 00889 00890 /** the number of values processed so far 00891 */ 00892 unsigned int count; 00893 00894 }; 00895 00896 template <class VALUETYPE> 00897 class FunctorTraits<FindMinMax<VALUETYPE> > 00898 : public FunctorTraitsBase<FindMinMax<VALUETYPE> > 00899 { 00900 public: 00901 typedef VigraTrueType isUnaryAnalyser; 00902 }; 00903 00904 /********************************************************/ 00905 /* */ 00906 /* FindSum */ 00907 /* */ 00908 /********************************************************/ 00909 00910 /** \brief Find the sum of the pixel values in an image or ROI. 00911 00912 This Functor can also be used in conjunction with 00913 \ref ArrayOfRegionStatistics to find the sum of all regions in 00914 a labeled image, and with the reduce mode of transformMultiArray(). 00915 00916 <b> Traits defined:</b> 00917 00918 <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitializer</tt> 00919 are true (<tt>VigraTrueType</tt>) 00920 00921 <b> Usage:</b> 00922 00923 <b>\#include</b> <vigra/inspectimage.hxx><br> 00924 Namespace: vigra 00925 00926 \code 00927 vigra::BImage img; 00928 00929 vigra::FindSum<vigra::BImage::PixelType> sum; // init functor 00930 00931 vigra::inspectImage(srcImageRange(img), sum); 00932 00933 cout << "Sum: " << sum(); 00934 00935 \endcode 00936 00937 <b> Required Interface:</b> 00938 00939 \code 00940 VALUETYPE v1, v2(v1); 00941 00942 v1 += v2; 00943 \endcode 00944 00945 */ 00946 template <class VALUETYPE> 00947 class FindSum 00948 : public UnaryReduceFunctorTag 00949 { 00950 public: 00951 00952 /** the functor's argument type 00953 */ 00954 typedef VALUETYPE argument_type; 00955 00956 /** the functor's result type 00957 */ 00958 typedef typename NumericTraits<VALUETYPE>::Promote result_type; 00959 00960 /** init sum 00961 */ 00962 FindSum() 00963 : sum_(NumericTraits<result_type>::zero()) 00964 {} 00965 00966 /** (re-)init sum 00967 */ 00968 void reset() 00969 { 00970 sum_ = NumericTraits<result_type>::zero(); 00971 } 00972 00973 /** update sum 00974 */ 00975 void operator()(argument_type const & v) 00976 { 00977 sum_ += v; 00978 } 00979 00980 /** merge two statistics 00981 */ 00982 void operator()(FindSum const & v) 00983 { 00984 sum_ += v.sum_; 00985 } 00986 00987 /** return current sum 00988 */ 00989 result_type sum() const 00990 { 00991 return sum_; 00992 } 00993 00994 /** return current sum 00995 */ 00996 result_type operator()() const 00997 { 00998 return sum_; 00999 } 01000 01001 result_type sum_; 01002 }; 01003 01004 01005 01006 /********************************************************/ 01007 /* */ 01008 /* FindAverage */ 01009 /* */ 01010 /********************************************************/ 01011 01012 /** \brief Find the average pixel value in an image or ROI. 01013 01014 In addition the size of the ROI is calculated. 01015 This Functor can also be used in conjunction with 01016 \ref ArrayOfRegionStatistics to find the average of all regions in 01017 a labeled image. 01018 01019 <b> Traits defined:</b> 01020 01021 <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitializer</tt> 01022 are true (<tt>VigraTrueType</tt>) 01023 01024 <b> Usage:</b> 01025 01026 <b>\#include</b> <vigra/inspectimage.hxx><br> 01027 Namespace: vigra 01028 01029 \code 01030 vigra::BImage img; 01031 01032 vigra::FindAverage<vigra::BImage::PixelType> average; // init functor 01033 01034 vigra::inspectImage(srcImageRange(img), average); 01035 01036 cout << "Average: " << average(); 01037 01038 \endcode 01039 01040 <b> Required Interface:</b> 01041 01042 \code 01043 VALUETYPE v1, v2(v1); 01044 double d; 01045 01046 v1 += v2; 01047 v1 / d; 01048 \endcode 01049 01050 */ 01051 template <class VALUETYPE> 01052 class FindAverage 01053 { 01054 public: 01055 01056 /** the functor's argument type 01057 */ 01058 typedef VALUETYPE argument_type; 01059 01060 /** the functor's first argument type (for calls with a weight) 01061 */ 01062 typedef VALUETYPE first_argument_type; 01063 01064 /** the functor's second argument type (for calls with a weight) 01065 */ 01066 typedef double second_argument_type; 01067 01068 /** the functor's result type 01069 */ 01070 typedef typename NumericTraits<VALUETYPE>::RealPromote result_type; 01071 01072 /** \deprecated use argument_type and result_type 01073 */ 01074 typedef typename NumericTraits<VALUETYPE>::RealPromote value_type; 01075 01076 /** init average 01077 */ 01078 FindAverage() 01079 : sum_(NumericTraits<result_type>::zero()), count_(0) 01080 {} 01081 01082 /** (re-)init average 01083 */ 01084 void reset() 01085 { 01086 count_ = 0; 01087 sum_ = NumericTraits<result_type>::zero(); 01088 } 01089 01090 /** update average 01091 */ 01092 void operator()(argument_type const & v) 01093 { 01094 sum_ += v; 01095 ++count_; 01096 } 01097 01098 /** update average, using weighted input. 01099 * <tt>stats(value, 1.0)</tt> is equivalent to the unweighted 01100 * call <tt>stats(value)</tt>, and <tt>stats(value, 2.0)</tt> 01101 * is equivalent to two unweighted calls. 01102 */ 01103 void operator()(first_argument_type const & v, second_argument_type weight) 01104 { 01105 sum_ += v * weight; 01106 count_ += weight; 01107 } 01108 01109 /** merge two statistics 01110 */ 01111 void operator()(FindAverage const & v) 01112 { 01113 sum_ += v.sum_; 01114 count_ += v.count_; 01115 } 01116 01117 /** return number of values (sum of weights) seen so far 01118 */ 01119 double count() const 01120 { 01121 return count_; 01122 } 01123 01124 /** return current average 01125 */ 01126 result_type average() const 01127 { 01128 return sum_ / (double)count_; 01129 } 01130 01131 /** return current average 01132 */ 01133 result_type operator()() const 01134 { 01135 return sum_ / (double)count_; 01136 } 01137 01138 result_type sum_; 01139 double count_; 01140 }; 01141 01142 template <class VALUETYPE> 01143 class FunctorTraits<FindAverage<VALUETYPE> > 01144 : public FunctorTraitsBase<FindAverage<VALUETYPE> > 01145 { 01146 public: 01147 typedef VigraTrueType isInitializer; 01148 typedef VigraTrueType isUnaryAnalyser; 01149 }; 01150 01151 /********************************************************/ 01152 /* */ 01153 /* FindAverageAndVariance */ 01154 /* */ 01155 /********************************************************/ 01156 01157 /** \brief Find the average pixel value and its variance in an image or ROI. 01158 01159 This Functor uses West's algorithm to accumulate highly accurate values for 01160 the mean and the sum of squared differences of all values seen so far (the 01161 naive incremental algorithm for the computation of the sum of squares 01162 produces large round-off errors when the mean is much larger than the 01163 standard deviation of the data.) This Functor can also be used in 01164 conjunction with \ref ArrayOfRegionStatistics to find the statistics of all 01165 regions in a labeled image. 01166 01167 <b> Traits defined:</b> 01168 01169 <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitializer</tt> 01170 are true (<tt>VigraTrueType</tt>) 01171 01172 <b> Usage:</b> 01173 01174 <b>\#include</b> <vigra/inspectimage.hxx><br> 01175 Namespace: vigra 01176 01177 \code 01178 vigra::BImage img; 01179 01180 vigra::FindAverageAndVariance<vigra::BImage::PixelType> averageAndVariance; // init functor 01181 01182 vigra::inspectImage(srcImageRange(img), averageAndVariance); 01183 01184 cout << "Average: " << averageAndVariance.average() << "\n"; 01185 cout << "Standard deviation: " << sqrt(averageAndVariance.variance()) << "\n"; 01186 01187 \endcode 01188 01189 <b> Required Interface:</b> 01190 01191 \code 01192 VALUETYPE v1, v2(v1); 01193 double d; 01194 01195 v1 += v2; 01196 v1 + v2; 01197 v1 - v2; 01198 v1 * v2; 01199 v1 / d; 01200 d * v1; 01201 \endcode 01202 01203 */ 01204 template <class VALUETYPE> 01205 class FindAverageAndVariance 01206 { 01207 public: 01208 01209 /** the functor's argument type 01210 */ 01211 typedef VALUETYPE argument_type; 01212 01213 /** the functor's first argument type (for calls with a weight) 01214 */ 01215 typedef VALUETYPE first_argument_type; 01216 01217 /** the functor's second argument type (for calls with a weight) 01218 */ 01219 typedef double second_argument_type; 01220 01221 /** the functor's result type 01222 */ 01223 typedef typename NumericTraits<VALUETYPE>::RealPromote result_type; 01224 01225 /** \deprecated use argument_type and result_type 01226 */ 01227 typedef typename NumericTraits<VALUETYPE>::RealPromote value_type; 01228 01229 /** init average 01230 */ 01231 FindAverageAndVariance() 01232 : mean_(NumericTraits<result_type>::zero()), 01233 sumOfSquaredDifferences_(NumericTraits<result_type>::zero()), 01234 count_(0.0) 01235 {} 01236 01237 /** (re-)init average and variance 01238 */ 01239 void reset() 01240 { 01241 count_ = 0.0; 01242 mean_ = NumericTraits<result_type>::zero(); 01243 sumOfSquaredDifferences_ = NumericTraits<result_type>::zero(); 01244 } 01245 01246 /** update average and variance 01247 */ 01248 void operator()(argument_type const & v) 01249 { 01250 ++count_; 01251 result_type t1 = v - mean_; 01252 result_type t2 = t1 / count_; 01253 mean_ += t2; 01254 sumOfSquaredDifferences_ += (count_-1.0)*t1*t2; 01255 } 01256 01257 /** update average and variance, using weighted input. 01258 * <tt>stats(value, 1.0)</tt> is equivalent to the unweighted 01259 * call <tt>stats(value)</tt>, and <tt>stats(value, 2.0)</tt> 01260 * is equivalent to two unweighted calls. 01261 */ 01262 void operator()(first_argument_type const & v, second_argument_type weight) 01263 { 01264 count_ += weight; 01265 result_type t1 = v - mean_; 01266 result_type t2 = t1 * weight / count_; 01267 mean_ += t2; 01268 01269 //sumOfSquaredDifferences_ += (count_ - weight)*t1*t2; 01270 01271 if(count_ > weight) 01272 sumOfSquaredDifferences_ += 01273 (t1 * t1 * weight / count_) * (count_ - weight ); 01274 } 01275 01276 /** merge two statistics 01277 */ 01278 void operator()(FindAverageAndVariance const & v) 01279 { 01280 double newCount = count_ + v.count_; 01281 sumOfSquaredDifferences_ += v.sumOfSquaredDifferences_ + 01282 count_ / newCount * v.count_ * (mean_ - v.mean_) * (mean_ - v.mean_); 01283 mean_ = (count_ * mean_ + v.count_ * v.mean_) / newCount; 01284 count_ += v.count_; 01285 } 01286 01287 /** return number of values (sum of weights) seen so far 01288 */ 01289 unsigned int count() const 01290 { 01291 return (unsigned int)count_; 01292 } 01293 01294 /** return current average 01295 */ 01296 result_type average() const 01297 { 01298 return mean_; 01299 } 01300 01301 /** return current variance. 01302 If <tt>unbiased = true</tt>, the sum of squared differences 01303 is divided by <tt>count()-1</tt> instead of just <tt>count()</tt>. 01304 */ 01305 result_type variance(bool unbiased = false) const 01306 { 01307 return unbiased 01308 ? sumOfSquaredDifferences_ / (count_ - 1.0) 01309 : sumOfSquaredDifferences_ / count_; 01310 } 01311 01312 /** return current variance. calls <tt>variance()</tt>. 01313 */ 01314 result_type operator()() const 01315 { 01316 return variance(); 01317 } 01318 01319 result_type mean_, sumOfSquaredDifferences_; 01320 double count_; 01321 }; 01322 01323 template <class VALUETYPE> 01324 class FunctorTraits<FindAverageAndVariance<VALUETYPE> > 01325 : public FunctorTraitsBase<FindAverageAndVariance<VALUETYPE> > 01326 { 01327 public: 01328 typedef VigraTrueType isInitializer; 01329 typedef VigraTrueType isUnaryAnalyser; 01330 }; 01331 01332 /********************************************************/ 01333 /* */ 01334 /* FindROISize */ 01335 /* */ 01336 /********************************************************/ 01337 01338 /** \brief Calculate the size of an ROI in an image. 01339 01340 This Functor is often used in conjunction with 01341 \ref ArrayOfRegionStatistics to find the sizes of all regions in 01342 a labeled image. 01343 01344 <b> Traits defined:</b> 01345 01346 <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitializer</tt> 01347 are true (<tt>VigraTrueType</tt>) 01348 01349 <b> Usage:</b> 01350 01351 <b>\#include</b> <vigra/inspectimage.hxx><br> 01352 Namespace: vigra 01353 01354 \code 01355 vigra::BImage img, mask; 01356 01357 vigra::FindROISize<vigra::BImage::PixelType> roisize; // init functor 01358 01359 vigra::inspectImageIf(srcImageRange(img), srcImage(mask), roisize); 01360 01361 cout << "Size of ROI: " << roisize.count; 01362 01363 \endcode 01364 01365 */ 01366 template <class VALUETYPE> 01367 class FindROISize 01368 { 01369 public: 01370 01371 /** the functor's argument type 01372 */ 01373 typedef VALUETYPE argument_type; 01374 01375 /** the functor's result type 01376 */ 01377 typedef unsigned int result_type; 01378 01379 /** \deprecated use argument_type and result_type 01380 */ 01381 typedef VALUETYPE value_type; 01382 01383 /** init counter to 0 01384 */ 01385 FindROISize() 01386 : count(0) 01387 {} 01388 01389 /** (re-)init ROI size with 0 01390 */ 01391 void reset() 01392 { 01393 count = 0; 01394 } 01395 01396 /** update counter 01397 */ 01398 void operator()(argument_type const &) 01399 { 01400 ++count; 01401 } 01402 01403 /** return current size 01404 */ 01405 result_type operator()() const 01406 { 01407 return count; 01408 } 01409 01410 /** return current size 01411 */ 01412 result_type size() const 01413 { 01414 return count; 01415 } 01416 01417 /** merge two statistics 01418 */ 01419 void operator()(FindROISize const & o) 01420 { 01421 count += o.count; 01422 } 01423 01424 /** the current counter 01425 */ 01426 result_type count; 01427 01428 }; 01429 01430 template <class VALUETYPE> 01431 class FunctorTraits<FindROISize<VALUETYPE> > 01432 : public FunctorTraitsBase<FindROISize<VALUETYPE> > 01433 { 01434 public: 01435 typedef VigraTrueType isInitializer; 01436 typedef VigraTrueType isUnaryAnalyser; 01437 }; 01438 01439 /********************************************************/ 01440 /* */ 01441 /* FindBoundingRectangle */ 01442 /* */ 01443 /********************************************************/ 01444 01445 /** \brief Calculate the bounding rectangle of an ROI in an image. 01446 01447 As always in VIGRA, <TT>roiRect.lowerRight</TT> is <em> just outside the rectangle</em>. 01448 That is, the last pixel actually in the rectangle is <TT>roiRect.lowerRight - Diff2D(1,1)</TT>. 01449 This Functor is often used in conjunction with 01450 \ref ArrayOfRegionStatistics to find the bounding rectangles 01451 of all regions in a labeled image. 01452 01453 <b> Traits defined:</b> 01454 01455 <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitializer</tt> 01456 are true (<tt>VigraTrueType</tt>) 01457 01458 <b> Usage:</b> 01459 01460 <b>\#include</b> <vigra/inspectimage.hxx><br> 01461 Namespace: vigra 01462 01463 \code 01464 vigra::BImage img, mask; 01465 ... 01466 01467 vigra::FindBoundingRectangle roiRect; // init functor 01468 01469 // Diff2D is used as the iterator for the source image. This 01470 // simulates an image where each pixel value equals the pixel's 01471 // coordinates. The image 'mask' determines the ROI. 01472 vigra::inspectImageIf(srcIterRange(Diff2D(0,0), (Diff2D)img.size()), 01473 srcImage(mask), roiRect); 01474 01475 cout << "Upper left of ROI: " << 01476 roiRect.upperLeft.x << ", " << roiRect.upperLeft.y << endl; 01477 cout << "Lower right of ROI: " << 01478 roiRect.lowerRight.x << ", " << roiRect.lowerRight.y << endl; 01479 01480 \endcode 01481 01482 */ 01483 class FindBoundingRectangle 01484 { 01485 public: 01486 01487 /** the functor's argument type 01488 */ 01489 typedef Diff2D argument_type; 01490 01491 /** the functors result type 01492 */ 01493 typedef Rect2D result_type; 01494 01495 /** \deprecated use argument_type 01496 */ 01497 typedef Diff2D value_type; 01498 01499 /** Upper left of the region as seen so far 01500 */ 01501 Point2D upperLeft; 01502 01503 /** Lower right of the region as seen so far 01504 */ 01505 Point2D lowerRight; 01506 01507 /** are the functors contents valid ? 01508 */ 01509 bool valid; 01510 01511 /** init rectangle to invalid values 01512 */ 01513 FindBoundingRectangle() 01514 : valid(false) 01515 {} 01516 01517 /** (re-)init functor to find other bounds 01518 */ 01519 void reset() 01520 { 01521 valid = false; 01522 } 01523 01524 /** update rectangle by including the coordinate coord 01525 */ 01526 void operator()(argument_type const & coord) 01527 { 01528 if(!valid) 01529 { 01530 upperLeft = Point2D(coord); 01531 lowerRight = Point2D(coord + Diff2D(1,1)); 01532 valid = true; 01533 } 01534 else 01535 { 01536 upperLeft.x = std::min(upperLeft.x, coord.x); 01537 upperLeft.y = std::min(upperLeft.y, coord.y); 01538 lowerRight.x = std::max(lowerRight.x, coord.x + 1); 01539 lowerRight.y = std::max(lowerRight.y, coord.y + 1); 01540 } 01541 } 01542 01543 /** update rectangle by merging it with another rectangle 01544 */ 01545 void operator()(FindBoundingRectangle const & otherRegion) 01546 { 01547 if(!valid) 01548 { 01549 upperLeft = otherRegion.upperLeft; 01550 lowerRight = otherRegion.lowerRight; 01551 valid = otherRegion.valid; 01552 } 01553 else if(otherRegion.valid) 01554 { 01555 upperLeft.x = std::min(upperLeft.x, otherRegion.upperLeft.x); 01556 upperLeft.y = std::min(upperLeft.y, otherRegion.upperLeft.y); 01557 lowerRight.x = std::max(lowerRight.x, otherRegion.lowerRight.x); 01558 lowerRight.y = std::max(lowerRight.y, otherRegion.lowerRight.y); 01559 } 01560 } 01561 01562 /** Get size of current rectangle. 01563 */ 01564 Size2D size() const 01565 { 01566 return lowerRight - upperLeft; 01567 } 01568 01569 /** Get current rectangle. <TT>result_type::first</TT> is the upper 01570 left corner of the rectangle, <TT>result_type::second</TT> 01571 the lower right. 01572 */ 01573 result_type operator()() const 01574 { 01575 return result_type(upperLeft, lowerRight); 01576 } 01577 }; 01578 01579 template <> 01580 class FunctorTraits<FindBoundingRectangle> 01581 : public FunctorTraitsBase<FindBoundingRectangle> 01582 { 01583 public: 01584 typedef VigraTrueType isInitializer; 01585 typedef VigraTrueType isUnaryAnalyser; 01586 }; 01587 01588 /********************************************************/ 01589 /* */ 01590 /* LastValueFunctor */ 01591 /* */ 01592 /********************************************************/ 01593 01594 /** \brief Stores and returns the last value it has seen. 01595 01596 This Functor is best used in conjunction with 01597 \ref ArrayOfRegionStatistics to realize a look-up table. 01598 01599 <b> Traits defined:</b> 01600 01601 <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitializer</tt> 01602 are true (<tt>VigraTrueType</tt>) 01603 01604 <b> Usage:</b> 01605 01606 <b>\#include</b> <vigra/inspectimage.hxx><br> 01607 Namespace: vigra 01608 01609 \code 01610 vigra::BImage img; 01611 01612 vigra::ArrayOfRegionStatistics<LastValueFunctor<unsigned char> > lut(255); 01613 01614 for(int i=0; i<256; ++i) 01615 { 01616 lut[i] = ...; // init look-up table 01617 } 01618 01619 vigra::transformImage(srcImageRange(img), destImage(img), lut); 01620 01621 \endcode 01622 01623 */ 01624 template <class VALUETYPE> 01625 class LastValueFunctor 01626 { 01627 public: 01628 01629 /** the functor's argument type 01630 */ 01631 typedef VALUETYPE argument_type; 01632 01633 /** the functor's result type 01634 */ 01635 typedef VALUETYPE result_type; 01636 01637 /** \deprecated use argument_type and result_type 01638 */ 01639 typedef VALUETYPE value_type; 01640 01641 /** default construction of value (i.e. builtin types will be set to zero) 01642 */ 01643 LastValueFunctor(argument_type const &initial = argument_type()) 01644 : value(initial) 01645 {} 01646 01647 /** replace value 01648 */ 01649 void operator=(argument_type const & v) { value = v; } 01650 01651 /** reset to initial value (the same as after default construction) 01652 */ 01653 void reset() { value = VALUETYPE(); } 01654 01655 /** replace value 01656 */ 01657 void operator()(argument_type const & v) { value = v; } 01658 01659 /** return current value 01660 */ 01661 result_type const & operator()() const { return value; } 01662 01663 /** the current value 01664 */ 01665 VALUETYPE value; 01666 01667 }; 01668 01669 template <class VALUETYPE> 01670 class FunctorTraits<LastValueFunctor<VALUETYPE> > 01671 : public FunctorTraitsBase<LastValueFunctor<VALUETYPE> > 01672 { 01673 public: 01674 typedef VigraTrueType isInitializer; 01675 typedef VigraTrueType isUnaryAnalyser; 01676 }; 01677 01678 /********************************************************/ 01679 /* */ 01680 /* ReduceFunctor */ 01681 /* */ 01682 /********************************************************/ 01683 01684 /** \brief Apply a functor to reduce the dimensionality of an array. 01685 01686 This functor can be used to emulate the <tt>reduce</tt> standard function of 01687 functional programming using <tt>std::for_each()</tt> or <tt>inspectImage()</tt> 01688 and similar functions. This functor is initialized with a functor encoding 01689 the expression to be applied, and an accumulator storing the current state 01690 of the reduction. For each element of the array, the embedded functor is called 01691 with the accumulator and the current element(s) of the array. The result 01692 of the reduction is available by calling <tt>reduceFunctor()</tt>. 01693 01694 <b> Traits defined:</b> 01695 01696 <tt>FunctorTraits::isUnaryAnalyser</tt>, <tt>FunctorTraits::isBinaryAnalyser</tt> 01697 and <tt>FunctorTraits::isInitializer</tt> 01698 are true (<tt>VigraTrueType</tt>) 01699 01700 <b> Usage:</b> 01701 01702 <b>\#include</b> <vigra/inspectimage.hxx><br> 01703 Namespace: vigra 01704 01705 \code 01706 vigra::BImage img; 01707 ... // fill the image 01708 01709 // create a functor to sum the elements of the image 01710 vigra::ReduceFunctor<std::plus<int>, int> sumElements(std::plus<int>, 0); 01711 01712 vigra::inspectImage(srcImageRange(img), sumElements); 01713 01714 cout << "The sum of the elements " << sumElements() << endl; 01715 01716 \endcode 01717 01718 <b> Required Interface:</b> 01719 01720 \code 01721 FUNCTOR f; 01722 VALUETYPE accumulator, current1, current2; 01723 01724 f(accumulator, current1); // for inspectImage() 01725 f(accumulator, current1, current2); // for inspectTwoImages() 01726 \endcode 01727 */ 01728 template <class FUNCTOR, class VALUETYPE> 01729 class ReduceFunctor 01730 { 01731 FUNCTOR f_; 01732 VALUETYPE start_, accumulator_; 01733 public: 01734 01735 /** the functor's argument type 01736 when used as a unary inspector. 01737 (This is not strictly correct since the argument type 01738 is actually a template parameter.) 01739 */ 01740 typedef VALUETYPE argument_type; 01741 01742 /** the functor's first argument type 01743 when used as a binary inspector. 01744 (This is not strictly correct since the argument type 01745 is actually a template parameter.) 01746 */ 01747 typedef VALUETYPE first_argument_type; 01748 01749 /** the functor's second argument type 01750 when used as a binary inspector. 01751 (This is not strictly correct since the argument type 01752 is actually a template parameter.) 01753 */ 01754 typedef VALUETYPE second_argument_type; 01755 01756 /** the functor's result type 01757 */ 01758 typedef VALUETYPE result_type; 01759 01760 /** create with the given functor and initial value \a initial 01761 for the accumulator. 01762 */ 01763 ReduceFunctor(FUNCTOR const & f, VALUETYPE const & initial) 01764 : f_(f), 01765 start_(initial), 01766 accumulator_(initial) 01767 {} 01768 01769 /** Reset accumulator to the initial value. 01770 */ 01771 void reset() 01772 { accumulator_ = start_; } 01773 01774 /** Use binary functor to connect given value with the accumulator. 01775 The accumulator is used as the first argument, the value \a v 01776 as the second. 01777 */ 01778 template <class T> 01779 void operator()(T const & v) 01780 { 01781 accumulator_ = f_(accumulator_, v); 01782 } 01783 01784 /** Use ternary functor to connect given values with accumulator. 01785 The accumulator is used as the first argument, the values \a v1 01786 ans \a v2 as the second and third. 01787 */ 01788 template <class T1, class T2> 01789 void operator()(T1 const & v1, T2 const & v2) 01790 { 01791 accumulator_ = f_(accumulator_, v1, v2); 01792 } 01793 01794 /** return current value 01795 */ 01796 result_type const & operator()() const 01797 { return accumulator_; } 01798 }; 01799 01800 template <class FUNCTOR, class VALUETYPE> 01801 ReduceFunctor<FUNCTOR, VALUETYPE> 01802 reduceFunctor(FUNCTOR const & f, VALUETYPE const & initial) 01803 { 01804 return ReduceFunctor<FUNCTOR, VALUETYPE>(f, initial); 01805 } 01806 01807 template <class FUNCTOR, class VALUETYPE> 01808 class FunctorTraits<ReduceFunctor<FUNCTOR, VALUETYPE> > 01809 : public FunctorTraitsBase<ReduceFunctor<FUNCTOR, VALUETYPE> > 01810 { 01811 public: 01812 typedef VigraTrueType isInitializer; 01813 typedef VigraTrueType isUnaryAnalyser; 01814 typedef VigraTrueType isBinaryAnalyser; 01815 }; 01816 01817 /********************************************************/ 01818 /* */ 01819 /* ArrayOfRegionStatistics */ 01820 /* */ 01821 /********************************************************/ 01822 01823 /** \brief Calculate statistics for all regions of a labeled image. 01824 01825 This Functor encapsulates an array of statistics functors, one 01826 for each label, and selects the one to be updated according to the 01827 pixel's label. 01828 01829 <b> Traits defined:</b> 01830 01831 <tt>FunctorTraits::isBinaryAnalyser</tt> and <tt>FunctorTraits::isUnaryFunctor</tt> 01832 are true (<tt>VigraTrueType</tt>) 01833 01834 <b> Usage:</b> 01835 01836 <b>\#include</b> <vigra/inspectimage.hxx><br> 01837 Namespace: vigra 01838 01839 \code 01840 vigra::BImage img; 01841 vigra::IImage labels; 01842 int max_label; 01843 ... 01844 01845 // init functor as an array of 'max_label' FindMinMax-Functors 01846 vigra::ArrayOfRegionStatistics<vigra::FindMinMax<vigra::BImage::PixelType> > 01847 minmax(max_label); 01848 01849 vigra::inspectTwoImages(srcImageRange(img), srcImage(labels), minmax); 01850 01851 for(int i=0; i<= max_label; ++i) 01852 { 01853 cout << "Max gray level of region " << i << ": " 01854 << minmax.region[i].max << endl; 01855 } 01856 01857 // init functor as an array of 'max_label' FindAverage-Functors 01858 vigra::ArrayOfRegionStatistics<vigra::FindAverage<vigra::BImage::PixelType> > 01859 average(max_label); 01860 01861 vigra::inspectTwoImages(srcImageRange(img), srcImage(labels), average); 01862 01863 // write back the average of each region into the original image 01864 vigra::transformImage(srcImageRange(labels), destImage(img), average); 01865 01866 \endcode 01867 01868 <b> Required Interface:</b> 01869 01870 \code 01871 RegionStatistics region; 01872 RegionStatistics::argument_type a; 01873 RegionStatistics::result_type r; 01874 01875 region(a); // update statistics 01876 r = region(); // return statistics 01877 01878 \endcode 01879 */ 01880 template <class RegionStatistics, class LabelType = int> 01881 class ArrayOfRegionStatistics 01882 : public detail::get_extra_passes<RegionStatistics> 01883 { 01884 typedef std::vector<RegionStatistics> RegionArray; 01885 01886 public: 01887 /** argument type of the contained statistics object 01888 becomes first argument of the analyser 01889 */ 01890 typedef typename RegionStatistics::argument_type first_argument_type; 01891 01892 /** label type is used to determine the region to be updated 01893 */ 01894 typedef LabelType second_argument_type; 01895 01896 /** label type is also used to determine the region to be 01897 returned by the 1 argument operator() 01898 */ 01899 typedef LabelType argument_type; 01900 01901 /** result type of the contained statistics object 01902 becomes result type of the analyser 01903 */ 01904 typedef typename RegionStatistics::result_type result_type; 01905 01906 /** the value type of the array: the contained statistics object. 01907 <b>Note:</b> this definition was different in older 01908 VIGRA versions. The old definition was wrong. 01909 */ 01910 typedef RegionStatistics value_type; 01911 01912 /** the array's reference type 01913 */ 01914 typedef RegionStatistics & reference; 01915 01916 /** the array's const reference type 01917 */ 01918 typedef RegionStatistics const & const_reference; 01919 01920 /** type to iterate over the statistics array 01921 */ 01922 typedef typename RegionArray::iterator iterator; 01923 01924 /** type to iterate over a const statistics array 01925 */ 01926 typedef typename RegionArray::const_iterator const_iterator; 01927 01928 /** init array of RegionStatistics with default size 0. 01929 */ 01930 ArrayOfRegionStatistics() 01931 {} 01932 01933 /** init array of RegionStatistics with index domain 01934 0...max_region_label. 01935 */ 01936 ArrayOfRegionStatistics(unsigned int max_region_label) 01937 : regions(max_region_label+1) 01938 {} 01939 01940 /** resize array to new index domain 0...max_region_label. 01941 All bin are re-initialized. 01942 */ 01943 void resize(unsigned int max_region_label) 01944 { 01945 RegionArray newRegions(max_region_label+1); 01946 regions.swap(newRegions); 01947 } 01948 01949 /** reset the contained functors to their initial state. 01950 */ 01951 void reset() 01952 { 01953 RegionArray newRegions(regions.size()); 01954 regions.swap(newRegions); 01955 } 01956 01957 /** update regions statistics for region <TT>label</TT>. The label type 01958 is converted to <TT>unsigned int</TT>. 01959 */ 01960 void operator()(first_argument_type const & v, second_argument_type label) { 01961 regions[static_cast<unsigned int>(label)](v); 01962 } 01963 01964 /** merge second region into first 01965 */ 01966 void merge(argument_type label1, argument_type label2) { 01967 regions[static_cast<unsigned int>(label1)](regions[static_cast<unsigned int>(label2)]); 01968 } 01969 01970 /** ask for maximal index (label) allowed 01971 */ 01972 unsigned int maxRegionLabel() const 01973 { return size() - 1; } 01974 01975 /** ask for array size (i.e. maxRegionLabel() + 1) 01976 */ 01977 unsigned int size() const 01978 { return regions.size(); } 01979 01980 /** access the statistics for a region via its label. The label type 01981 is converted to <TT>unsigned int</TT>. 01982 */ 01983 result_type operator()(argument_type label) const 01984 { return regions[static_cast<unsigned int>(label)](); } 01985 01986 /** read the statistics functor for a region via its label 01987 */ 01988 const_reference operator[](argument_type label) const 01989 { return regions[static_cast<unsigned int>(label)]; } 01990 01991 /** access the statistics functor for a region via its label 01992 */ 01993 reference operator[](argument_type label) 01994 { return regions[static_cast<unsigned int>(label)]; } 01995 01996 /** iterator to the begin of the region array 01997 */ 01998 iterator begin() 01999 { return regions.begin(); } 02000 02001 /** const iterator to the begin of the region array 02002 */ 02003 const_iterator begin() const 02004 { return regions.begin(); } 02005 02006 /** iterator to the end of the region array 02007 */ 02008 iterator end() 02009 { return regions.end(); } 02010 02011 /** const iterator to the end of the region array 02012 */ 02013 const_iterator end() const 02014 { return regions.end(); } 02015 02016 /** prepare next pass for multi-pass RegionStatistics types 02017 */ 02018 void calc_sync() 02019 { 02020 for (iterator j = begin(); j != end(); ++j) 02021 this->sync(*j); 02022 } 02023 // update: passes >= 2 02024 struct pass_n_dispatch 02025 { 02026 ArrayOfRegionStatistics & x; 02027 unsigned pass_number; 02028 pass_n_dispatch(ArrayOfRegionStatistics & a, unsigned n) 02029 : x(a), pass_number(n) {} 02030 template <class S> // instantiate only when used. 02031 void operator()(const first_argument_type & v, S label) 02032 { 02033 x.regions[static_cast<unsigned>(label)].updatePassN(v, pass_number); 02034 } 02035 }; 02036 template <class N> // instantiate only when used. 02037 pass_n_dispatch pass_n(N n) 02038 { 02039 if (n < 2 || static_cast<unsigned>(n) > this->max_passes) 02040 vigra_fail("ArrayOfRegionStatistics::pass_n(): inconsistent use."); 02041 return pass_n_dispatch(*this, n); 02042 } 02043 02044 std::vector<RegionStatistics> regions; 02045 }; 02046 02047 template <class RegionStatistics, class LabelType> 02048 class FunctorTraits<ArrayOfRegionStatistics<RegionStatistics, LabelType> > 02049 : public FunctorTraitsBase<ArrayOfRegionStatistics<RegionStatistics, LabelType> > 02050 { 02051 public: 02052 typedef VigraTrueType isUnaryFunctor; 02053 typedef VigraTrueType isBinaryAnalyser; 02054 }; 02055 02056 //@} 02057 02058 } // namespace vigra 02059 02060 #endif // VIGRA_INSPECTIMAGE_HXX
© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) |
html generated using doxygen and Python
|