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

inspectimage.hxx
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 
48 namespace vigra {
49 
50 /** \addtogroup InspectAlgo Algorithms to Inspect Images
51 
52  Apply read-only functor to every pixel
53 */
54 //@{
55 
56 /********************************************************/
57 /* */
58 /* inspectLine */
59 /* */
60 /********************************************************/
61 
62 template <class SrcIterator, class SrcAccessor, class Functor>
63 void
64 inspectLine(SrcIterator s,
65  SrcIterator send, SrcAccessor src,
66  Functor & f)
67 {
68  for(; s != send; ++s)
69  f(src(s));
70 }
71 
72 template <class SrcIterator, class SrcAccessor,
73  class MaskIterator, class MaskAccessor,
74  class Functor>
75 void
76 inspectLineIf(SrcIterator s,
77  SrcIterator send, SrcAccessor src,
78  MaskIterator m, MaskAccessor mask,
79  Functor & f)
80 {
81  for(; s != send; ++s, ++m)
82  if(mask(m))
83  f(src(s));
84 }
85 
86 template <class SrcIterator1, class SrcAccessor1,
87  class SrcIterator2, class SrcAccessor2,
88  class Functor>
89 void
90 inspectTwoLines(SrcIterator1 s1,
91  SrcIterator1 s1end, SrcAccessor1 src1,
92  SrcIterator2 s2, SrcAccessor2 src2,
93  Functor & f)
94 {
95  for(; s1 != s1end; ++s1, ++s2)
96  f(src1(s1), src2(s2));
97 }
98 
99 template <class SrcIterator1, class SrcAccessor1,
100  class SrcIterator2, class SrcAccessor2,
101  class MaskIterator, class MaskAccessor,
102  class Functor>
103 void
104 inspectTwoLinesIf(SrcIterator1 s1,
105  SrcIterator1 s1end, SrcAccessor1 src1,
106  SrcIterator2 s2, SrcAccessor2 src2,
107  MaskIterator m, MaskAccessor mask,
108  Functor & f)
109 {
110  for(; s1 != s1end; ++s1, ++s2, ++m)
111  if(mask(m))
112  f(src1(s1), src2(s2));
113 }
114 
115 /********************************************************/
116 /* */
117 /* inspectImage */
118 /* */
119 /********************************************************/
120 
121 /** \brief Apply read-only functor to every pixel in the image.
122 
123  This function can be used to collect statistics of the image etc.
124  The results must be stored in the functor, which serves as a return
125  value.
126  The function uses an accessor to access the pixel data.
127 
128  <b> Declarations:</b>
129 
130  pass arguments explicitly:
131  \code
132  namespace vigra {
133  template <class ImageIterator, class Accessor, class Functor>
134  void
135  inspectImage(ImageIterator upperleft, ImageIterator lowerright,
136  Accessor a, Functor & f)
137  }
138  \endcode
139 
140  use argument objects in conjunction with \ref ArgumentObjectFactories :
141  \code
142  namespace vigra {
143  template <class ImageIterator, class Accessor, class Functor>
144  void
145  inspectImage(triple<ImageIterator, ImageIterator, Accessor> img,
146  Functor & f)
147  }
148  \endcode
149 
150  <b> Usage:</b>
151 
152  <b>\#include</b> <vigra/inspectimage.hxx><br>
153  Namespace: vigra
154 
155  \code
156  // init functor
157  vigra::BImage img;
158 
159  vigra::FindMinMax<vigra::BImage::PixelType> minmax;
160 
161  vigra::inspectImage(srcImageRange(img), minmax);
162 
163  cout << "Min: " << minmax.min << " Max: " << minmax.max;
164 
165  \endcode
166 
167  <b> Required Interface:</b>
168 
169  \code
170  ConstImageIterator upperleft, lowerright;
171  ConstImageIterator::row_iterator ix = upperleft.rowIterator();
172 
173  Accessor accessor;
174  Functor functor;
175 
176  functor(accessor(ix)); // return not used
177  \endcode
178 
179 */
180 doxygen_overloaded_function(template <...> void inspectImage)
181 
182 template <class ImageIterator, class Accessor, class Functor>
183 void
184 inspectImage(ImageIterator upperleft, ImageIterator lowerright,
185  Accessor a, Functor & f)
186 {
187  int w = lowerright.x - upperleft.x;
188 
189  for(; upperleft.y<lowerright.y; ++upperleft.y)
190  {
191  inspectLine(upperleft.rowIterator(),
192  upperleft.rowIterator() + w, a, f);
193  }
194 }
195 
196 template <class ImageIterator, class Accessor, class Functor>
197 inline
198 void
199 inspectImage(triple<ImageIterator, ImageIterator, Accessor> img,
200  Functor & f)
201 {
202  inspectImage(img.first, img.second, img.third, f);
203 }
204 
205 namespace functor
206 {
207  template <class T> class UnaryAnalyser;
208 }
209 
210 template <class ImageIterator, class Accessor, class Functor>
211 inline
212 void
213 inspectImage(ImageIterator upperleft, ImageIterator lowerright,
214  Accessor a, functor::UnaryAnalyser<Functor> const & f)
215 {
216  inspectImage(upperleft, lowerright, a,
217  const_cast<functor::UnaryAnalyser<Functor> &>(f));
218 }
219 
220 template <class ImageIterator, class Accessor, class Functor>
221 inline
222 void
223 inspectImage(triple<ImageIterator, ImageIterator, Accessor> img,
224  functor::UnaryAnalyser<Functor> const & f)
225 {
226  inspectImage(img.first, img.second, img.third,
227  const_cast<functor::UnaryAnalyser<Functor> &>(f));
228 }
229 
230 /********************************************************/
231 /* */
232 /* inspectImageIf */
233 /* */
234 /********************************************************/
235 
236 /** \brief Apply read-only functor to every pixel in the ROI.
237 
238  This function can be used to collect statistics of the roi etc.
239  The functor is called whenever the return value of the mask's
240  accessor is not zero.
241  The results must be stored in the functor, which serves as a return
242  value.
243  Accessors are used to access the pixel and mask data.
244 
245  <b> Declarations:</b>
246 
247  pass arguments explicitly:
248  \code
249  namespace vigra {
250  template <class ImageIterator, class Accessor,
251  class MaskImageIterator, class MaskAccessor, class Functor>
252  void
253  inspectImageIf(ImageIterator upperleft, ImageIterator lowerright,
254  MaskImageIterator mask_upperleft, MaskAccessor ma,
255  Functor & f)
256  }
257  \endcode
258 
259 
260  use argument objects in conjunction with \ref ArgumentObjectFactories :
261  \code
262  namespace vigra {
263  template <class ImageIterator, class Accessor,
264  class MaskImageIterator, class MaskAccessor, class Functor>
265  void
266  inspectImageIf(triple<ImageIterator, ImageIterator, Accessor> img,
267  pair<MaskImageIterator, MaskAccessor> mask,
268  Functor & f)
269  }
270  \endcode
271 
272  <b> Usage:</b>
273 
274  <b>\#include</b> <vigra/inspectimage.hxx><br>
275  Namespace: vigra
276 
277  \code
278  vigra::BImage img(100, 100);
279  vigra::BImage mask(100, 100);
280 
281  // init functor
282  vigra::FindMinMax<vigra::BImage::PixelType> minmax;
283 
284  vigra::inspectImageIf(srcImageRange(img),
285  maskImage(mask), minmax);
286 
287  cout << "Min: " << minmax.min << " Max: " << minmax.max;
288 
289  \endcode
290 
291  <b> Required Interface:</b>
292 
293  \code
294  ConstImageIterator upperleft, lowerright;
295  MaskImageIterator mask_upperleft;
296  ConstImageIterator::row_iterator ix = upperleft.rowIterator();
297  MaskImageIterator::row_iterator mx = mask_upperleft.rowIterator();
298 
299  Accessor accessor;
300  MaskAccessor mask_accessor;
301 
302  Functor functor;
303 
304  if(mask_accessor(mx)) functor(accessor(ix));
305  \endcode
306 
307 */
308 doxygen_overloaded_function(template <...> void inspectImageIf)
309 
310 template <class ImageIterator, class Accessor,
311  class MaskImageIterator, class MaskAccessor, class Functor>
312 void
313 inspectImageIf(ImageIterator upperleft,
314  ImageIterator lowerright, Accessor a,
315  MaskImageIterator mask_upperleft, MaskAccessor ma,
316  Functor & f)
317 {
318  int w = lowerright.x - upperleft.x;
319 
320  for(; upperleft.y<lowerright.y; ++upperleft.y, ++mask_upperleft.y)
321  {
322  inspectLineIf(upperleft.rowIterator(),
323  upperleft.rowIterator() + w, a,
324  mask_upperleft.rowIterator(), ma, f);
325  }
326 }
327 
328 template <class ImageIterator, class Accessor,
329  class MaskImageIterator, class MaskAccessor, class Functor>
330 inline
331 void
332 inspectImageIf(triple<ImageIterator, ImageIterator, Accessor> img,
333  pair<MaskImageIterator, MaskAccessor> mask,
334  Functor & f)
335 {
336  inspectImageIf(img.first, img.second, img.third,
337  mask.first, mask.second, f);
338 }
339 
340 template <class ImageIterator, class Accessor,
341  class MaskImageIterator, class MaskAccessor, class Functor>
342 inline void
343 inspectImageIf(ImageIterator upperleft,
344  ImageIterator lowerright, Accessor a,
345  MaskImageIterator mask_upperleft, MaskAccessor ma,
346  functor::UnaryAnalyser<Functor> const & f)
347 {
348  inspectImageIf(upperleft, lowerright, a,
349  mask_upperleft, ma, const_cast<functor::UnaryAnalyser<Functor> &>(f));
350 }
351 
352 template <class ImageIterator, class Accessor,
353  class MaskImageIterator, class MaskAccessor, class Functor>
354 inline void
355 inspectImageIf(triple<ImageIterator, ImageIterator, Accessor> img,
356  pair<MaskImageIterator, MaskAccessor> mask,
357  functor::UnaryAnalyser<Functor> const & f)
358 {
359  inspectImageIf(img.first, img.second, img.third,
360  mask.first, mask.second, const_cast<functor::UnaryAnalyser<Functor> &>(f));
361 }
362 
363 /********************************************************/
364 /* */
365 /* inspectTwoImages */
366 /* */
367 /********************************************************/
368 
369 /** \brief Apply read-only functor to every pixel of both images.
370 
371  This function can be used to collect statistics for each region of a
372  labeled image, especially in conjunction with
373  the \ref ArrayOfRegionStatistics functor. The results must be
374  stored in the functor which serves as a return value.
375  Accessors are used to access the pixel data.
376 
377  <b> Declarations:</b>
378 
379  pass arguments explicitly:
380  \code
381  namespace vigra {
382  template <class ImageIterator1, class Accessor1,
383  class ImageIterator2, class Accessor2,
384  class Functor>
385  void
386  inspectTwoImages(ImageIterator1 upperleft1, ImageIterator1 lowerright1, Accessor1 a1,
387  ImageIterator2 upperleft2, Accessor2 a2,
388  Functor & f)
389  }
390  \endcode
391 
392 
393  use argument objects in conjunction with \ref ArgumentObjectFactories :
394  \code
395  namespace vigra {
396  template <class ImageIterator1, class Accessor1,
397  class ImageIterator2, class Accessor2,
398  class Functor>
399  void
400  inspectTwoImages(triple<ImageIterator1, ImageIterator1, Accessor1> img1,
401  pair<ImageIterator2, Accessor2> img2,
402  Functor & f)
403  }
404  \endcode
405 
406  <b> Usage:</b>
407 
408  <b>\#include</b> <vigra/inspectimage.hxx><br>
409  Namespace: vigra
410 
411  \code
412  vigra::BImage image1;
413  vigra::BImage image2;
414 
415  SomeStatisticsFunctor stats(...); // init functor
416 
417  vigra::inspectTwoImages(srcImageRange(image1), srcImage(image2),
418  stats);
419 
420 
421  \endcode
422 
423  <b> Required Interface:</b>
424 
425  \code
426  ImageIterator1 upperleft1, lowerright1;
427  ImageIterator2 upperleft2;
428  ImageIterator1::row_iterator ix1 = upperleft1.rowIterator();
429  ImageIterator2::row_iterator ix2 = upperleft2.rowIterator();
430 
431  Accessor1 accessor1;
432  Accessor2 accessor2;
433 
434  Functor functor;
435  functor(accessor1(ix1), accessor2(ix2)); // return not used
436  \endcode
437 
438 */
439 doxygen_overloaded_function(template <...> void inspectTwoImages)
440 
441 template <class ImageIterator1, class Accessor1,
442  class ImageIterator2, class Accessor2,
443  class Functor>
444 void
445 inspectTwoImages(ImageIterator1 upperleft1, ImageIterator1 lowerright1, Accessor1 a1,
446  ImageIterator2 upperleft2, Accessor2 a2,
447  Functor & f)
448 {
449  int w = lowerright1.x - upperleft1.x;
450 
451  for(; upperleft1.y<lowerright1.y; ++upperleft1.y, ++upperleft2.y)
452  {
453  inspectTwoLines(upperleft1.rowIterator(),
454  upperleft1.rowIterator() + w, a1,
455  upperleft2.rowIterator(), a2, f);
456  }
457 }
458 
459 template <class ImageIterator1, class Accessor1,
460  class ImageIterator2, class Accessor2,
461  class Functor>
462 inline
463 void
464 inspectTwoImages(triple<ImageIterator1, ImageIterator1, Accessor1> img1,
465  pair<ImageIterator2, Accessor2> img2,
466  Functor & f)
467 {
468  inspectTwoImages(img1.first, img1.second, img1.third,
469  img2.first, img2.second, f);
470 }
471 
472 template <class ImageIterator1, class Accessor1,
473  class ImageIterator2, class Accessor2,
474  class Functor>
475 inline void
476 inspectTwoImages(ImageIterator1 upperleft1, ImageIterator1 lowerright1, Accessor1 a1,
477  ImageIterator2 upperleft2, Accessor2 a2,
478  functor::UnaryAnalyser<Functor> const & f)
479 {
480  inspectTwoImages(upperleft1, lowerright1, a1,
481  upperleft2, a2, const_cast<functor::UnaryAnalyser<Functor> &>(f));
482 }
483 
484 template <class ImageIterator1, class Accessor1,
485  class ImageIterator2, class Accessor2,
486  class Functor>
487 inline
488 void
489 inspectTwoImages(triple<ImageIterator1, ImageIterator1, Accessor1> img1,
490  pair<ImageIterator2, Accessor2> img2,
491  functor::UnaryAnalyser<Functor> const & f)
492 {
493  inspectTwoImages(img1.first, img1.second, img1.third,
494  img2.first, img2.second, const_cast<functor::UnaryAnalyser<Functor> &>(f));
495 }
496 
497 /********************************************************/
498 /* */
499 /* inspectTwoImagesIf */
500 /* */
501 /********************************************************/
502 
503 /** \brief Apply read-only functor to those pixels of both images where
504  the mask image is non-zero.
505 
506  This function can be used to collect statistics for selected regions of a
507  labeled image, especially in conjunction with
508  the \ref ArrayOfRegionStatistics functor. The results must be
509  stored in the functor which serves as a return value.
510  Accessors are used to access the pixel data.
511 
512  <b> Declarations:</b>
513 
514  pass arguments explicitly:
515  \code
516  namespace vigra {
517  template <class ImageIterator1, class Accessor1,
518  class ImageIterator2, class Accessor2,
519  class MaskImageIterator, class MaskAccessor,
520  class Functor>
521  void
522  inspectTwoImagesIf(ImageIterator1 upperleft1, ImageIterator1 lowerright1, Accessor1 a1,
523  ImageIterator2 upperleft2, Accessor2 a2,
524  MaskImageIterator mupperleft, MaskAccessor mask,
525  Functor & f)
526  }
527  \endcode
528 
529 
530  use argument objects in conjunction with \ref ArgumentObjectFactories :
531  \code
532  namespace vigra {
533  template <class ImageIterator1, class Accessor1,
534  class ImageIterator2, class Accessor2,
535  class MaskImageIterator, class MaskAccessor,
536  class Functor>
537  void
538  inspectTwoImagesIf(triple<ImageIterator1, ImageIterator1, Accessor1> img1,
539  pair<ImageIterator2, Accessor2> img2,
540  pair<MaskImageIterator, MaskAccessor> mimg,
541  Functor & f)
542  }
543  \endcode
544 
545  <b> Usage:</b>
546 
547  <b>\#include</b> <vigra/inspectimage.hxx><br>
548  Namespace: vigra
549 
550  \code
551  vigra::BImage image1;
552  vigra::BImage image2;
553  vigra::BImage maskimage;
554 
555  SomeStatisticsFunctor stats(...); // init functor
556 
557  vigra::inspectTwoImagesIf(srcImageRange(image1), srcImage(image2),
558  srcImage(maskimage), region_stats);
559 
560  \endcode
561 
562  <b> Required Interface:</b>
563 
564  \code
565  ImageIterator1 upperleft1, lowerright1;
566  ImageIterator2 upperleft2;
567  MaskImageIterator upperleftm;
568  ImageIterator1::row_iterator ix1 = upperleft1.rowIterator();
569  ImageIterator2::row_iterator ix2 = upperleft2.rowIterator();
570  MaskImageIterator::row_iterator mx = mupperleft.rowIterator();
571 
572  Accessor1 accessor1;
573  Accessor2 accessor2;
574  MaskAccessor mask;
575 
576  Functor functor;
577  if(mask(mx))
578  functor(accessor1(ix1), accessor2(ix2));
579  \endcode
580 
581 */
582 doxygen_overloaded_function(template <...> void inspectTwoImagesIf)
583 
584 template <class ImageIterator1, class Accessor1,
585  class ImageIterator2, class Accessor2,
586  class MaskImageIterator, class MaskAccessor,
587  class Functor>
588 void
589 inspectTwoImagesIf(ImageIterator1 upperleft1, ImageIterator1 lowerright1, Accessor1 a1,
590  ImageIterator2 upperleft2, Accessor2 a2,
591  MaskImageIterator mupperleft, MaskAccessor mask,
592  Functor & f)
593 {
594  int w = lowerright1.x - upperleft1.x;
595 
596  for(; upperleft1.y<lowerright1.y; ++upperleft1.y, ++upperleft2.y, ++mupperleft.y)
597  {
598  inspectTwoLinesIf(upperleft1.rowIterator(),
599  upperleft1.rowIterator() + w, a1,
600  upperleft2.rowIterator(), a2,
601  mupperleft.rowIterator(), mask, f);
602  }
603 }
604 
605 template <class ImageIterator1, class Accessor1,
606  class ImageIterator2, class Accessor2,
607  class MaskImageIterator, class MaskAccessor,
608  class Functor>
609 inline
610 void
611 inspectTwoImagesIf(triple<ImageIterator1, ImageIterator1, Accessor1> img1,
612  pair<ImageIterator2, Accessor2> img2,
613  pair<MaskImageIterator, MaskAccessor> m,
614  Functor & f)
615 {
616  inspectTwoImagesIf(img1.first, img1.second, img1.third,
617  img2.first, img2.second,
618  m.first, m.second,
619  f);
620 }
621 
622 template <class ImageIterator1, class Accessor1,
623  class ImageIterator2, class Accessor2,
624  class MaskImageIterator, class MaskAccessor,
625  class Functor>
626 inline void
627 inspectTwoImagesIf(ImageIterator1 upperleft1, ImageIterator1 lowerright1, Accessor1 a1,
628  ImageIterator2 upperleft2, Accessor2 a2,
629  MaskImageIterator mupperleft, MaskAccessor mask,
630  functor::UnaryAnalyser<Functor> const & f)
631 {
632  inspectTwoImagesIf(upperleft1, lowerright1, a1,
633  upperleft2, a2,
634  mupperleft, mask,
635  const_cast<functor::UnaryAnalyser<Functor> &>(f));
636 }
637 
638 template <class ImageIterator1, class Accessor1,
639  class ImageIterator2, class Accessor2,
640  class MaskImageIterator, class MaskAccessor,
641  class Functor>
642 inline
643 void
644 inspectTwoImagesIf(triple<ImageIterator1, ImageIterator1, Accessor1> img1,
645  pair<ImageIterator2, Accessor2> img2,
646  pair<MaskImageIterator, MaskAccessor> m,
647  functor::UnaryAnalyser<Functor> const & f)
648 {
649  inspectTwoImagesIf(img1.first, img1.second, img1.third,
650  img2.first, img2.second,
651  m.first, m.second,
652  const_cast<functor::UnaryAnalyser<Functor> &>(f));
653 }
654 
655 //@}
656 
657 /** \addtogroup InspectFunctor Functors To Inspect Images
658  Functors which report image statistics
659 */
660 //@{
661 
662 /********************************************************/
663 /* */
664 /* FindMinMax */
665 /* */
666 /********************************************************/
667 
668 /** \brief Find the minimum and maximum pixel value in an image or ROI.
669 
670  In addition the size of the ROI is calculated.
671  These functors can also be used in conjunction with
672  \ref ArrayOfRegionStatistics to find the extremes of all regions in
673  a labeled image.
674 
675  <b> Traits defined:</b>
676 
677  <tt>FunctorTraits::isUnaryAnalyser</tt> is true (<tt>VigraTrueType</tt>)
678 
679  <b> Usage:</b>
680 
681  <b>\#include</b> <vigra/inspectimage.hxx><br>
682  Namespace: vigra
683 
684  \code
685  vigra::BImage img;
686 
687  vigra::FindMinMax<vigra::BImage::PixelType> minmax; // init functor
688 
689  vigra::inspectImage(srcImageRange(img), minmax);
690 
691  cout << "Min: " << minmax.min << " Max: " << minmax.max;
692 
693  \endcode
694 
695  <b> Required Interface:</b>
696 
697  \code
698  VALUETYPE v1, v2(v1);
699 
700  v1 < v2;
701  v1 = v2;
702  \endcode
703 
704 */
705 template <class VALUETYPE>
707 {
708  public:
709 
710  /** the functor's argument type
711  */
712  typedef VALUETYPE argument_type;
713 
714  /** the functor's result type
715  */
716  typedef VALUETYPE result_type;
717 
718  /** \deprecated use argument_type
719  */
720  typedef VALUETYPE value_type;
721 
722  /** init min and max
723  */
725  : min( NumericTraits<value_type>::max() ),
726  max( NumericTraits<value_type>::min() ),
727  count(0)
728  {}
729 
730  /** (re-)init functor (clear min, max)
731  */
732  void reset()
733  {
734  count = 0;
735  }
736 
737  /** update min and max
738  */
739  void operator()(argument_type const & v)
740  {
741  if(count)
742  {
743  if(v < min) min = v;
744  if(max < v) max = v;
745  }
746  else
747  {
748  min = v;
749  max = v;
750  }
751  ++count;
752  }
753 
754  /** update min and max with components of RGBValue<VALUETYPE>
755  */
757  {
758  operator()(v.red());
759  operator()(v.green());
760  operator()(v.blue());
761  }
762 
763  /** merge two statistics
764  */
765  void operator()(FindMinMax const & v)
766  {
767  if(v.count)
768  {
769  if(count)
770  {
771  if(v.min < min) min = v.min;
772  if((this->max) < v.max) max = v.max;
773  }
774  else
775  {
776  min = v.min;
777  max = v.max;
778  }
779  }
780  count += v.count;
781  }
782 
783  /** the current min
784  */
785  VALUETYPE min;
786 
787  /** the current max
788  */
789  VALUETYPE max;
790 
791  /** the number of values processed so far
792  */
793  unsigned int count;
794 
795 };
796 
797 template <class VALUETYPE>
798 class FunctorTraits<FindMinMax<VALUETYPE> >
799 : public FunctorTraitsBase<FindMinMax<VALUETYPE> >
800 {
801  public:
802  typedef VigraTrueType isUnaryAnalyser;
803 };
804 
805 /********************************************************/
806 /* */
807 /* FindSum */
808 /* */
809 /********************************************************/
810 
811 /** \brief Find the sum of the pixel values in an image or ROI.
812 
813  This Functor can also be used in conjunction with
814  \ref ArrayOfRegionStatistics to find the sum of all regions in
815  a labeled image, and with the reduce mode of transformMultiArray().
816 
817  <b> Traits defined:</b>
818 
819  <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitializer</tt>
820  are true (<tt>VigraTrueType</tt>)
821 
822  <b> Usage:</b>
823 
824  <b>\#include</b> <vigra/inspectimage.hxx><br>
825  Namespace: vigra
826 
827  \code
828  vigra::BImage img;
829 
830  vigra::FindSum<vigra::BImage::PixelType> sum; // init functor
831 
832  vigra::inspectImage(srcImageRange(img), sum);
833 
834  cout << "Sum: " << sum();
835 
836  \endcode
837 
838  <b> Required Interface:</b>
839 
840  \code
841  VALUETYPE v1, v2(v1);
842 
843  v1 += v2;
844  \endcode
845 
846 */
847 template <class VALUETYPE>
848 class FindSum
849 : public UnaryReduceFunctorTag
850 {
851  public:
852 
853  /** the functor's argument type
854  */
855  typedef VALUETYPE argument_type;
856 
857  /** the functor's result type
858  */
859  typedef typename NumericTraits<VALUETYPE>::Promote result_type;
860 
861  /** init sum
862  */
864  : sum_(NumericTraits<result_type>::zero())
865  {}
866 
867  /** (re-)init sum
868  */
869  void reset()
870  {
871  sum_ = NumericTraits<result_type>::zero();
872  }
873 
874  /** update sum
875  */
876  void operator()(argument_type const & v)
877  {
878  sum_ += v;
879  }
880 
881  /** merge two statistics
882  */
883  void operator()(FindSum const & v)
884  {
885  sum_ += v.sum_;
886  }
887 
888  /** return current sum
889  */
890  result_type sum() const
891  {
892  return sum_;
893  }
894 
895  /** return current sum
896  */
898  {
899  return sum_;
900  }
901 
902  result_type sum_;
903 };
904 
905 
906 
907 /********************************************************/
908 /* */
909 /* FindAverage */
910 /* */
911 /********************************************************/
912 
913 /** \brief Find the average pixel value in an image or ROI.
914 
915  In addition the size of the ROI is calculated.
916  This Functor can also be used in conjunction with
917  \ref ArrayOfRegionStatistics to find the average of all regions in
918  a labeled image.
919 
920  <b> Traits defined:</b>
921 
922  <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitializer</tt>
923  are true (<tt>VigraTrueType</tt>)
924 
925  <b> Usage:</b>
926 
927  <b>\#include</b> <vigra/inspectimage.hxx><br>
928  Namespace: vigra
929 
930  \code
931  vigra::BImage img;
932 
933  vigra::FindAverage<vigra::BImage::PixelType> average; // init functor
934 
935  vigra::inspectImage(srcImageRange(img), average);
936 
937  cout << "Average: " << average();
938 
939  \endcode
940 
941  <b> Required Interface:</b>
942 
943  \code
944  VALUETYPE v1, v2(v1);
945  double d;
946 
947  v1 += v2;
948  v1 / d;
949  \endcode
950 
951 */
952 template <class VALUETYPE>
954 {
955  public:
956 
957  /** the functor's argument type
958  */
959  typedef VALUETYPE argument_type;
960 
961  /** the functor's first argument type (for calls with a weight)
962  */
963  typedef VALUETYPE first_argument_type;
964 
965  /** the functor's second argument type (for calls with a weight)
966  */
967  typedef double second_argument_type;
968 
969  /** the functor's result type
970  */
971  typedef typename NumericTraits<VALUETYPE>::RealPromote result_type;
972 
973  /** \deprecated use argument_type and result_type
974  */
975  typedef typename NumericTraits<VALUETYPE>::RealPromote value_type;
976 
977  /** init average
978  */
980  : sum_(NumericTraits<result_type>::zero()), count_(0)
981  {}
982 
983  /** (re-)init average
984  */
985  void reset()
986  {
987  count_ = 0;
988  sum_ = NumericTraits<result_type>::zero();
989  }
990 
991  /** update average
992  */
993  void operator()(argument_type const & v)
994  {
995  sum_ += v;
996  ++count_;
997  }
998 
999  /** update average, using weighted input.
1000  * <tt>stats(value, 1.0)</tt> is equivalent to the unweighted
1001  * call <tt>stats(value)</tt>, and <tt>stats(value, 2.0)</tt>
1002  * is equivalent to two unweighted calls.
1003  */
1005  {
1006  sum_ += v * weight;
1007  count_ += weight;
1008  }
1009 
1010  /** merge two statistics
1011  */
1012  void operator()(FindAverage const & v)
1013  {
1014  sum_ += v.sum_;
1015  count_ += v.count_;
1016  }
1017 
1018  /** return number of values (sum of weights) seen so far
1019  */
1020  double count() const
1021  {
1022  return count_;
1023  }
1024 
1025  /** return current average
1026  */
1028  {
1029  return sum_ / (double)count_;
1030  }
1031 
1032  /** return current average
1033  */
1035  {
1036  return sum_ / (double)count_;
1037  }
1038 
1039  result_type sum_;
1040  double count_;
1041 };
1042 
1043 template <class VALUETYPE>
1044 class FunctorTraits<FindAverage<VALUETYPE> >
1045 : public FunctorTraitsBase<FindAverage<VALUETYPE> >
1046 {
1047  public:
1048  typedef VigraTrueType isInitializer;
1049  typedef VigraTrueType isUnaryAnalyser;
1050 };
1051 
1052 /********************************************************/
1053 /* */
1054 /* FindAverageAndVariance */
1055 /* */
1056 /********************************************************/
1057 
1058 /** \brief Find the average pixel value and its variance in an image or ROI.
1059 
1060  This Functor uses West's algorithm to accumulate highly accurate values for
1061  the mean and the sum of squared differences of all values seen so far (the
1062  naive incremental algorithm for the computation of the sum of squares
1063  produces large round-off errors when the mean is much larger than the
1064  standard deviation of the data.) This Functor can also be used in
1065  conjunction with \ref ArrayOfRegionStatistics to find the statistics of all
1066  regions in a labeled image.
1067 
1068  <b> Traits defined:</b>
1069 
1070  <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitializer</tt>
1071  are true (<tt>VigraTrueType</tt>)
1072 
1073  <b> Usage:</b>
1074 
1075  <b>\#include</b> <vigra/inspectimage.hxx><br>
1076  Namespace: vigra
1077 
1078  \code
1079  vigra::BImage img;
1080 
1081  vigra::FindAverageAndVariance<vigra::BImage::PixelType> averageAndVariance; // init functor
1082 
1083  vigra::inspectImage(srcImageRange(img), averageAndVariance);
1084 
1085  cout << "Average: " << averageAndVariance.average() << "\n";
1086  cout << "Standard deviation: " << sqrt(averageAndVariance.variance()) << "\n";
1087 
1088  \endcode
1089 
1090  <b> Required Interface:</b>
1091 
1092  \code
1093  VALUETYPE v1, v2(v1);
1094  double d;
1095 
1096  v1 += v2;
1097  v1 + v2;
1098  v1 - v2;
1099  v1 * v2;
1100  v1 / d;
1101  d * v1;
1102  \endcode
1103 
1104 */
1105 template <class VALUETYPE>
1107 {
1108  public:
1109 
1110  /** the functor's argument type
1111  */
1112  typedef VALUETYPE argument_type;
1113 
1114  /** the functor's first argument type (for calls with a weight)
1115  */
1116  typedef VALUETYPE first_argument_type;
1117 
1118  /** the functor's second argument type (for calls with a weight)
1119  */
1120  typedef double second_argument_type;
1121 
1122  /** the functor's result type
1123  */
1124  typedef typename NumericTraits<VALUETYPE>::RealPromote result_type;
1125 
1126  /** \deprecated use argument_type and result_type
1127  */
1128  typedef typename NumericTraits<VALUETYPE>::RealPromote value_type;
1129 
1130  /** init average
1131  */
1133  : mean_(NumericTraits<result_type>::zero()),
1134  sumOfSquaredDifferences_(NumericTraits<result_type>::zero()),
1135  count_(0.0)
1136  {}
1137 
1138  /** (re-)init average and variance
1139  */
1140  void reset()
1141  {
1142  count_ = 0.0;
1143  mean_ = NumericTraits<result_type>::zero();
1144  sumOfSquaredDifferences_ = NumericTraits<result_type>::zero();
1145  }
1146 
1147  /** update average and variance
1148  */
1149  void operator()(argument_type const & v)
1150  {
1151  ++count_;
1152  result_type t1 = v - mean_;
1153  result_type t2 = t1 / count_;
1154  mean_ += t2;
1155  sumOfSquaredDifferences_ += (count_-1.0)*t1*t2;
1156  }
1157 
1158  /** update average and variance, using weighted input.
1159  * <tt>stats(value, 1.0)</tt> is equivalent to the unweighted
1160  * call <tt>stats(value)</tt>, and <tt>stats(value, 2.0)</tt>
1161  * is equivalent to two unweighted calls.
1162  */
1164  {
1165  count_ += weight;
1166  result_type t1 = v - mean_;
1167  result_type t2 = t1 * weight / count_;
1168  mean_ += t2;
1169 
1170  //sumOfSquaredDifferences_ += (count_ - weight)*t1*t2;
1171 
1172  if(count_ > weight)
1173  sumOfSquaredDifferences_ +=
1174  (t1 * t1 * weight / count_) * (count_ - weight );
1175  }
1176 
1177  /** merge two statistics
1178  */
1180  {
1181  double newCount = count_ + v.count_;
1182  sumOfSquaredDifferences_ += v.sumOfSquaredDifferences_ +
1183  count_ / newCount * v.count_ * (mean_ - v.mean_) * (mean_ - v.mean_);
1184  mean_ = (count_ * mean_ + v.count_ * v.mean_) / newCount;
1185  count_ += v.count_;
1186  }
1187 
1188  /** return number of values (sum of weights) seen so far
1189  */
1190  unsigned int count() const
1191  {
1192  return (unsigned int)count_;
1193  }
1194 
1195  /** return current average
1196  */
1198  {
1199  return mean_;
1200  }
1201 
1202  /** return current variance.
1203  If <tt>unbiased = true</tt>, the sum of squared differences
1204  is divided by <tt>count()-1</tt> instead of just <tt>count()</tt>.
1205  */
1206  result_type variance(bool unbiased = false) const
1207  {
1208  return unbiased
1209  ? sumOfSquaredDifferences_ / (count_ - 1.0)
1210  : sumOfSquaredDifferences_ / count_;
1211  }
1212 
1213  /** return current variance. calls <tt>variance()</tt>.
1214  */
1216  {
1217  return variance();
1218  }
1219 
1220  result_type mean_, sumOfSquaredDifferences_;
1221  double count_;
1222 };
1223 
1224 template <class VALUETYPE>
1225 class FunctorTraits<FindAverageAndVariance<VALUETYPE> >
1226 : public FunctorTraitsBase<FindAverageAndVariance<VALUETYPE> >
1227 {
1228  public:
1229  typedef VigraTrueType isInitializer;
1230  typedef VigraTrueType isUnaryAnalyser;
1231 };
1232 
1233 /********************************************************/
1234 /* */
1235 /* FindROISize */
1236 /* */
1237 /********************************************************/
1238 
1239 /** \brief Calculate the size of an ROI in an image.
1240 
1241  This Functor is often used in conjunction with
1242  \ref ArrayOfRegionStatistics to find the sizes of all regions in
1243  a labeled image.
1244 
1245  <b> Traits defined:</b>
1246 
1247  <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitializer</tt>
1248  are true (<tt>VigraTrueType</tt>)
1249 
1250  <b> Usage:</b>
1251 
1252  <b>\#include</b> <vigra/inspectimage.hxx><br>
1253  Namespace: vigra
1254 
1255  \code
1256  vigra::BImage img, mask;
1257 
1258  vigra::FindROISize<vigra::BImage::PixelType> roisize; // init functor
1259 
1260  vigra::inspectImageIf(srcImageRange(img), srcImage(mask), roisize);
1261 
1262  cout << "Size of ROI: " << roisize.count;
1263 
1264  \endcode
1265 
1266 */
1267 template <class VALUETYPE>
1269 {
1270  public:
1271 
1272  /** the functor's argument type
1273  */
1274  typedef VALUETYPE argument_type;
1275 
1276  /** the functor's result type
1277  */
1278  typedef unsigned int result_type;
1279 
1280  /** \deprecated use argument_type and result_type
1281  */
1282  typedef VALUETYPE value_type;
1283 
1284  /** init counter to 0
1285  */
1287  : count(0)
1288  {}
1289 
1290  /** (re-)init ROI size with 0
1291  */
1292  void reset()
1293  {
1294  count = 0;
1295  }
1296 
1297  /** update counter
1298  */
1300  {
1301  ++count;
1302  }
1303 
1304  /** return current size
1305  */
1307  {
1308  return count;
1309  }
1310 
1311  /** return current size
1312  */
1314  {
1315  return count;
1316  }
1317 
1318  /** merge two statistics
1319  */
1320  void operator()(FindROISize const & o)
1321  {
1322  count += o.count;
1323  }
1324 
1325  /** the current counter
1326  */
1328 
1329 };
1330 
1331 template <class VALUETYPE>
1332 class FunctorTraits<FindROISize<VALUETYPE> >
1333 : public FunctorTraitsBase<FindROISize<VALUETYPE> >
1334 {
1335  public:
1336  typedef VigraTrueType isInitializer;
1337  typedef VigraTrueType isUnaryAnalyser;
1338 };
1339 
1340 /********************************************************/
1341 /* */
1342 /* FindBoundingRectangle */
1343 /* */
1344 /********************************************************/
1345 
1346 /** \brief Calculate the bounding rectangle of an ROI in an image.
1347 
1348  As always in VIGRA, <TT>roiRect.lowerRight</TT> is <em> just outside the rectangle</em>.
1349  That is, the last pixel actually in the rectangle is <TT>roiRect.lowerRight - Diff2D(1,1)</TT>.
1350  This Functor is often used in conjunction with
1351  \ref ArrayOfRegionStatistics to find the bounding rectangles
1352  of all regions in a labeled image.
1353 
1354  <b> Traits defined:</b>
1355 
1356  <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitializer</tt>
1357  are true (<tt>VigraTrueType</tt>)
1358 
1359  <b> Usage:</b>
1360 
1361  <b>\#include</b> <vigra/inspectimage.hxx><br>
1362  Namespace: vigra
1363 
1364  \code
1365  vigra::BImage img, mask;
1366  ...
1367 
1368  vigra::FindBoundingRectangle roiRect; // init functor
1369 
1370  // Diff2D is used as the iterator for the source image. This
1371  // simulates an image where each pixel value equals that pixel's
1372  // coordinates. Tha image 'mask' determines the ROI.
1373  vigra::inspectImageIf(srcIterRange(Diff2D(0,0), (Diff2D)img.size()),
1374  srcImage(mask), roiRect);
1375 
1376  cout << "Upper left of ROI: " <<
1377  roiRect.upperLeft.x << ", " << roiRect.upperLeft.y << endl;
1378  cout << "Lower right of ROI: " <<
1379  roiRect.lowerRight.x << ", " << roiRect.lowerRight.y << endl;
1380 
1381  \endcode
1382 
1383 */
1385 {
1386  public:
1387 
1388  /** the functor's argument type
1389  */
1391 
1392  /** the functors result type
1393  */
1395 
1396  /** \deprecated use argument_type
1397  */
1399 
1400  /** Upper left of the region as seen so far
1401  */
1403 
1404  /** Lower right of the region as seen so far
1405  */
1407 
1408  /** are the functors contents valid ?
1409  */
1410  bool valid;
1411 
1412  /** init rectangle to invalid values
1413  */
1415  : valid(false)
1416  {}
1417 
1418  /** (re-)init functor to find other bounds
1419  */
1420  void reset()
1421  {
1422  valid = false;
1423  }
1424 
1425  /** update rectangle by including the coordinate coord
1426  */
1427  void operator()(argument_type const & coord)
1428  {
1429  if(!valid)
1430  {
1431  upperLeft = Point2D(coord);
1432  lowerRight = Point2D(coord + Diff2D(1,1));
1433  valid = true;
1434  }
1435  else
1436  {
1437  upperLeft.x = std::min(upperLeft.x, coord.x);
1438  upperLeft.y = std::min(upperLeft.y, coord.y);
1439  lowerRight.x = std::max(lowerRight.x, coord.x + 1);
1440  lowerRight.y = std::max(lowerRight.y, coord.y + 1);
1441  }
1442  }
1443 
1444  /** update rectangle by merging it with another rectangle
1445  */
1446  void operator()(FindBoundingRectangle const & otherRegion)
1447  {
1448  if(!valid)
1449  {
1450  upperLeft = otherRegion.upperLeft;
1451  lowerRight = otherRegion.lowerRight;
1452  valid = otherRegion.valid;
1453  }
1454  else if(otherRegion.valid)
1455  {
1456  upperLeft.x = std::min(upperLeft.x, otherRegion.upperLeft.x);
1457  upperLeft.y = std::min(upperLeft.y, otherRegion.upperLeft.y);
1458  lowerRight.x = std::max(lowerRight.x, otherRegion.lowerRight.x);
1459  lowerRight.y = std::max(lowerRight.y, otherRegion.lowerRight.y);
1460  }
1461  }
1462 
1463  /** Get size of current rectangle.
1464  */
1465  Size2D size() const
1466  {
1467  return lowerRight - upperLeft;
1468  }
1469 
1470  /** Get current rectangle. <TT>result_type::first</TT> is the upper
1471  left corner of the rectangle, <TT>result_type::second</TT>
1472  the lower right.
1473  */
1475  {
1476  return result_type(upperLeft, lowerRight);
1477  }
1478 };
1479 
1480 template <>
1481 class FunctorTraits<FindBoundingRectangle>
1482 : public FunctorTraitsBase<FindBoundingRectangle>
1483 {
1484  public:
1485  typedef VigraTrueType isInitializer;
1486  typedef VigraTrueType isUnaryAnalyser;
1487 };
1488 
1489 /********************************************************/
1490 /* */
1491 /* LastValueFunctor */
1492 /* */
1493 /********************************************************/
1494 
1495 /** \brief Stores and returns the last value it has seen.
1496 
1497  This Functor is best used in conjunction with
1498  \ref ArrayOfRegionStatistics to realize a look-up table.
1499 
1500  <b> Traits defined:</b>
1501 
1502  <tt>FunctorTraits::isUnaryAnalyser</tt> and <tt>FunctorTraits::isInitializer</tt>
1503  are true (<tt>VigraTrueType</tt>)
1504 
1505  <b> Usage:</b>
1506 
1507  <b>\#include</b> <vigra/inspectimage.hxx><br>
1508  Namespace: vigra
1509 
1510  \code
1511  vigra::BImage img;
1512 
1513  vigra::ArrayOfRegionStatistics<LastValueFunctor<unsigned char> > lut(255);
1514 
1515  for(int i=0; i<256; ++i)
1516  {
1517  lut[i] = ...; // init look-up table
1518  }
1519 
1520  vigra::transformImage(srcImageRange(img), destImage(img), lut);
1521 
1522  \endcode
1523 
1524 */
1525 template <class VALUETYPE>
1527 {
1528  public:
1529 
1530  /** the functor's argument type
1531  */
1532  typedef VALUETYPE argument_type;
1533 
1534  /** the functor's result type
1535  */
1536  typedef VALUETYPE result_type;
1537 
1538  /** \deprecated use argument_type and result_type
1539  */
1540  typedef VALUETYPE value_type;
1541 
1542  /** default construction of value (i.e. builtin types will be set to zero)
1543  */
1545  : value(initial)
1546  {}
1547 
1548  /** replace value
1549  */
1550  void operator=(argument_type const & v) { value = v; }
1551 
1552  /** reset to initial value (the same as after default construction)
1553  */
1554  void reset() { value = VALUETYPE(); }
1555 
1556  /** replace value
1557  */
1558  void operator()(argument_type const & v) { value = v; }
1559 
1560  /** return current value
1561  */
1562  result_type const & operator()() const { return value; }
1563 
1564  /** the current value
1565  */
1566  VALUETYPE value;
1567 
1568 };
1569 
1570 template <class VALUETYPE>
1571 class FunctorTraits<LastValueFunctor<VALUETYPE> >
1572 : public FunctorTraitsBase<LastValueFunctor<VALUETYPE> >
1573 {
1574  public:
1575  typedef VigraTrueType isInitializer;
1576  typedef VigraTrueType isUnaryAnalyser;
1577 };
1578 
1579 /********************************************************/
1580 /* */
1581 /* ReduceFunctor */
1582 /* */
1583 /********************************************************/
1584 
1585 /** \brief Apply a functor to reduce the dimensionality of an array.
1586 
1587  This functor can be used to emulate the <tt>reduce</tt> standard function of
1588  functional programming using <tt>std::for_each()</tt> or <tt>inspectImage()</tt>
1589  and similar functions. This functor is initialized with a functor encoding
1590  the expression to be applied, and an accumulator storing the current state
1591  of the reduction. For each element of the array, the embedded functor is called
1592  with the accumulator and the current element(s) of the array. The result
1593  of the reduction is available by calling <tt>reduceFunctor()</tt>.
1594 
1595  <b> Traits defined:</b>
1596 
1597  <tt>FunctorTraits::isUnaryAnalyser</tt>, <tt>FunctorTraits::isBinaryAnalyser</tt>
1598  and <tt>FunctorTraits::isInitializer</tt>
1599  are true (<tt>VigraTrueType</tt>)
1600 
1601  <b> Usage:</b>
1602 
1603  <b>\#include</b> <vigra/inspectimage.hxx><br>
1604  Namespace: vigra
1605 
1606  \code
1607  vigra::BImage img;
1608  ... // fill the image
1609 
1610  // create a functor to sum the elements of the image
1611  vigra::ReduceFunctor<std::plus<int>, int> sumElements(std::plus<int>, 0);
1612 
1613  vigra::inspectImage(srcImageRange(img), sumElements);
1614 
1615  cout << "The sum of the elements " << sumElements() << endl;
1616 
1617  \endcode
1618 
1619  <b> Required Interface:</b>
1620 
1621  \code
1622  FUNCTOR f;
1623  VALUETYPE accumulator, current1, current2;
1624 
1625  f(accumulator, current1); // for inspectImage()
1626  f(accumulator, current1, current2); // for inspectTwoImages()
1627  \endcode
1628 */
1629 template <class FUNCTOR, class VALUETYPE>
1631 {
1632  FUNCTOR f_;
1633  VALUETYPE start_, accumulator_;
1634  public:
1635 
1636  /** the functor's argument type
1637  when used as a unary inspector.
1638  (This is not strictly correct since the argument type
1639  is actually a template parameter.)
1640  */
1641  typedef VALUETYPE argument_type;
1642 
1643  /** the functor's first argument type
1644  when used as a binary inspector.
1645  (This is not strictly correct since the argument type
1646  is actually a template parameter.)
1647  */
1648  typedef VALUETYPE first_argument_type;
1649 
1650  /** the functor's second argument type
1651  when used as a binary inspector.
1652  (This is not strictly correct since the argument type
1653  is actually a template parameter.)
1654  */
1655  typedef VALUETYPE second_argument_type;
1656 
1657  /** the functor's result type
1658  */
1659  typedef VALUETYPE result_type;
1660 
1661  /** create with the given functor and initial value \a initial
1662  for the accumulator.
1663  */
1664  ReduceFunctor(FUNCTOR const & f, VALUETYPE const & initial)
1665  : f_(f),
1666  start_(initial),
1667  accumulator_(initial)
1668  {}
1669 
1670  /** Reset accumulator to the initial value.
1671  */
1672  void reset()
1673  { accumulator_ = start_; }
1674 
1675  /** Use binary functor to connect given value with the accumulator.
1676  The accumulator is used as the first argument, the value \a v
1677  as the second.
1678  */
1679  template <class T>
1680  void operator()(T const & v)
1681  {
1682  accumulator_ = f_(accumulator_, v);
1683  }
1684 
1685  /** Use ternary functor to connect given values with accumulator.
1686  The accumulator is used as the first argument, the values \a v1
1687  ans \a v2 as the second and third.
1688  */
1689  template <class T1, class T2>
1690  void operator()(T1 const & v1, T2 const & v2)
1691  {
1692  accumulator_ = f_(accumulator_, v1, v2);
1693  }
1694 
1695  /** return current value
1696  */
1697  result_type const & operator()() const
1698  { return accumulator_; }
1699 };
1700 
1701 template <class FUNCTOR, class VALUETYPE>
1702 ReduceFunctor<FUNCTOR, VALUETYPE>
1703 reduceFunctor(FUNCTOR const & f, VALUETYPE const & initial)
1704 {
1705  return ReduceFunctor<FUNCTOR, VALUETYPE>(f, initial);
1706 }
1707 
1708 template <class FUNCTOR, class VALUETYPE>
1709 class FunctorTraits<ReduceFunctor<FUNCTOR, VALUETYPE> >
1710 : public FunctorTraitsBase<ReduceFunctor<FUNCTOR, VALUETYPE> >
1711 {
1712  public:
1713  typedef VigraTrueType isInitializer;
1714  typedef VigraTrueType isUnaryAnalyser;
1715  typedef VigraTrueType isBinaryAnalyser;
1716 };
1717 
1718 /********************************************************/
1719 /* */
1720 /* ArrayOfRegionStatistics */
1721 /* */
1722 /********************************************************/
1723 
1724 /** \brief Calculate statistics for all regions of a labeled image.
1725 
1726  This Functor encapsulates an array of statistics functors, one
1727  for each label, and selects the one to be updated according to the
1728  pixel's label.
1729 
1730  <b> Traits defined:</b>
1731 
1732  <tt>FunctorTraits::isBinaryAnalyser</tt> and <tt>FunctorTraits::isUnaryFunctor</tt>
1733  are true (<tt>VigraTrueType</tt>)
1734 
1735  <b> Usage:</b>
1736 
1737  <b>\#include</b> <vigra/inspectimage.hxx><br>
1738  Namespace: vigra
1739 
1740  \code
1741  vigra::BImage img;
1742  vigra::IImage labels;
1743  int max_label;
1744  ...
1745 
1746  // init functor as an array of 'max_label' FindMinMax-Functors
1747  vigra::ArrayOfRegionStatistics<vigra::FindMinMax<vigra::BImage::PixelType> >
1748  minmax(max_label);
1749 
1750  vigra::inspectTwoImages(srcImageRange(img), srcImage(labels), minmax);
1751 
1752  for(int i=0; i<= max_label; ++i)
1753  {
1754  cout << "Max gray level of region " << i << ": "
1755  << minmax.region[i].max << endl;
1756  }
1757 
1758  // init functor as an array of 'max_label' FindAverage-Functors
1759  vigra::ArrayOfRegionStatistics<vigra::FindAverage<vigra::BImage::PixelType> >
1760  average(max_label);
1761 
1762  vigra::inspectTwoImages(srcImageRange(img), srcImage(labels), average);
1763 
1764  // write back the average of each region into the original image
1765  vigra::transformImage(srcImageRange(labels), destImage(img), average);
1766 
1767  \endcode
1768 
1769  <b> Required Interface:</b>
1770 
1771  \code
1772  RegionStatistics region;
1773  RegionStatistics::argument_type a;
1774  RegionStatistics::result_type r;
1775 
1776  region(a); // update statistics
1777  r = region(); // return statistics
1778 
1779  \endcode
1780 */
1781 template <class RegionStatistics, class LabelType = int>
1783 {
1784  typedef std::vector<RegionStatistics> RegionArray;
1785 
1786  public:
1787  /** argument type of the contained statistics object
1788  becomes first argument of the analyser
1789  */
1790  typedef typename RegionStatistics::argument_type first_argument_type;
1791 
1792  /** label type is used to determine the region to be updated
1793  */
1794  typedef LabelType second_argument_type;
1795 
1796  /** label type is also used to determine the region to be
1797  returned by the 1 argument operator()
1798  */
1799  typedef LabelType argument_type;
1800 
1801  /** result type of the contained statistics object
1802  becomes result type of the analyser
1803  */
1804  typedef typename RegionStatistics::result_type result_type;
1805 
1806  /** the value type of the array: the contained statistics object.
1807  <b>Note:</b> this definition was different in older
1808  VIGRA versions. The old definition was wrong.
1809  */
1810  typedef RegionStatistics value_type;
1811 
1812  /** the array's reference type
1813  */
1814  typedef RegionStatistics & reference;
1815 
1816  /** the array's const reference type
1817  */
1818  typedef RegionStatistics const & const_reference;
1819 
1820  /** type to iterate over the statistics array
1821  */
1822  typedef typename RegionArray::iterator iterator;
1823 
1824  /** type to iterate over a const statistics array
1825  */
1826  typedef typename RegionArray::const_iterator const_iterator;
1827 
1828  /** init array of RegionStatistics with default size 0.
1829  */
1831  {}
1832 
1833  /** init array of RegionStatistics with index domain
1834  0...max_region_label.
1835  */
1836  ArrayOfRegionStatistics(unsigned int max_region_label)
1837  : regions(max_region_label+1)
1838  {}
1839 
1840  /** resize array to new index domain 0...max_region_label.
1841  All bin are re-initialized.
1842  */
1843  void resize(unsigned int max_region_label)
1844  {
1845  RegionArray newRegions(max_region_label+1);
1846  regions.swap(newRegions);
1847  }
1848 
1849  /** reset the contained functors to their initial state.
1850  */
1851  void reset()
1852  {
1853  RegionArray newRegions(regions.size());
1854  regions.swap(newRegions);
1855  }
1856 
1857  /** update regions statistics for region <TT>label</TT>. The label type
1858  is converted to <TT>unsigned int</TT>.
1859  */
1861  regions[static_cast<unsigned int>(label)](v);
1862  }
1863 
1864  /** merge second region into first
1865  */
1866  void merge(argument_type label1, argument_type label2) {
1867  regions[static_cast<unsigned int>(label1)](regions[static_cast<unsigned int>(label2)]);
1868  }
1869 
1870  /** ask for maximal index (label) allowed
1871  */
1872  unsigned int maxRegionLabel() const
1873  { return size() - 1; }
1874 
1875  /** ask for array size (i.e. maxRegionLabel() + 1)
1876  */
1877  unsigned int size() const
1878  { return regions.size(); }
1879 
1880  /** access the statistics for a region via its label. The label type
1881  is converted to <TT>unsigned int</TT>.
1882  */
1884  { return regions[static_cast<unsigned int>(label)](); }
1885 
1886  /** read the statistics functor for a region via its label
1887  */
1889  { return regions[static_cast<unsigned int>(label)]; }
1890 
1891  /** access the statistics functor for a region via its label
1892  */
1894  { return regions[static_cast<unsigned int>(label)]; }
1895 
1896  /** iterator to the begin of the region array
1897  */
1899  { return regions.begin(); }
1900 
1901  /** const iterator to the begin of the region array
1902  */
1904  { return regions.begin(); }
1905 
1906  /** iterator to the end of the region array
1907  */
1909  { return regions.end(); }
1910 
1911  /** const iterator to the end of the region array
1912  */
1914  { return regions.end(); }
1915 
1916  std::vector<RegionStatistics> regions;
1917 };
1918 
1919 template <class RegionStatistics, class LabelType>
1920 class FunctorTraits<ArrayOfRegionStatistics<RegionStatistics, LabelType> >
1921 : public FunctorTraitsBase<ArrayOfRegionStatistics<RegionStatistics, LabelType> >
1922 {
1923  public:
1924  typedef VigraTrueType isUnaryFunctor;
1925  typedef VigraTrueType isBinaryAnalyser;
1926 };
1927 
1928 //@}
1929 
1930 } // namespace vigra
1931 
1932 #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.8.0 (Wed Sep 26 2012)