1 /************************************************************************/
2 /*                                                                      */
3 /*               Copyright 1998-2002 by Ullrich Koethe                  */
4 /*                                                                      */
5 /*    This file is part of the VIGRA computer vision library.           */
6 /*    The VIGRA Website is                                              */
7 /*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
8 /*    Please direct questions, bug reports, and contributions to        */
9 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
10 /*        vigra@informatik.uni-hamburg.de                               */
11 /*                                                                      */
12 /*    Permission is hereby granted, free of charge, to any person       */
13 /*    obtaining a copy of this software and associated documentation    */
14 /*    files (the "Software"), to deal in the Software without           */
15 /*    restriction, including without limitation the rights to use,      */
16 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
17 /*    sell copies of the Software, and to permit persons to whom the    */
18 /*    Software is furnished to do so, subject to the following          */
19 /*    conditions:                                                       */
20 /*                                                                      */
21 /*    The above copyright notice and this permission notice shall be    */
22 /*    included in all copies or substantial portions of the             */
23 /*    Software.                                                         */
24 /*                                                                      */
25 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
26 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
27 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
28 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
29 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
30 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
31 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
32 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */
33 /*                                                                      */
34 /************************************************************************/
35 
36 
37 #ifndef VIGRA_INSPECTIMAGE_HXX
38 #define VIGRA_INSPECTIMAGE_HXX
39 
40 #include <vector>
41 #include <algorithm>
42 #include "utilities.hxx"
43 #include "numerictraits.hxx"
44 #include "iteratortraits.hxx"
45 #include "functortraits.hxx"
46 #include "rgbvalue.hxx"
47 #include "inspector_passes.hxx"
48 #include "multi_shape.hxx"
49 
50 namespace vigra {
51 
52 /** \addtogroup InspectAlgo Algorithms to Inspect Images
53 
54     Collect information and statistics over all or selected pixels.
55 */
56 //@{
57 
58 /********************************************************/
59 /*                                                      */
60 /*                      inspectLine                     */
61 /*                                                      */
62 /********************************************************/
63 
64 template <class SrcIterator, class SrcAccessor, class Functor>
65 void
inspectLine(SrcIterator s,SrcIterator send,SrcAccessor src,Functor & f)66 inspectLine(SrcIterator s,
67             SrcIterator send, SrcAccessor src,
68             Functor & f)
69 {
70     for(; s != send; ++s)
71         f(src(s));
72 }
73 
74 template <class SrcIterator, class SrcAccessor,
75           class MaskIterator, class MaskAccessor,
76           class Functor>
77 void
inspectLineIf(SrcIterator s,SrcIterator send,SrcAccessor src,MaskIterator m,MaskAccessor mask,Functor & f)78 inspectLineIf(SrcIterator s,
79               SrcIterator send, SrcAccessor src,
80               MaskIterator m, MaskAccessor mask,
81               Functor & f)
82 {
83     for(; s != send; ++s, ++m)
84         if(mask(m))
85             f(src(s));
86 }
87 
88 template <class SrcIterator1, class SrcAccessor1,
89           class SrcIterator2, class SrcAccessor2,
90           class Functor>
91 void
inspectTwoLines(SrcIterator1 s1,SrcIterator1 s1end,SrcAccessor1 src1,SrcIterator2 s2,SrcAccessor2 src2,Functor & f)92 inspectTwoLines(SrcIterator1 s1,
93                 SrcIterator1 s1end, SrcAccessor1 src1,
94                 SrcIterator2 s2, SrcAccessor2 src2,
95                 Functor & f)
96 {
97     for(; s1 != s1end; ++s1, ++s2)
98         f(src1(s1), src2(s2));
99 }
100 
101 template <class SrcIterator1, class SrcAccessor1,
102           class SrcIterator2, class SrcAccessor2,
103           class MaskIterator, class MaskAccessor,
104           class Functor>
105 void
inspectTwoLinesIf(SrcIterator1 s1,SrcIterator1 s1end,SrcAccessor1 src1,SrcIterator2 s2,SrcAccessor2 src2,MaskIterator m,MaskAccessor mask,Functor & f)106 inspectTwoLinesIf(SrcIterator1 s1,
107                   SrcIterator1 s1end, SrcAccessor1 src1,
108                   SrcIterator2 s2, SrcAccessor2 src2,
109                   MaskIterator m, MaskAccessor mask,
110                   Functor & f)
111 {
112     for(; s1 != s1end; ++s1, ++s2, ++m)
113         if(mask(m))
114             f(src1(s1), src2(s2));
115 }
116 
117 /********************************************************/
118 /*                                                      */
119 /*                        inspectImage                  */
120 /*                                                      */
121 /********************************************************/
122 
123 /** \brief Apply read-only functor to every pixel in the image.
124 
125     This function can be used to collect statistics of the image etc.
126     The results must be stored in the functor, which serves as a return value
127     (and is therefore passed by reference).
128 
129     For many common statistics, the use of \ref vigra::acc::extractFeatures() in combination with
130     \ref FeatureAccumulators is more convenient.
131 
132     <b> Declarations:</b>
133 
134     pass 2D array views:
135     \code
136     namespace vigra {
137         template <class T, class S, class Functor>
138         void
139         inspectImage(MultiArrayView<2, T, S> const & img,
140                      Functor & f);
141     }
142     \endcode
143 
144     \deprecatedAPI{inspectImage}
145     pass \ref ImageIterators and \ref DataAccessors :
146     \code
147     namespace vigra {
148         template <class ImageIterator, class Accessor, class Functor>
149         void
150         inspectImage(ImageIterator upperleft, ImageIterator lowerright, Accessor a,
151                      Functor & f)
152     }
153     \endcode
154     use argument objects in conjunction with \ref ArgumentObjectFactories :
155     \code
156     namespace vigra {
157         template <class ImageIterator, class Accessor, class Functor>
158         void
159         inspectImage(triple<ImageIterator, ImageIterator, Accessor> img,
160                      Functor & f)
161     }
162     \endcode
163     \deprecatedEnd
164 
165     <b> Usage:</b>
166 
167     <b>\#include</b> \<vigra/inspectimage.hxx\><br>
168     Namespace: vigra
169 
170     \code
171     MultiArray<2, unsigned char> img(width, height);
172     ... // fill img
173 
174     // init functor
175     FindMinMax<unsined char> minmax;
176 
177     inspectImage(img, minmax);
178 
179     cout << "Min: " << minmax.min << " Max: " << minmax.max;
180     \endcode
181 
182     \deprecatedUsage{inspectImage}
183     \code
184     // init functor
185     vigra::BImage img;
186 
187     vigra::FindMinMax<vigra::BImage::PixelType> minmax;
188 
189     vigra::inspectImage(srcImageRange(img), minmax);
190 
191     cout << "Min: " << minmax.min << " Max: " << minmax.max;
192     \endcode
193     <b> Required Interface:</b>
194     \code
195     ConstImageIterator upperleft, lowerright;
196     ConstImageIterator::row_iterator ix = upperleft.rowIterator();
197 
198     Accessor accessor;
199     Functor functor;
200 
201     functor(accessor(ix));         // return not used
202     \endcode
203     \deprecatedEnd
204 
205     \see InspectFunctor, FeatureAccumulators
206 */
207 doxygen_overloaded_function(template <...> void inspectImage)
208 
209 template <class ImageIterator, class Accessor>
210 struct inspectImage_binder
211 {
212     ImageIterator upperleft;
213     ImageIterator lowerright;
214     Accessor a;
215 
inspectImage_bindervigra::inspectImage_binder216     inspectImage_binder(ImageIterator ul, ImageIterator lr, Accessor ac)
217         : upperleft(ul), lowerright(lr), a(ac) {}
218     template <class Functor>
operator ()vigra::inspectImage_binder219     void operator()(Functor & f)
220     {
221         int w = lowerright.x - upperleft.x;
222 
223         for (ImageIterator t = upperleft; t.y < lowerright.y; ++t.y)
224         {
225             inspectLine(t.rowIterator(), t.rowIterator() + w, a, f);
226         }
227     }
228 };
229 
230 template <class ImageIterator, class Accessor, class Functor>
231 void
inspectImage(ImageIterator upperleft,ImageIterator lowerright,Accessor a,Functor & f)232 inspectImage(ImageIterator upperleft, ImageIterator lowerright,
233          Accessor a, Functor & f)
234 {
235     inspectImage_binder<ImageIterator, Accessor> g(upperleft, lowerright, a);
236     detail::extra_passes_select(g, f);
237 }
238 
239 template <class ImageIterator, class Accessor, class Functor>
240 inline void
inspectImage(triple<ImageIterator,ImageIterator,Accessor> img,Functor & f)241 inspectImage(triple<ImageIterator, ImageIterator, Accessor> img,
242              Functor & f)
243 {
244     inspectImage(img.first, img.second, img.third, f);
245 }
246 
247 template <class T, class S, class Functor>
248 inline void
inspectImage(MultiArrayView<2,T,S> const & img,Functor & f)249 inspectImage(MultiArrayView<2, T, S> const & img,
250              Functor & f)
251 {
252     inspectImage(srcImageRange(img), f);
253 }
254 
255 namespace functor
256 {
257     template <class T> class UnaryAnalyser;
258 }
259 
260 template <class ImageIterator, class Accessor, class Functor>
261 inline
262 void
inspectImage(ImageIterator upperleft,ImageIterator lowerright,Accessor a,functor::UnaryAnalyser<Functor> const & f)263 inspectImage(ImageIterator upperleft, ImageIterator lowerright,
264          Accessor a, functor::UnaryAnalyser<Functor> const & f)
265 {
266     inspectImage(upperleft, lowerright, a,
267                  const_cast<functor::UnaryAnalyser<Functor> &>(f));
268 }
269 
270 template <class ImageIterator, class Accessor, class Functor>
271 inline void
inspectImage(triple<ImageIterator,ImageIterator,Accessor> img,functor::UnaryAnalyser<Functor> const & f)272 inspectImage(triple<ImageIterator, ImageIterator, Accessor> img,
273              functor::UnaryAnalyser<Functor> const & f)
274 {
275     inspectImage(img.first, img.second, img.third,
276                  const_cast<functor::UnaryAnalyser<Functor> &>(f));
277 }
278 
279 template <class T, class S, class Functor>
280 inline void
inspectImage(MultiArrayView<2,T,S> const & img,functor::UnaryAnalyser<Functor> const & f)281 inspectImage(MultiArrayView<2, T, S> const & img,
282              functor::UnaryAnalyser<Functor> const & f)
283 {
284     inspectImage(srcImageRange(img),
285                  const_cast<functor::UnaryAnalyser<Functor> &>(f));
286 }
287 
288 /********************************************************/
289 /*                                                      */
290 /*                      inspectImageIf                  */
291 /*                                                      */
292 /********************************************************/
293 
294 /** \brief Apply read-only functor to every pixel in the ROI.
295 
296     This function can be used to collect statistics of the ROI etc.
297     The functor is called whenever the return value of the mask's
298     accessor is not zero.
299     The results must be stored in the functor, which serves as a return
300     value (and is therefore passed by reference.
301 
302     <b> Declarations:</b>
303 
304     pass 2D array views:
305     \code
306     namespace vigra {
307         template <class T, class S,
308                   class TM, class SM, class Functor>
309         void
310         inspectImageIf(MultiArrayView<2, T, S> const & img,
311                        MultiArrayView<2, TM, SM> const & mask,
312                        Functor & f);
313     }
314     \endcode
315 
316     \deprecatedAPI{inspectImageIf}
317     pass \ref ImageIterators and \ref DataAccessors :
318     \code
319     namespace vigra {
320         template <class ImageIterator, class Accessor,
321                   class MaskImageIterator, class MaskAccessor, class Functor>
322         void
323         inspectImageIf(ImageIterator upperleft, ImageIterator lowerright,
324                MaskImageIterator mask_upperleft, MaskAccessor ma,
325                Functor & f)
326     }
327     \endcode
328     use argument objects in conjunction with \ref ArgumentObjectFactories :
329     \code
330     namespace vigra {
331         template <class ImageIterator, class Accessor,
332               class MaskImageIterator, class MaskAccessor, class Functor>
333         void
334         inspectImageIf(triple<ImageIterator, ImageIterator, Accessor> img,
335                pair<MaskImageIterator, MaskAccessor> mask,
336                Functor & f)
337     }
338     \endcode
339     \deprecatedEnd
340 
341     <b> Usage:</b>
342 
343     <b>\#include</b> \<vigra/inspectimage.hxx\><br>
344     Namespace: vigra
345 
346     \code
347     MultiArray<2, unsigned char> img(100, 100),
348                                  mask(100, 100);
349     ... // fill img and mask
350 
351     // init functor
352     FindMinMax<unsigned char> minmax;
353 
354     inspectImageIf(img, mask, minmax);
355 
356     cout << "Min: " << minmax.min << " Max: " << minmax.max;
357     \endcode
358 
359     \deprecatedUsage{inspectImageIf}
360     \code
361     vigra::BImage img(100, 100);
362     vigra::BImage mask(100, 100);
363 
364     // init functor
365     vigra::FindMinMax<vigra::BImage::PixelType> minmax;
366 
367     vigra::inspectImageIf(srcImageRange(img),
368                           maskImage(mask), minmax);
369 
370     cout << "Min: " << minmax.min << " Max: " << minmax.max;
371     \endcode
372     <b> Required Interface:</b>
373     \code
374     ConstImageIterator upperleft, lowerright;
375     MaskImageIterator mask_upperleft;
376     ConstImageIterator::row_iterator ix = upperleft.rowIterator();
377     MaskImageIterator::row_iterator mx = mask_upperleft.rowIterator();
378 
379     Accessor accessor;
380     MaskAccessor mask_accessor;
381 
382     Functor functor;
383 
384     if(mask_accessor(mx)) functor(accessor(ix));
385     \endcode
386     \deprecatedEnd
387 
388     \see InspectFunctor, FeatureAccumulators
389 */
390 doxygen_overloaded_function(template <...> void inspectImageIf)
391 
392 template <class ImageIterator, class Accessor,
393       class MaskImageIterator, class MaskAccessor>
394 struct inspectImageIf_binder
395 {
396     ImageIterator upperleft;
397     ImageIterator lowerright;
398     Accessor a;
399     MaskImageIterator mask_upperleft;
400     MaskAccessor ma;
401 
inspectImageIf_bindervigra::inspectImageIf_binder402     inspectImageIf_binder(ImageIterator ul, ImageIterator lr, Accessor ac,
403                         MaskImageIterator m_ul, MaskAccessor m_ac)
404         : upperleft(ul), lowerright(lr), a(ac), mask_upperleft(m_ul), ma(m_ac)
405     {}
406     template <class Functor>
operator ()vigra::inspectImageIf_binder407     void operator()(Functor & f)
408     {
409         int w = lowerright.x - upperleft.x;
410 
411         MaskImageIterator mt = mask_upperleft;
412         for (ImageIterator t = upperleft; t.y < lowerright.y; ++t.y, ++mt.y)
413         {
414             inspectLineIf(t.rowIterator(),
415                           t.rowIterator() + w, a,
416                           mt.rowIterator(), ma, f);
417         }
418     }
419 };
420 
421 template <class ImageIterator, class Accessor,
422       class MaskImageIterator, class MaskAccessor, class Functor>
423 void
inspectImageIf(ImageIterator upperleft,ImageIterator lowerright,Accessor a,MaskImageIterator mask_upperleft,MaskAccessor ma,Functor & f)424 inspectImageIf(ImageIterator upperleft,
425                ImageIterator lowerright, Accessor a,
426            MaskImageIterator mask_upperleft, MaskAccessor ma,
427            Functor & f)
428 {
429     inspectImageIf_binder<ImageIterator, Accessor, MaskImageIterator,
430                                                                    MaskAccessor>
431         g(upperleft, lowerright, a, mask_upperleft, ma);
432     detail::extra_passes_select(g, f);
433 }
434 
435 template <class ImageIterator, class Accessor,
436       class MaskImageIterator, class MaskAccessor, class Functor>
437 inline void
inspectImageIf(ImageIterator upperleft,ImageIterator lowerright,Accessor a,MaskImageIterator mask_upperleft,MaskAccessor ma,functor::UnaryAnalyser<Functor> const & f)438 inspectImageIf(ImageIterator upperleft,
439                ImageIterator lowerright, Accessor a,
440                MaskImageIterator mask_upperleft, MaskAccessor ma,
441                functor::UnaryAnalyser<Functor> const & f)
442 {
443     inspectImageIf(upperleft, lowerright, a,
444                    mask_upperleft, ma, const_cast<functor::UnaryAnalyser<Functor> &>(f));
445 }
446 
447 template <class ImageIterator, class Accessor,
448           class MaskImageIterator, class MaskAccessor, class Functor>
449 inline void
inspectImageIf(triple<ImageIterator,ImageIterator,Accessor> img,pair<MaskImageIterator,MaskAccessor> mask,Functor & f)450 inspectImageIf(triple<ImageIterator, ImageIterator, Accessor> img,
451                pair<MaskImageIterator, MaskAccessor> mask,
452                Functor & f)
453 {
454     inspectImageIf(img.first, img.second, img.third,
455                    mask.first, mask.second, f);
456 }
457 
458 template <class ImageIterator, class Accessor,
459           class MaskImageIterator, class MaskAccessor, class Functor>
460 inline void
inspectImageIf(triple<ImageIterator,ImageIterator,Accessor> img,pair<MaskImageIterator,MaskAccessor> mask,functor::UnaryAnalyser<Functor> const & f)461 inspectImageIf(triple<ImageIterator, ImageIterator, Accessor> img,
462                pair<MaskImageIterator, MaskAccessor> mask,
463                functor::UnaryAnalyser<Functor> const & f)
464 {
465     inspectImageIf(img.first, img.second, img.third,
466                    mask.first, mask.second, const_cast<functor::UnaryAnalyser<Functor> &>(f));
467 }
468 
469 template <class T, class S,
470           class TM, class SM, class Functor>
471 inline void
inspectImageIf(MultiArrayView<2,T,S> const & img,MultiArrayView<2,TM,SM> const & mask,Functor & f)472 inspectImageIf(MultiArrayView<2, T, S> const & img,
473                MultiArrayView<2, TM, SM> const & mask,
474                Functor & f)
475 {
476     vigra_precondition(img.shape() == mask.shape(),
477         "inspectImageIf(): shape mismatch between input and output.");
478     inspectImageIf(srcImageRange(img),
479                    maskImage(mask), f);
480 }
481 
482 template <class T, class S,
483           class TM, class SM, class Functor>
484 inline void
inspectImageIf(MultiArrayView<2,T,S> const & img,MultiArrayView<2,TM,SM> const & mask,functor::UnaryAnalyser<Functor> const & f)485 inspectImageIf(MultiArrayView<2, T, S> const & img,
486                MultiArrayView<2, TM, SM> const & mask,
487                functor::UnaryAnalyser<Functor> const & f)
488 {
489     inspectImageIf(srcImageRange(img),
490                    maskImage(mask), const_cast<functor::UnaryAnalyser<Functor> &>(f));
491 }
492 
493 /********************************************************/
494 /*                                                      */
495 /*                  inspectTwoImages                    */
496 /*                                                      */
497 /********************************************************/
498 
499 /** \brief Apply read-only functor to every pixel of both images.
500 
501     This function can be used to collect statistics for each region of a
502     labeled image, especially in conjunction with
503     the \ref ArrayOfRegionStatistics functor. The results must be
504     stored in the functor which serves as a return value.
505 
506     Note: For many common statistics, the use of \ref vigra::acc::extractFeatures() in combination
507     with \ref FeatureAccumulators is more convenient.
508 
509     <b> Declarations:</b>
510 
511     pass 2D array views:
512     \code
513     namespace vigra {
514         template <class T1, class S1,
515                   class T2, class S2,
516                   class Functor>
517         void
518         inspectTwoImages(MultiArrayView<2, T1, S1> const & img1,
519                          MultiArrayView<2, T2, S2> const & img2,
520                          Functor & f);
521     }
522     \endcode
523 
524     \deprecatedAPI{inspectTwoImages}
525     pass \ref ImageIterators and \ref DataAccessors :
526     \code
527     namespace vigra {
528         template <class ImageIterator1, class Accessor1,
529               class ImageIterator2, class Accessor2,
530               class Functor>
531         void
532         inspectTwoImages(ImageIterator1 upperleft1, ImageIterator1 lowerright1, Accessor1 a1,
533                  ImageIterator2 upperleft2, Accessor2 a2,
534                  Functor & f)
535     }
536     \endcode
537     use argument objects in conjunction with \ref ArgumentObjectFactories :
538     \code
539     namespace vigra {
540         template <class ImageIterator1, class Accessor1,
541               class ImageIterator2, class Accessor2,
542               class Functor>
543         void
544         inspectTwoImages(triple<ImageIterator1, ImageIterator1, Accessor1> img1,
545                          pair<ImageIterator2, Accessor2> img2,
546                  Functor & f)
547     }
548     \endcode
549     \deprecatedEnd
550 
551     <b> Usage:</b>
552 
553     <b>\#include</b> \<vigra/inspectimage.hxx\><br>
554     Namespace: vigra
555 
556     \code
557     MultiArray<2, unsigned char> image1(width, height), image2(width, height);
558 
559     SomeStatisticsFunctor stats(...);     // init functor
560 
561     inspectTwoImages(image1, image2, stats);
562     \endcode
563 
564     \deprecatedUsage{inspectTwoImages}
565     \code
566     vigra::BImage image1;
567     vigra::BImage image2;
568 
569     SomeStatisticsFunctor stats(...);     // init functor
570 
571     vigra::inspectTwoImages(srcImageRange(image1), srcImage(image2),
572                             stats);
573     \endcode
574     <b> Required Interface:</b>
575     \code
576     ImageIterator1 upperleft1, lowerright1;
577     ImageIterator2 upperleft2;
578     ImageIterator1::row_iterator ix1 = upperleft1.rowIterator();
579     ImageIterator2::row_iterator ix2 = upperleft2.rowIterator();
580 
581     Accessor1 accessor1;
582     Accessor2 accessor2;
583 
584     Functor functor;
585     functor(accessor1(ix1), accessor2(ix2));  // return not used
586     \endcode
587     \deprecatedEnd
588 
589     \see InspectFunctor, FeatureAccumulators
590 */
591 doxygen_overloaded_function(template <...> void inspectTwoImages)
592 
593 template <class ImageIterator1, class Accessor1,
594           class ImageIterator2, class Accessor2>
595 struct inspectTwoImages_binder
596 {
597     ImageIterator1 upperleft1;
598     ImageIterator1 lowerright1;
599     Accessor1      a1;
600     ImageIterator2 upperleft2;
601     Accessor2      a2;
inspectTwoImages_bindervigra::inspectTwoImages_binder602     inspectTwoImages_binder(ImageIterator1 u1, ImageIterator1 l1, Accessor1 a1_,
603                         ImageIterator2 u2, Accessor2 a2_)
604         : upperleft1(u1), lowerright1(l1), a1(a1_), upperleft2(u2), a2(a2_) {}
605     template <class Functor>
operator ()vigra::inspectTwoImages_binder606     void operator()(Functor & f)
607     {
608         int w = lowerright1.x - upperleft1.x;
609 
610         ImageIterator1 t1 = upperleft1;
611         ImageIterator2 t2 = upperleft2;
612         for (; t1.y < lowerright1.y; ++t1.y, ++t2.y)
613         {
614             inspectTwoLines(t1.rowIterator(),
615                             t1.rowIterator() + w, a1,
616                             t2.rowIterator(), a2, f);
617         }
618     }
619 };
620 
621 template <class ImageIterator1, class Accessor1,
622           class ImageIterator2, class Accessor2,
623           class Functor>
624 void
inspectTwoImages(ImageIterator1 upperleft1,ImageIterator1 lowerright1,Accessor1 a1,ImageIterator2 upperleft2,Accessor2 a2,Functor & f)625 inspectTwoImages(ImageIterator1 upperleft1, ImageIterator1 lowerright1,
626                  Accessor1 a1,
627                  ImageIterator2 upperleft2, Accessor2 a2,
628                  Functor & f)
629 {
630     inspectTwoImages_binder<ImageIterator1, Accessor1,
631                             ImageIterator2, Accessor2>
632         g(upperleft1, lowerright1, a1, upperleft2, a2);
633     detail::extra_passes_select(g, f);
634 }
635 
636 template <class ImageIterator1, class Accessor1,
637           class ImageIterator2, class Accessor2,
638           class Functor>
639 inline void
inspectTwoImages(ImageIterator1 upperleft1,ImageIterator1 lowerright1,Accessor1 a1,ImageIterator2 upperleft2,Accessor2 a2,functor::UnaryAnalyser<Functor> const & f)640 inspectTwoImages(ImageIterator1 upperleft1, ImageIterator1 lowerright1, Accessor1 a1,
641                  ImageIterator2 upperleft2, Accessor2 a2,
642                  functor::UnaryAnalyser<Functor> const & f)
643 {
644     inspectTwoImages(upperleft1, lowerright1, a1,
645                      upperleft2, a2, const_cast<functor::UnaryAnalyser<Functor> &>(f));
646 }
647 
648 template <class ImageIterator1, class Accessor1,
649           class ImageIterator2, class Accessor2,
650           class Functor>
651 inline void
inspectTwoImages(triple<ImageIterator1,ImageIterator1,Accessor1> img1,pair<ImageIterator2,Accessor2> img2,Functor & f)652 inspectTwoImages(triple<ImageIterator1, ImageIterator1, Accessor1> img1,
653                  pair<ImageIterator2, Accessor2> img2,
654                  Functor & f)
655 {
656     inspectTwoImages(img1.first, img1.second, img1.third,
657                      img2.first, img2.second, f);
658 }
659 
660 template <class ImageIterator1, class Accessor1,
661           class ImageIterator2, class Accessor2,
662           class Functor>
663 inline void
inspectTwoImages(triple<ImageIterator1,ImageIterator1,Accessor1> img1,pair<ImageIterator2,Accessor2> img2,functor::UnaryAnalyser<Functor> const & f)664 inspectTwoImages(triple<ImageIterator1, ImageIterator1, Accessor1> img1,
665                  pair<ImageIterator2, Accessor2> img2,
666                  functor::UnaryAnalyser<Functor> const & f)
667 {
668     inspectTwoImages(img1.first, img1.second, img1.third,
669                      img2.first, img2.second, const_cast<functor::UnaryAnalyser<Functor> &>(f));
670 }
671 
672 template <class T1, class S1,
673           class T2, class S2,
674           class Functor>
675 inline void
inspectTwoImages(MultiArrayView<2,T1,S1> const & img1,MultiArrayView<2,T2,S2> const & img2,Functor & f)676 inspectTwoImages(MultiArrayView<2, T1, S1> const & img1,
677                  MultiArrayView<2, T2, S2> const & img2,
678                  Functor & f)
679 {
680     vigra_precondition(img1.shape() == img2.shape(),
681         "inspectTwoImages(): shape mismatch between input and output.");
682     inspectTwoImages(srcImageRange(img1),
683                      srcImage(img2),
684                      f);
685 }
686 
687 
688 template <class T1, class S1,
689           class T2, class S2,
690           class Functor>
691 inline void
inspectTwoImages(MultiArrayView<2,T1,S1> const & img1,MultiArrayView<2,T2,S2> const & img2,functor::UnaryAnalyser<Functor> const & f)692 inspectTwoImages(MultiArrayView<2, T1, S1> const & img1,
693                  MultiArrayView<2, T2, S2> const & img2,
694                  functor::UnaryAnalyser<Functor> const & f)
695 {
696     vigra_precondition(img1.shape() == img2.shape(),
697         "inspectTwoImages(): shape mismatch between input and output.");
698     inspectTwoImages(srcImageRange(img1),
699                      srcImage(img2), const_cast<functor::UnaryAnalyser<Functor> &>(f));
700 }
701 
702 /********************************************************/
703 /*                                                      */
704 /*                inspectTwoImagesIf                    */
705 /*                                                      */
706 /********************************************************/
707 
708 /** \brief Apply read-only functor to those pixels of both images where
709     the mask image is non-zero.
710 
711     This function can be used to collect statistics for selected regions of a
712     labeled image, especially in conjunction with
713     the \ref ArrayOfRegionStatistics functor. The results must be
714     stored in the functor which serves as a return value.
715 
716     <b> Declarations:</b>
717 
718     pass 2D array views:
719     \code
720     namespace vigra {
721         template <class T1, class S1,
722                   class T2, class S2,
723                   class TM, class SM,
724                   class Functor>
725         void
726         inspectTwoImagesIf(MultiArrayView<2, T1, S1> const & img1,
727                            MultiArrayView<2, T2, S2> const & img2,
728                            MultiArrayView<2, TM, SM> const & mask,
729                            Functor & f);
730     }
731     \endcode
732 
733     \deprecatedAPI{inspectTwoImagesIf}
734     pass \ref ImageIterators and \ref DataAccessors :
735     \code
736     namespace vigra {
737         template <class ImageIterator1, class Accessor1,
738                   class ImageIterator2, class Accessor2,
739                   class MaskImageIterator, class MaskAccessor,
740                   class Functor>
741         void
742         inspectTwoImagesIf(ImageIterator1 upperleft1, ImageIterator1 lowerright1, Accessor1 a1,
743                          ImageIterator2 upperleft2, Accessor2 a2,
744                          MaskImageIterator mupperleft, MaskAccessor mask,
745                          Functor & f)
746     }
747     \endcode
748     use argument objects in conjunction with \ref ArgumentObjectFactories :
749     \code
750     namespace vigra {
751         template <class ImageIterator1, class Accessor1,
752                   class ImageIterator2, class Accessor2,
753                   class MaskImageIterator, class MaskAccessor,
754                   class Functor>
755         void
756         inspectTwoImagesIf(triple<ImageIterator1, ImageIterator1, Accessor1> img1,
757                  pair<ImageIterator2, Accessor2> img2,
758                  pair<MaskImageIterator, MaskAccessor> mimg,
759                  Functor & f)
760     }
761     \endcode
762     \deprecatedEnd
763 
764     <b> Usage:</b>
765 
766     <b>\#include</b> \<vigra/inspectimage.hxx\><br>
767     Namespace: vigra
768 
769     \code
770     MultiArray<2, unsigned char> image1(width, height), image2(width, height),
771                                  maskimage(width, height);
772 
773     SomeStatisticsFunctor stats(...);     // init functor
774 
775     inspectTwoImagesIf(image1, image2, maskimage, region_stats);
776     \endcode
777 
778     \deprecatedUsage{inspectTwoImagesIf}
779     \code
780     vigra::BImage image1;
781     vigra::BImage image2;
782     vigra::BImage maskimage;
783 
784     SomeStatisticsFunctor stats(...);     // init functor
785 
786     vigra::inspectTwoImagesIf(srcImageRange(image1), srcImage(image2),
787                               srcImage(maskimage), region_stats);
788 
789     \endcode
790     <b> Required Interface:</b>
791     \code
792     ImageIterator1 upperleft1, lowerright1;
793     ImageIterator2 upperleft2;
794     MaskImageIterator upperleftm;
795     ImageIterator1::row_iterator ix1 = upperleft1.rowIterator();
796     ImageIterator2::row_iterator ix2 = upperleft2.rowIterator();
797     MaskImageIterator::row_iterator mx = mupperleft.rowIterator();
798 
799     Accessor1 accessor1;
800     Accessor2 accessor2;
801     MaskAccessor mask;
802 
803     Functor functor;
804     if(mask(mx))
805         functor(accessor1(ix1), accessor2(ix2));
806     \endcode
807     \deprecatedEnd
808 
809     \see InspectFunctor, FeatureAccumulators
810 */
811 doxygen_overloaded_function(template <...> void inspectTwoImagesIf)
812 
813 template <class ImageIterator1, class Accessor1,
814           class ImageIterator2, class Accessor2,
815           class MaskImageIterator, class MaskAccessor>
816 struct inspectTwoImagesIf_binder
817 {
818     ImageIterator1    upperleft1;
819     ImageIterator1    lowerright1;
820     Accessor1         a1;
821     ImageIterator2    upperleft2;
822     Accessor2         a2;
823     MaskImageIterator mupperleft;
824     MaskAccessor      mask;
inspectTwoImagesIf_bindervigra::inspectTwoImagesIf_binder825     inspectTwoImagesIf_binder(ImageIterator1 u1, ImageIterator1 l1,
826                               Accessor1 a1_, ImageIterator2 u2, Accessor2 a2_,
827                               MaskImageIterator mu, MaskAccessor ma)
828         : upperleft1(u1), lowerright1(l1), a1(a1_), upperleft2(u2), a2(a2_),
829           mupperleft(mu), mask(ma) {}
830     template <class Functor>
operator ()vigra::inspectTwoImagesIf_binder831     void operator()(Functor & f)
832     {
833         int w = lowerright1.x - upperleft1.x;
834 
835         ImageIterator1 t1 = upperleft1;
836         ImageIterator2 t2 = upperleft2;
837         MaskImageIterator mu = mupperleft;
838         for(; t1.y < lowerright1.y; ++t1.y, ++t2.y, ++mu.y)
839         {
840             inspectTwoLinesIf(t1.rowIterator(),
841                               t1.rowIterator() + w, a1,
842                               t2.rowIterator(), a2,
843                               mu.rowIterator(), mask, f);
844         }
845     }
846 };
847 
848 template <class ImageIterator1, class Accessor1,
849           class ImageIterator2, class Accessor2,
850           class MaskImageIterator, class MaskAccessor,
851           class Functor>
852 void
inspectTwoImagesIf(ImageIterator1 upperleft1,ImageIterator1 lowerright1,Accessor1 a1,ImageIterator2 upperleft2,Accessor2 a2,MaskImageIterator mupperleft,MaskAccessor mask,Functor & f)853 inspectTwoImagesIf(ImageIterator1 upperleft1, ImageIterator1 lowerright1,
854                    Accessor1 a1,
855                    ImageIterator2 upperleft2, Accessor2 a2,
856                    MaskImageIterator mupperleft, MaskAccessor mask,
857                    Functor & f)
858 {
859     inspectTwoImagesIf_binder<ImageIterator1, Accessor1,
860                               ImageIterator2, Accessor2,
861                               MaskImageIterator, MaskAccessor>
862         g(upperleft1, lowerright1, a1, upperleft2, a2, mupperleft, mask);
863     detail::extra_passes_select(g, f);
864 }
865 
866 template <class ImageIterator1, class Accessor1,
867           class ImageIterator2, class Accessor2,
868           class MaskImageIterator, class MaskAccessor,
869           class Functor>
870 inline void
inspectTwoImagesIf(ImageIterator1 upperleft1,ImageIterator1 lowerright1,Accessor1 a1,ImageIterator2 upperleft2,Accessor2 a2,MaskImageIterator mupperleft,MaskAccessor mask,functor::UnaryAnalyser<Functor> const & f)871 inspectTwoImagesIf(ImageIterator1 upperleft1, ImageIterator1 lowerright1, Accessor1 a1,
872                  ImageIterator2 upperleft2, Accessor2 a2,
873                  MaskImageIterator mupperleft, MaskAccessor mask,
874                  functor::UnaryAnalyser<Functor> const & f)
875 {
876     inspectTwoImagesIf(upperleft1, lowerright1, a1,
877                        upperleft2, a2,
878                        mupperleft, mask,
879                        const_cast<functor::UnaryAnalyser<Functor> &>(f));
880 }
881 
882 template <class ImageIterator1, class Accessor1,
883           class ImageIterator2, class Accessor2,
884           class MaskImageIterator, class MaskAccessor,
885           class Functor>
886 inline void
inspectTwoImagesIf(triple<ImageIterator1,ImageIterator1,Accessor1> img1,pair<ImageIterator2,Accessor2> img2,pair<MaskImageIterator,MaskAccessor> m,Functor & f)887 inspectTwoImagesIf(triple<ImageIterator1, ImageIterator1, Accessor1> img1,
888                    pair<ImageIterator2, Accessor2> img2,
889                    pair<MaskImageIterator, MaskAccessor> m,
890                    Functor & f)
891 {
892     inspectTwoImagesIf(img1.first, img1.second, img1.third,
893                        img2.first, img2.second,
894                        m.first, m.second,
895                        f);
896 }
897 
898 template <class ImageIterator1, class Accessor1,
899           class ImageIterator2, class Accessor2,
900           class MaskImageIterator, class MaskAccessor,
901           class Functor>
902 inline void
inspectTwoImagesIf(triple<ImageIterator1,ImageIterator1,Accessor1> img1,pair<ImageIterator2,Accessor2> img2,pair<MaskImageIterator,MaskAccessor> m,functor::UnaryAnalyser<Functor> const & f)903 inspectTwoImagesIf(triple<ImageIterator1, ImageIterator1, Accessor1> img1,
904                    pair<ImageIterator2, Accessor2> img2,
905                    pair<MaskImageIterator, MaskAccessor> m,
906                    functor::UnaryAnalyser<Functor> const & f)
907 {
908     inspectTwoImagesIf(img1.first, img1.second, img1.third,
909                        img2.first, img2.second,
910                        m.first, m.second,
911                        const_cast<functor::UnaryAnalyser<Functor> &>(f));
912 }
913 
914 template <class T1, class S1,
915           class T2, class S2,
916           class TM, class SM,
917           class Functor>
918 inline void
inspectTwoImagesIf(MultiArrayView<2,T1,S1> const & img1,MultiArrayView<2,T2,S2> const & img2,MultiArrayView<2,TM,SM> const & mask,Functor & f)919 inspectTwoImagesIf(MultiArrayView<2, T1, S1> const & img1,
920                    MultiArrayView<2, T2, S2> const & img2,
921                    MultiArrayView<2, TM, SM> const & mask,
922                    Functor & f)
923 {
924     vigra_precondition(img1.shape() == img2.shape() && img1.shape() == mask.shape(),
925         "inspectTwoImagesIf(): shape mismatch between input and output.");
926     inspectTwoImagesIf(srcImageRange(img1),
927                        srcImage(img2),
928                        maskImage(mask),
929                        f);
930 }
931 
932 template <class T1, class S1,
933           class T2, class S2,
934           class TM, class SM,
935           class Functor>
936 inline void
inspectTwoImagesIf(MultiArrayView<2,T1,S1> const & img1,MultiArrayView<2,T2,S2> const & img2,MultiArrayView<2,TM,SM> const & mask,functor::UnaryAnalyser<Functor> const & f)937 inspectTwoImagesIf(MultiArrayView<2, T1, S1> const & img1,
938                    MultiArrayView<2, T2, S2> const & img2,
939                    MultiArrayView<2, TM, SM> const & mask,
940                    functor::UnaryAnalyser<Functor> const & f)
941 {
942     vigra_precondition(img1.shape() == img2.shape() && img1.shape() == mask.shape(),
943         "inspectTwoImagesIf(): shape mismatch between input and output.");
944     inspectTwoImagesIf(srcImageRange(img1),
945                        srcImage(img2),
946                        maskImage(mask),
947                        const_cast<functor::UnaryAnalyser<Functor> &>(f));
948 }
949 
950 //@}
951 
952 /** \addtogroup InspectFunctor Functors To Inspect Images
953     Functors which report image statistics
954 */
955 //@{
956 
957 /********************************************************/
958 /*                                                      */
959 /*                     FindMinMax                       */
960 /*                                                      */
961 /********************************************************/
962 
963 /** \brief Find the minimum and maximum pixel value in an image or ROI.
964 
965     In addition the size of the ROI is calculated.
966     These functors can also be used in conjunction with
967     \ref ArrayOfRegionStatistics to find the extremes of all regions in
968     a labeled image.
969 
970     <b> Traits defined:</b>
971 
972     <tt>FunctorTraits::isUnaryAnalyser</tt> is true (<tt>VigraTrueType</tt>)
973 
974     <b> Usage:</b>
975 
976     <b>\#include</b> \<vigra/inspectimage.hxx\><br>
977     Namespace: vigra
978 
979     \code
980     vigra::BImage img;
981 
982     vigra::FindMinMax<vigra::BImage::PixelType> minmax;   // init functor
983 
984     vigra::inspectImage(srcImageRange(img), minmax);
985 
986     cout << "Min: " << minmax.min << " Max: " << minmax.max;
987 
988     \endcode
989 
990     <b> Required Interface:</b>
991 
992     \code
993     VALUETYPE v1, v2(v1);
994 
995     v1 < v2;
996     v1 = v2;
997     \endcode
998 
999 */
1000 template <class VALUETYPE>
1001 class FindMinMax
1002 {
1003    public:
1004 
1005         /** the functor's argument type
1006         */
1007     typedef VALUETYPE argument_type;
1008 
1009         /** the functor's result type
1010         */
1011     typedef VALUETYPE result_type;
1012 
1013         /** \deprecated use argument_type
1014         */
1015     typedef VALUETYPE value_type;
1016 
1017         /** init min and max
1018         */
FindMinMax()1019     FindMinMax()
1020     : min( NumericTraits<value_type>::max() ),
1021       max( NumericTraits<value_type>::min() ),
1022       count(0)
1023     {}
1024 
1025         /** (re-)init functor (clear min, max)
1026         */
reset()1027     void reset()
1028     {
1029         count = 0;
1030     }
1031 
1032         /** update min and max
1033         */
operator ()(argument_type const & v)1034     void operator()(argument_type const & v)
1035     {
1036         if(count)
1037         {
1038             if(v < min) min = v;
1039             if(max < v) max = v;
1040         }
1041         else
1042         {
1043             min = v;
1044             max = v;
1045         }
1046         ++count;
1047     }
1048 
1049         /** update min and max with components of RGBValue<VALUETYPE>
1050         */
operator ()(RGBValue<VALUETYPE> const & v)1051     void operator()(RGBValue<VALUETYPE> const & v)
1052     {
1053         operator()(v.red());
1054         operator()(v.green());
1055         operator()(v.blue());
1056     }
1057 
1058         /** merge two statistics
1059         */
operator ()(FindMinMax const & v)1060     void operator()(FindMinMax const & v)
1061     {
1062         if(v.count)
1063         {
1064             if(count)
1065             {
1066                 if(v.min < min) min = v.min;
1067                 if((this->max) < v.max) max = v.max;
1068             }
1069             else
1070             {
1071                 min = v.min;
1072                 max = v.max;
1073             }
1074         }
1075         count += v.count;
1076     }
1077 
1078         /** the current min
1079         */
1080     VALUETYPE min;
1081 
1082         /** the current max
1083         */
1084     VALUETYPE max;
1085 
1086         /** the number of values processed so far
1087         */
1088     unsigned int count;
1089 
1090 };
1091 
1092 template <class VALUETYPE>
1093 class FunctorTraits<FindMinMax<VALUETYPE> >
1094 : public FunctorTraitsBase<FindMinMax<VALUETYPE> >
1095 {
1096   public:
1097     typedef VigraTrueType isUnaryAnalyser;
1098 };
1099 
1100 /********************************************************/
1101 /*                                                      */
1102 /*                      FindSum                         */
1103 /*                                                      */
1104 /********************************************************/
1105 
1106 /** \brief  Find the sum of the pixel values in an image or ROI.
1107 
1108     This Functor can also be used in conjunction with
1109     \ref ArrayOfRegionStatistics to find the sum of all regions in
1110     a labeled image, and with the reduce mode of transformMultiArray().
1111 
1112     <b> Traits defined:</b>
1113 
1114     <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitializer</tt>
1115     are true (<tt>VigraTrueType</tt>)
1116 
1117     <b> Usage:</b>
1118 
1119     <b>\#include</b> \<vigra/inspectimage.hxx\><br>
1120     Namespace: vigra
1121 
1122     \code
1123     vigra::BImage img;
1124 
1125     vigra::FindSum<vigra::BImage::PixelType> sum;   // init functor
1126 
1127     vigra::inspectImage(srcImageRange(img), sum);
1128 
1129     cout << "Sum: " << sum();
1130 
1131     \endcode
1132 
1133     <b> Required Interface:</b>
1134 
1135     \code
1136     VALUETYPE v1, v2(v1);
1137 
1138     v1 += v2;
1139     \endcode
1140 
1141 */
1142 template <class VALUETYPE>
1143 class FindSum
1144 : public UnaryReduceFunctorTag
1145 {
1146    public:
1147 
1148         /** the functor's argument type
1149         */
1150     typedef VALUETYPE argument_type;
1151 
1152         /** the functor's result type
1153         */
1154     typedef typename NumericTraits<VALUETYPE>::Promote result_type;
1155 
1156         /** init sum
1157         */
FindSum()1158     FindSum()
1159     : sum_(NumericTraits<result_type>::zero())
1160     {}
1161 
1162         /** (re-)init sum
1163         */
reset()1164     void reset()
1165     {
1166         sum_ = NumericTraits<result_type>::zero();
1167     }
1168 
1169         /** update sum
1170         */
operator ()(argument_type const & v)1171     void operator()(argument_type const & v)
1172     {
1173         sum_ += v;
1174     }
1175 
1176         /** merge two statistics
1177         */
operator ()(FindSum const & v)1178     void operator()(FindSum const & v)
1179     {
1180         sum_   += v.sum_;
1181     }
1182 
1183         /** return current sum
1184         */
sum() const1185     result_type sum() const
1186     {
1187         return sum_;
1188     }
1189 
1190         /** return current sum
1191         */
operator ()() const1192     result_type operator()() const
1193     {
1194         return sum_;
1195     }
1196 
1197     result_type sum_;
1198 };
1199 
1200 
1201 
1202 /********************************************************/
1203 /*                                                      */
1204 /*                    FindAverage                       */
1205 /*                                                      */
1206 /********************************************************/
1207 
1208 /** \brief  Find the average pixel value in an image or ROI.
1209 
1210     In addition the size of the ROI is calculated.
1211     This Functor can also be used in conjunction with
1212     \ref ArrayOfRegionStatistics to find the average of all regions in
1213     a labeled image.
1214 
1215     <b> Traits defined:</b>
1216 
1217     <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitializer</tt>
1218     are true (<tt>VigraTrueType</tt>)
1219 
1220     <b> Usage:</b>
1221 
1222     <b>\#include</b> \<vigra/inspectimage.hxx\><br>
1223     Namespace: vigra
1224 
1225     \code
1226     vigra::BImage img;
1227 
1228     vigra::FindAverage<vigra::BImage::PixelType> average;   // init functor
1229 
1230     vigra::inspectImage(srcImageRange(img), average);
1231 
1232     cout << "Average: " << average();
1233 
1234     \endcode
1235 
1236     <b> Required Interface:</b>
1237 
1238     \code
1239     VALUETYPE v1, v2(v1);
1240     double d;
1241 
1242     v1 += v2;
1243     v1 / d;
1244     \endcode
1245 
1246 */
1247 template <class VALUETYPE>
1248 class FindAverage
1249 {
1250    public:
1251 
1252         /** the functor's argument type
1253         */
1254     typedef VALUETYPE argument_type;
1255 
1256         /** the functor's first argument type (for calls with a weight)
1257         */
1258     typedef VALUETYPE first_argument_type;
1259 
1260         /** the functor's second argument type (for calls with a weight)
1261         */
1262     typedef double second_argument_type;
1263 
1264         /** the functor's result type
1265         */
1266     typedef typename NumericTraits<VALUETYPE>::RealPromote result_type;
1267 
1268         /** \deprecated use argument_type and result_type
1269         */
1270     typedef typename NumericTraits<VALUETYPE>::RealPromote value_type;
1271 
1272         /** init average
1273         */
FindAverage()1274     FindAverage()
1275     : sum_(NumericTraits<result_type>::zero()), count_(0)
1276     {}
1277 
1278         /** (re-)init average
1279         */
reset()1280     void reset()
1281     {
1282         count_ = 0;
1283         sum_ = NumericTraits<result_type>::zero();
1284     }
1285 
1286         /** update average
1287         */
operator ()(argument_type const & v)1288     void operator()(argument_type const & v)
1289     {
1290         sum_ += v;
1291         ++count_;
1292     }
1293 
1294         /** update average, using weighted input.
1295          * <tt>stats(value, 1.0)</tt> is equivalent to the unweighted
1296          * call <tt>stats(value)</tt>, and <tt>stats(value, 2.0)</tt>
1297          * is equivalent to two unweighted calls.
1298          */
operator ()(first_argument_type const & v,second_argument_type weight)1299     void operator()(first_argument_type const & v, second_argument_type weight)
1300     {
1301         sum_   += v * weight;
1302         count_ += weight;
1303     }
1304 
1305         /** merge two statistics
1306         */
operator ()(FindAverage const & v)1307     void operator()(FindAverage const & v)
1308     {
1309         sum_   += v.sum_;
1310         count_ += v.count_;
1311     }
1312 
1313         /** return number of values (sum of weights) seen so far
1314         */
count() const1315     double count() const
1316     {
1317         return count_;
1318     }
1319 
1320         /** return current average
1321         */
average() const1322     result_type average() const
1323     {
1324         return sum_ / (double)count_;
1325     }
1326 
1327         /** return current average
1328         */
operator ()() const1329     result_type operator()() const
1330     {
1331         return sum_ / (double)count_;
1332     }
1333 
1334     result_type sum_;
1335     double count_;
1336 };
1337 
1338 template <class VALUETYPE>
1339 class FunctorTraits<FindAverage<VALUETYPE> >
1340 : public FunctorTraitsBase<FindAverage<VALUETYPE> >
1341 {
1342   public:
1343     typedef VigraTrueType isInitializer;
1344     typedef VigraTrueType isUnaryAnalyser;
1345 };
1346 
1347 /********************************************************/
1348 /*                                                      */
1349 /*                 FindAverageAndVariance               */
1350 /*                                                      */
1351 /********************************************************/
1352 
1353 /** \brief  Find the average pixel value and its variance in an image or ROI.
1354 
1355     This Functor uses West's algorithm to accumulate highly accurate values for
1356     the mean and the sum of squared differences of all values seen so far (the
1357     naive incremental algorithm for the computation of the sum of squares
1358     produces large round-off errors when the mean is much larger than the
1359     standard deviation of the data.) This Functor can also be used in
1360     conjunction with \ref ArrayOfRegionStatistics to find the statistics of all
1361     regions in a labeled image.
1362 
1363     <b> Traits defined:</b>
1364 
1365     <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitializer</tt>
1366     are true (<tt>VigraTrueType</tt>)
1367 
1368     <b> Usage:</b>
1369 
1370     <b>\#include</b> \<vigra/inspectimage.hxx\><br>
1371     Namespace: vigra
1372 
1373     \code
1374     vigra::BImage img;
1375 
1376     vigra::FindAverageAndVariance<vigra::BImage::PixelType> averageAndVariance;   // init functor
1377 
1378     vigra::inspectImage(srcImageRange(img), averageAndVariance);
1379 
1380     cout << "Average: " << averageAndVariance.average() << "\n";
1381     cout << "Standard deviation: " << sqrt(averageAndVariance.variance()) << "\n";
1382 
1383     \endcode
1384 
1385     <b> Required Interface:</b>
1386 
1387     \code
1388     VALUETYPE v1, v2(v1);
1389     double d;
1390 
1391     v1 += v2;
1392     v1 + v2;
1393     v1 - v2;
1394     v1 * v2;
1395     v1 / d;
1396     d * v1;
1397     \endcode
1398 
1399 */
1400 template <class VALUETYPE>
1401 class FindAverageAndVariance
1402 {
1403    public:
1404 
1405         /** the functor's argument type
1406         */
1407     typedef VALUETYPE argument_type;
1408 
1409         /** the functor's first argument type (for calls with a weight)
1410         */
1411     typedef VALUETYPE first_argument_type;
1412 
1413         /** the functor's second argument type (for calls with a weight)
1414         */
1415     typedef double second_argument_type;
1416 
1417         /** the functor's result type
1418         */
1419     typedef typename NumericTraits<VALUETYPE>::RealPromote result_type;
1420 
1421         /** \deprecated use argument_type and result_type
1422         */
1423     typedef typename NumericTraits<VALUETYPE>::RealPromote value_type;
1424 
1425         /** init average
1426         */
FindAverageAndVariance()1427     FindAverageAndVariance()
1428     : mean_(NumericTraits<result_type>::zero()),
1429       sumOfSquaredDifferences_(NumericTraits<result_type>::zero()),
1430       count_(0.0)
1431     {}
1432 
1433         /** (re-)init average and variance
1434         */
reset()1435     void reset()
1436     {
1437         count_ = 0.0;
1438         mean_ = NumericTraits<result_type>::zero();
1439         sumOfSquaredDifferences_ = NumericTraits<result_type>::zero();
1440     }
1441 
1442         /** update average and variance
1443         */
operator ()(argument_type const & v)1444     void operator()(argument_type const & v)
1445     {
1446         ++count_;
1447         result_type t1 = v - mean_;
1448         result_type t2 = t1 / count_;
1449         mean_ += t2;
1450         sumOfSquaredDifferences_ += (count_-1.0)*t1*t2;
1451     }
1452 
1453         /** update average and variance, using weighted input.
1454          * <tt>stats(value, 1.0)</tt> is equivalent to the unweighted
1455          * call <tt>stats(value)</tt>, and <tt>stats(value, 2.0)</tt>
1456          * is equivalent to two unweighted calls.
1457          */
operator ()(first_argument_type const & v,second_argument_type weight)1458     void operator()(first_argument_type const & v, second_argument_type weight)
1459     {
1460         count_ += weight;
1461         result_type t1 = v - mean_;
1462         result_type t2 = t1 * weight / count_;
1463         mean_ += t2;
1464 
1465         //sumOfSquaredDifferences_ += (count_ - weight)*t1*t2;
1466 
1467         if(count_ > weight)
1468             sumOfSquaredDifferences_ +=
1469                 (t1 * t1 * weight / count_) * (count_ - weight );
1470     }
1471 
1472         /** merge two statistics
1473         */
operator ()(FindAverageAndVariance const & v)1474     void operator()(FindAverageAndVariance const & v)
1475     {
1476         double newCount = count_ + v.count_;
1477         sumOfSquaredDifferences_ += v.sumOfSquaredDifferences_ +
1478                                     count_ / newCount * v.count_ * (mean_ - v.mean_) * (mean_ - v.mean_);
1479         mean_ = (count_ * mean_ + v.count_ * v.mean_) / newCount;
1480         count_ += v.count_;
1481     }
1482 
1483         /** return number of values (sum of weights) seen so far
1484         */
count() const1485     unsigned int count() const
1486     {
1487         return (unsigned int)count_;
1488     }
1489 
1490         /** return current average
1491         */
average() const1492     result_type average() const
1493     {
1494         return mean_;
1495     }
1496 
1497         /** return current variance.
1498             If <tt>unbiased = true</tt>, the sum of squared differences
1499             is divided by <tt>count()-1</tt> instead of just <tt>count()</tt>.
1500         */
variance(bool unbiased=false) const1501     result_type variance(bool unbiased = false) const
1502     {
1503         return unbiased
1504                   ? sumOfSquaredDifferences_ / (count_ - 1.0)
1505                   : sumOfSquaredDifferences_ / count_;
1506     }
1507 
1508         /** return current variance. calls <tt>variance()</tt>.
1509         */
operator ()() const1510     result_type operator()() const
1511     {
1512         return variance();
1513     }
1514 
1515     result_type mean_, sumOfSquaredDifferences_;
1516     double count_;
1517 };
1518 
1519 template <class VALUETYPE>
1520 class FunctorTraits<FindAverageAndVariance<VALUETYPE> >
1521 : public FunctorTraitsBase<FindAverageAndVariance<VALUETYPE> >
1522 {
1523   public:
1524     typedef VigraTrueType isInitializer;
1525     typedef VigraTrueType isUnaryAnalyser;
1526 };
1527 
1528 /********************************************************/
1529 /*                                                      */
1530 /*                    FindROISize                       */
1531 /*                                                      */
1532 /********************************************************/
1533 
1534 /** \brief Calculate the size of an ROI in an image.
1535 
1536     This Functor is often used in conjunction with
1537     \ref ArrayOfRegionStatistics to find the sizes of all regions in
1538     a labeled image.
1539 
1540     <b> Traits defined:</b>
1541 
1542     <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitializer</tt>
1543     are true (<tt>VigraTrueType</tt>)
1544 
1545     <b> Usage:</b>
1546 
1547     <b>\#include</b> \<vigra/inspectimage.hxx\><br>
1548     Namespace: vigra
1549 
1550     \code
1551     vigra::BImage img, mask;
1552 
1553     vigra::FindROISize<vigra::BImage::PixelType> roisize;   // init functor
1554 
1555     vigra::inspectImageIf(srcImageRange(img), srcImage(mask), roisize);
1556 
1557     cout << "Size of ROI: " << roisize.count;
1558 
1559     \endcode
1560 
1561 */
1562 template <class VALUETYPE>
1563 class FindROISize
1564 {
1565    public:
1566 
1567         /** the functor's argument type
1568         */
1569     typedef VALUETYPE argument_type;
1570 
1571         /** the functor's result type
1572         */
1573     typedef unsigned int result_type;
1574 
1575         /** \deprecated use argument_type and result_type
1576         */
1577     typedef VALUETYPE value_type;
1578 
1579         /** init counter to 0
1580         */
FindROISize()1581     FindROISize()
1582     : count(0)
1583     {}
1584 
1585         /** (re-)init ROI size with 0
1586         */
reset()1587     void reset()
1588     {
1589         count = 0;
1590     }
1591 
1592         /** update counter
1593         */
operator ()(argument_type const &)1594     void operator()(argument_type const &)
1595     {
1596         ++count;
1597     }
1598 
1599         /** return current size
1600         */
operator ()() const1601     result_type operator()() const
1602     {
1603         return count;
1604     }
1605 
1606         /** return current size
1607         */
size() const1608     result_type size() const
1609     {
1610         return count;
1611     }
1612 
1613         /** merge two statistics
1614         */
operator ()(FindROISize const & o)1615     void operator()(FindROISize const & o)
1616     {
1617         count += o.count;
1618     }
1619 
1620         /** the current counter
1621         */
1622     result_type count;
1623 
1624 };
1625 
1626 template <class VALUETYPE>
1627 class FunctorTraits<FindROISize<VALUETYPE> >
1628 : public FunctorTraitsBase<FindROISize<VALUETYPE> >
1629 {
1630   public:
1631     typedef VigraTrueType isInitializer;
1632     typedef VigraTrueType isUnaryAnalyser;
1633 };
1634 
1635 /********************************************************/
1636 /*                                                      */
1637 /*                FindBoundingRectangle                 */
1638 /*                                                      */
1639 /********************************************************/
1640 
1641 /** \brief Calculate the bounding rectangle of an ROI in an image.
1642 
1643     As always in VIGRA, <TT>roiRect.lowerRight</TT> is <em> just outside the rectangle</em>.
1644     That is, the last pixel actually in the rectangle is <TT>roiRect.lowerRight - Diff2D(1,1)</TT>.
1645     This Functor is often used in conjunction with
1646     \ref ArrayOfRegionStatistics to find the bounding rectangles
1647     of all regions in a labeled image.
1648 
1649     <b> Traits defined:</b>
1650 
1651     <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitializer</tt>
1652     are true (<tt>VigraTrueType</tt>)
1653 
1654     <b> Usage:</b>
1655 
1656     <b>\#include</b> \<vigra/inspectimage.hxx\><br>
1657     Namespace: vigra
1658 
1659     \code
1660     vigra::BImage img, mask;
1661     ...
1662 
1663     vigra::FindBoundingRectangle roiRect;   // init functor
1664 
1665     // Diff2D is used as the iterator for the source image. This
1666     // simulates an image where each pixel value equals the pixel's
1667     // coordinates. The image 'mask' determines the ROI.
1668     vigra::inspectImageIf(srcIterRange(Diff2D(0,0), (Diff2D)img.size()),
1669                           srcImage(mask), roiRect);
1670 
1671     cout << "Upper left of ROI: " <<
1672         roiRect.upperLeft.x << ", " << roiRect.upperLeft.y << endl;
1673     cout << "Lower right of ROI: " <<
1674         roiRect.lowerRight.x << ", " << roiRect.lowerRight.y << endl;
1675 
1676     \endcode
1677 
1678 */
1679 class FindBoundingRectangle
1680 {
1681   public:
1682 
1683         /** the functor's argument type
1684         */
1685     typedef Diff2D argument_type;
1686 
1687         /** the functors result type
1688         */
1689     typedef Rect2D result_type;
1690 
1691         /** \deprecated use argument_type
1692         */
1693     typedef Diff2D value_type;
1694 
1695         /** Upper left of the region as seen so far
1696         */
1697     Point2D upperLeft;
1698 
1699         /** Lower right of the region as seen so far
1700         */
1701     Point2D lowerRight;
1702 
1703         /** are the functors contents valid ?
1704         */
1705     bool valid;
1706 
1707         /** init rectangle to invalid values
1708         */
FindBoundingRectangle()1709     FindBoundingRectangle()
1710     : valid(false)
1711     {}
1712 
1713         /** (re-)init functor to find other bounds
1714         */
reset()1715     void reset()
1716     {
1717         valid = false;
1718     }
1719 
1720         /** update rectangle by including the coordinate coord
1721         */
operator ()(argument_type const & coord)1722     void operator()(argument_type const & coord)
1723     {
1724         if(!valid)
1725         {
1726             upperLeft = Point2D(coord);
1727             lowerRight = Point2D(coord + Diff2D(1,1));
1728             valid = true;
1729         }
1730         else
1731         {
1732             upperLeft.x = std::min(upperLeft.x, coord.x);
1733             upperLeft.y = std::min(upperLeft.y, coord.y);
1734             lowerRight.x = std::max(lowerRight.x, coord.x + 1);
1735             lowerRight.y = std::max(lowerRight.y, coord.y + 1);
1736         }
1737     }
1738 
1739         /** update rectangle by merging it with another rectangle
1740         */
operator ()(FindBoundingRectangle const & otherRegion)1741     void operator()(FindBoundingRectangle const & otherRegion)
1742     {
1743         if(!valid)
1744         {
1745             upperLeft = otherRegion.upperLeft;
1746             lowerRight = otherRegion.lowerRight;
1747             valid = otherRegion.valid;
1748         }
1749         else if(otherRegion.valid)
1750         {
1751             upperLeft.x = std::min(upperLeft.x, otherRegion.upperLeft.x);
1752             upperLeft.y = std::min(upperLeft.y, otherRegion.upperLeft.y);
1753             lowerRight.x = std::max(lowerRight.x, otherRegion.lowerRight.x);
1754             lowerRight.y = std::max(lowerRight.y, otherRegion.lowerRight.y);
1755         }
1756     }
1757 
1758         /** Get size of current rectangle.
1759         */
size() const1760     Size2D size() const
1761     {
1762         return lowerRight - upperLeft;
1763     }
1764 
1765         /** Get current rectangle. <TT>result_type::first</TT> is the upper
1766             left corner of the rectangle, <TT>result_type::second</TT>
1767             the lower right.
1768         */
operator ()() const1769     result_type operator()() const
1770     {
1771         return result_type(upperLeft, lowerRight);
1772     }
1773 };
1774 
1775 template <>
1776 class FunctorTraits<FindBoundingRectangle>
1777 : public FunctorTraitsBase<FindBoundingRectangle>
1778 {
1779   public:
1780     typedef VigraTrueType isInitializer;
1781     typedef VigraTrueType isUnaryAnalyser;
1782 };
1783 
1784 /********************************************************/
1785 /*                                                      */
1786 /*                 LastValueFunctor                     */
1787 /*                                                      */
1788 /********************************************************/
1789 
1790 /** \brief Stores and returns the last value it has seen.
1791 
1792     This Functor is best used in conjunction with
1793     \ref ArrayOfRegionStatistics to realize a look-up table.
1794 
1795     <b> Traits defined:</b>
1796 
1797     <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitializer</tt>
1798     are true (<tt>VigraTrueType</tt>)
1799 
1800     <b> Usage:</b>
1801 
1802     <b>\#include</b> \<vigra/inspectimage.hxx\><br>
1803     Namespace: vigra
1804 
1805     \code
1806     vigra::BImage img;
1807 
1808     vigra::ArrayOfRegionStatistics<LastValueFunctor<unsigned char> > lut(255);
1809 
1810     for(int i=0; i<256; ++i)
1811     {
1812         lut[i] = ...; // init look-up table
1813     }
1814 
1815     vigra::transformImage(srcImageRange(img), destImage(img), lut);
1816 
1817     \endcode
1818 
1819 */
1820 template <class VALUETYPE>
1821 class LastValueFunctor
1822 {
1823    public:
1824 
1825         /** the functor's argument type
1826         */
1827     typedef VALUETYPE argument_type;
1828 
1829         /** the functor's result type
1830         */
1831     typedef VALUETYPE result_type;
1832 
1833         /** \deprecated use argument_type and result_type
1834         */
1835     typedef VALUETYPE value_type;
1836 
1837         /** default construction of value (i.e. builtin types will be set to zero)
1838         */
LastValueFunctor(argument_type const & initial=argument_type ())1839     LastValueFunctor(argument_type const &initial = argument_type())
1840     : value(initial)
1841     {}
1842 
1843         /** replace value
1844         */
operator =(argument_type const & v)1845     void operator=(argument_type const & v) { value = v; }
1846 
1847         /** reset to initial value (the same as after default construction)
1848         */
reset()1849     void reset() { value = VALUETYPE(); }
1850 
1851         /** replace value
1852         */
operator ()(argument_type const & v)1853     void operator()(argument_type const & v) { value = v; }
1854 
1855         /** return current value
1856         */
operator ()() const1857     result_type const & operator()() const { return value; }
1858 
1859         /** the current value
1860         */
1861     VALUETYPE value;
1862 
1863 };
1864 
1865 template <class VALUETYPE>
1866 class FunctorTraits<LastValueFunctor<VALUETYPE> >
1867 : public FunctorTraitsBase<LastValueFunctor<VALUETYPE> >
1868 {
1869   public:
1870     typedef VigraTrueType isInitializer;
1871     typedef VigraTrueType isUnaryAnalyser;
1872 };
1873 
1874 /********************************************************/
1875 /*                                                      */
1876 /*                     ReduceFunctor                    */
1877 /*                                                      */
1878 /********************************************************/
1879 
1880 /** \brief Apply a functor to reduce the dimensionality of an array.
1881 
1882     This functor can be used to emulate the <tt>reduce</tt> standard function of
1883     functional programming using <tt>std::for_each()</tt> or <tt>inspectImage()</tt>
1884     and similar functions. This functor is initialized with a functor encoding
1885     the expression to be applied, and an accumulator storing the current state
1886     of the reduction. For each element of the array, the embedded functor is called
1887     with the accumulator and the current element(s) of the array. The result
1888     of the reduction is available by calling <tt>reduceFunctor()</tt>.
1889 
1890     <b> Traits defined:</b>
1891 
1892     <tt>FunctorTraits::isUnaryAnalyser</tt>, <tt>FunctorTraits::isBinaryAnalyser</tt>
1893     and <tt>FunctorTraits::isInitializer</tt>
1894     are true (<tt>VigraTrueType</tt>)
1895 
1896     <b> Usage:</b>
1897 
1898     <b>\#include</b> \<vigra/inspectimage.hxx\><br>
1899     Namespace: vigra
1900 
1901     \code
1902     vigra::BImage img;
1903     ... // fill the image
1904 
1905     // create a functor to sum the elements of the image
1906     vigra::ReduceFunctor<std::plus<int>, int> sumElements(std::plus<int>, 0);
1907 
1908     vigra::inspectImage(srcImageRange(img), sumElements);
1909 
1910     cout << "The sum of the elements " << sumElements() << endl;
1911 
1912     \endcode
1913 
1914     <b> Required Interface:</b>
1915 
1916     \code
1917     FUNCTOR f;
1918     VALUETYPE accumulator, current1, current2;
1919 
1920     f(accumulator, current1); // for inspectImage()
1921     f(accumulator, current1, current2); // for inspectTwoImages()
1922     \endcode
1923 */
1924 template <class FUNCTOR, class VALUETYPE>
1925 class ReduceFunctor
1926 {
1927     FUNCTOR f_;
1928     VALUETYPE start_, accumulator_;
1929    public:
1930 
1931         /** the functor's argument type
1932             when used as a unary inspector.
1933             (This is not strictly correct since the argument type
1934             is actually a template parameter.)
1935         */
1936     typedef VALUETYPE argument_type;
1937 
1938         /** the functor's first argument type
1939             when used as a binary inspector.
1940             (This is not strictly correct since the argument type
1941             is actually a template parameter.)
1942         */
1943     typedef VALUETYPE first_argument_type;
1944 
1945         /** the functor's second argument type
1946             when used as a binary inspector.
1947             (This is not strictly correct since the argument type
1948             is actually a template parameter.)
1949         */
1950     typedef VALUETYPE second_argument_type;
1951 
1952         /** the functor's result type
1953         */
1954     typedef VALUETYPE result_type;
1955 
1956         /** create with the given functor and initial value \a initial
1957             for the accumulator.
1958         */
ReduceFunctor(FUNCTOR const & f,VALUETYPE const & initial)1959     ReduceFunctor(FUNCTOR const & f, VALUETYPE const & initial)
1960     : f_(f),
1961       start_(initial),
1962       accumulator_(initial)
1963     {}
1964 
1965         /** Reset accumulator to the initial value.
1966         */
reset()1967     void reset()
1968       { accumulator_ = start_; }
1969 
1970         /** Use binary functor to connect given value with the accumulator.
1971             The accumulator is used as the first argument, the value \a v
1972             as the second.
1973         */
1974     template <class T>
operator ()(T const & v)1975     void operator()(T const & v)
1976     {
1977         accumulator_ = f_(accumulator_, v);
1978     }
1979 
1980         /** Use ternary functor to connect given values with accumulator.
1981             The accumulator is used as the first argument, the values \a v1
1982             ans \a v2 as the second and third.
1983         */
1984     template <class T1, class T2>
operator ()(T1 const & v1,T2 const & v2)1985     void operator()(T1 const & v1, T2 const & v2)
1986     {
1987         accumulator_ = f_(accumulator_, v1, v2);
1988     }
1989 
1990         /** return current value
1991         */
operator ()() const1992     result_type const & operator()() const
1993       { return accumulator_; }
1994 };
1995 
1996 template <class FUNCTOR, class VALUETYPE>
1997 ReduceFunctor<FUNCTOR, VALUETYPE>
reduceFunctor(FUNCTOR const & f,VALUETYPE const & initial)1998 reduceFunctor(FUNCTOR const & f, VALUETYPE const & initial)
1999 {
2000     return ReduceFunctor<FUNCTOR, VALUETYPE>(f, initial);
2001 }
2002 
2003 template <class FUNCTOR, class VALUETYPE>
2004 class FunctorTraits<ReduceFunctor<FUNCTOR, VALUETYPE> >
2005 : public FunctorTraitsBase<ReduceFunctor<FUNCTOR, VALUETYPE> >
2006 {
2007   public:
2008     typedef VigraTrueType isInitializer;
2009     typedef VigraTrueType isUnaryAnalyser;
2010     typedef VigraTrueType isBinaryAnalyser;
2011 };
2012 
2013 /********************************************************/
2014 /*                                                      */
2015 /*              ArrayOfRegionStatistics                 */
2016 /*                                                      */
2017 /********************************************************/
2018 
2019 /** \brief Calculate statistics for all regions of a labeled image.
2020 
2021     This Functor encapsulates an array of statistics functors, one
2022     for each label, and selects the one to be updated according to the
2023     pixel's label.
2024 
2025     <b> Traits defined:</b>
2026 
2027     <tt>FunctorTraits::isBinaryAnalyser</tt> and <tt>FunctorTraits::isUnaryFunctor</tt>
2028     are true (<tt>VigraTrueType</tt>)
2029 
2030     <b> Usage:</b>
2031 
2032     <b>\#include</b> \<vigra/inspectimage.hxx\><br>
2033     Namespace: vigra
2034 
2035     \code
2036     vigra::BImage img;
2037     vigra::IImage labels;
2038     int max_label;
2039     ...
2040 
2041     // init functor as an array of 'max_label' FindMinMax-Functors
2042     vigra::ArrayOfRegionStatistics<vigra::FindMinMax<vigra::BImage::PixelType> >
2043                                                          minmax(max_label);
2044 
2045     vigra::inspectTwoImages(srcImageRange(img), srcImage(labels), minmax);
2046 
2047     for(int i=0; i<= max_label; ++i)
2048     {
2049         cout << "Max gray level of region " << i << ": "
2050              << minmax.region[i].max << endl;
2051     }
2052 
2053     // init functor as an array of 'max_label' FindAverage-Functors
2054     vigra::ArrayOfRegionStatistics<vigra::FindAverage<vigra::BImage::PixelType> >
2055                                                          average(max_label);
2056 
2057     vigra::inspectTwoImages(srcImageRange(img), srcImage(labels), average);
2058 
2059     // write back the average of each region into the original image
2060     vigra::transformImage(srcImageRange(labels), destImage(img), average);
2061 
2062     \endcode
2063 
2064     <b> Required Interface:</b>
2065 
2066     \code
2067     RegionStatistics region;
2068     RegionStatistics::argument_type a;
2069     RegionStatistics::result_type r;
2070 
2071     region(a);     // update statistics
2072     r = region();  // return statistics
2073 
2074     \endcode
2075 */
2076 template <class RegionStatistics, class LabelType = int>
2077 class ArrayOfRegionStatistics
2078     : public detail::get_extra_passes<RegionStatistics>
2079 {
2080     typedef std::vector<RegionStatistics> RegionArray;
2081 
2082   public:
2083          /** argument type of the contained statistics object
2084              becomes first argument of the analyser
2085          */
2086     typedef typename RegionStatistics::argument_type first_argument_type;
2087 
2088          /** label type is used to determine the region to be updated
2089          */
2090     typedef LabelType second_argument_type;
2091 
2092          /** label type is also used to determine the region to be
2093              returned by the 1 argument operator()
2094          */
2095     typedef LabelType argument_type;
2096 
2097          /** result type of the contained statistics object
2098              becomes result type of the analyser
2099          */
2100     typedef typename RegionStatistics::result_type result_type;
2101 
2102          /** the value type of the array: the contained statistics object.
2103              <b>Note:</b> this definition was different in older
2104              VIGRA versions. The old definition was wrong.
2105          */
2106     typedef RegionStatistics value_type;
2107 
2108          /** the array's reference type
2109          */
2110     typedef RegionStatistics & reference;
2111 
2112          /** the array's const reference type
2113          */
2114     typedef RegionStatistics const & const_reference;
2115 
2116          /** type to iterate over the statistics array
2117          */
2118     typedef typename RegionArray::iterator iterator;
2119 
2120          /** type to iterate over a const statistics array
2121          */
2122     typedef typename RegionArray::const_iterator const_iterator;
2123 
2124         /** init array of RegionStatistics with default size 0.
2125         */
ArrayOfRegionStatistics()2126     ArrayOfRegionStatistics()
2127     {}
2128 
2129         /** init array of RegionStatistics with index domain
2130             0...max_region_label.
2131         */
ArrayOfRegionStatistics(unsigned int max_region_label)2132     ArrayOfRegionStatistics(unsigned int max_region_label)
2133     : regions(max_region_label+1)
2134     {}
2135 
2136         /** resize array to new index domain 0...max_region_label.
2137             All bin are re-initialized.
2138         */
resize(unsigned int max_region_label)2139     void resize(unsigned int max_region_label)
2140     {
2141         RegionArray newRegions(max_region_label+1);
2142         regions.swap(newRegions);
2143     }
2144 
2145         /** reset the contained functors to their initial state.
2146         */
reset()2147     void reset()
2148     {
2149         RegionArray newRegions(regions.size());
2150         regions.swap(newRegions);
2151     }
2152 
2153         /** update regions statistics for region <TT>label</TT>. The label type
2154             is converted to <TT>unsigned int</TT>.
2155         */
operator ()(first_argument_type const & v,second_argument_type label)2156     void operator()(first_argument_type const & v, second_argument_type label) {
2157         regions[static_cast<unsigned int>(label)](v);
2158     }
2159 
2160         /** merge second region into first
2161         */
merge(argument_type label1,argument_type label2)2162     void merge(argument_type label1, argument_type label2) {
2163         regions[static_cast<unsigned int>(label1)](regions[static_cast<unsigned int>(label2)]);
2164     }
2165 
2166         /** ask for maximal index (label) allowed
2167         */
maxRegionLabel() const2168     unsigned int maxRegionLabel() const
2169         { return size() - 1; }
2170 
2171         /** ask for array size (i.e. maxRegionLabel() + 1)
2172         */
size() const2173     unsigned int size() const
2174         { return regions.size(); }
2175 
2176         /** access the statistics for a region via its label. The label type
2177             is converted to <TT>unsigned int</TT>.
2178         */
operator ()(argument_type label) const2179     result_type operator()(argument_type label) const
2180         { return regions[static_cast<unsigned int>(label)](); }
2181 
2182         /** read the statistics functor for a region via its label
2183         */
operator [](argument_type label) const2184     const_reference operator[](argument_type label) const
2185         { return regions[static_cast<unsigned int>(label)]; }
2186 
2187         /** access the statistics functor for a region via its label
2188         */
operator [](argument_type label)2189     reference operator[](argument_type label)
2190         { return regions[static_cast<unsigned int>(label)]; }
2191 
2192         /** iterator to the begin of the region array
2193         */
begin()2194     iterator begin()
2195         { return regions.begin(); }
2196 
2197         /** const iterator to the begin of the region array
2198         */
begin() const2199     const_iterator begin() const
2200         { return regions.begin(); }
2201 
2202         /** iterator to the end of the region array
2203         */
end()2204     iterator end()
2205         { return regions.end(); }
2206 
2207         /** const iterator to the end of the region array
2208         */
end() const2209     const_iterator end() const
2210         { return regions.end(); }
2211 
2212         /** prepare next pass for multi-pass RegionStatistics types
2213         */
calc_sync()2214     void calc_sync()
2215     {
2216         for (iterator j = begin(); j != end(); ++j)
2217             this->sync(*j);
2218     }
2219     // update: passes >= 2
2220     struct pass_n_dispatch
2221     {
2222         ArrayOfRegionStatistics & x;
2223         unsigned                  pass_number;
pass_n_dispatchvigra::ArrayOfRegionStatistics::pass_n_dispatch2224         pass_n_dispatch(ArrayOfRegionStatistics & a, unsigned n)
2225             : x(a), pass_number(n) {}
2226         template <class S> // instantiate only when used.
operator ()vigra::ArrayOfRegionStatistics::pass_n_dispatch2227         void operator()(const first_argument_type & v, S label)
2228         {
2229             x.regions[static_cast<unsigned>(label)].updatePassN(v, pass_number);
2230         }
2231     };
2232     template <class N> // instantiate only when used.
pass_n(N n)2233     pass_n_dispatch pass_n(N n)
2234     {
2235         if (n < 2 || static_cast<unsigned>(n) > this->max_passes)
2236             vigra_fail("ArrayOfRegionStatistics::pass_n(): inconsistent use.");
2237         return pass_n_dispatch(*this, n);
2238     }
2239 
2240     std::vector<RegionStatistics> regions;
2241 };
2242 
2243 template <class RegionStatistics, class LabelType>
2244 class FunctorTraits<ArrayOfRegionStatistics<RegionStatistics, LabelType> >
2245 : public FunctorTraitsBase<ArrayOfRegionStatistics<RegionStatistics, LabelType> >
2246 {
2247   public:
2248     typedef VigraTrueType isUnaryFunctor;
2249     typedef VigraTrueType isBinaryAnalyser;
2250 };
2251 
2252 //@}
2253 
2254 } // namespace vigra
2255 
2256 #endif // VIGRA_INSPECTIMAGE_HXX
2257