[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

vigra/inspectimage.hxx VIGRA

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)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.9.0 (Tue Nov 6 2012)