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