vigra - vigra/labelvolume.hxx Source File

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

labelvolume.hxx |

1 /************************************************************************/
2 /* */
3 /* Copyright 2006-2007 by F. Heinrich, B. Seppke, 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 #ifndef VIGRA_LABELVOLUME_HXX
37 #define VIGRA_LABELVOLUME_HXX
38
39
40 #include "voxelneighborhood.hxx"
41 #include "multi_array.hxx"
42 #include "union_find.hxx"
43
44 namespace vigra{
45
46 /** \addtogroup Labeling Connected Components Labeling
47 The 3-dimensional connected components algorithms may use either 6 or 26 connectivity.
48 By means of a functor the merge criterion can be defined arbitrarily.
49 */
50 //@{
51
52 /********************************************************/
53 /* */
54 /* labelVolume */
55 /* */
56 /********************************************************/
57
58 /** \brief Find the connected components of a segmented volume.
59
60 Connected components are defined as regions with uniform voxel
61 values. Thus, <TT>T1</TT> either must be equality comparable,
62 or an EqualityFunctor must be provided explicitly that realizes
63 the desired equivalence predicate. The destination's value type
64 <tt>T2</tt> should be large enough to hold the labels
65 without overflow. Region numbers will be a consecutive sequence
66 starting with one and ending with the region number returned by
67 the function (inclusive).
68
69 Return: the number of regions found (= largest region label)
70
71 See \ref labelMultiArray() for a dimension-independent implementation of
72 connected components labelling.
73
74 <b> Declarations:</b>
75
76 pass 3D array views:
77 \code
78 namespace vigra {
79 template <class T1, class S1,
80 class T2, class S2,
81 class Neighborhood3D,
82 class EqualityFunctor = std::equal_to<T1> >
83 unsigned int
84 labelVolume(MultiArrayView<3, T1, S1> const & source,
85 MultiArrayView<3, T2, S2> dest,
86 Neighborhood3D neighborhood3D,
87 EqualityFunctor equal = EqualityFunctor());
88
89 }
90 \endcode
91
92 \deprecatedAPI{labelVolume}
93 pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors :
94 \code
95 namespace vigra {
96
97 template <class SrcIterator, class SrcAccessor,class SrcShape,
98 class DestIterator, class DestAccessor,
99 class Neighborhood3D>
100 unsigned int labelVolume(SrcIterator s_Iter, SrcShape srcShape, SrcAccessor sa,
101 DestIterator d_Iter, DestAccessor da,
102 Neighborhood3D neighborhood3D);
103
104 template <class SrcIterator, class SrcAccessor,class SrcShape,
105 class DestIterator, class DestAccessor,
106 class Neighborhood3D, class EqualityFunctor>
107 unsigned int labelVolume(SrcIterator s_Iter, SrcShape srcShape, SrcAccessor sa,
108 DestIterator d_Iter, DestAccessor da,
109 Neighborhood3D neighborhood3D, EqualityFunctor equal);
110
111 }
112 \endcode
113 use argument objects in conjunction with \ref ArgumentObjectFactories :
114 \code
115 namespace vigra {
116
117 template <class SrcIterator, class SrcAccessor,class SrcShape,
118 class DestIterator, class DestAccessor,
119 class Neighborhood3D>
120 unsigned int labelVolume(triple<SrcIterator, SrcShape, SrcAccessor> src,
121 pair<DestIterator, DestAccessor> dest,
122 Neighborhood3D neighborhood3D);
123
124 template <class SrcIterator, class SrcAccessor,class SrcShape,
125 class DestIterator, class DestAccessor,
126 class Neighborhood3D, class EqualityFunctor>
127 unsigned int labelVolume(triple<SrcIterator, SrcShape, SrcAccessor> src,
128 pair<DestIterator, DestAccessor> dest,
129 Neighborhood3D neighborhood3D, EqualityFunctor equal);
130
131 }
132 \endcode
133 use with 3D-Six-Neighborhood:
134 \code
135 namespace vigra {
136
137 template <class SrcIterator, class SrcAccessor,class SrcShape,
138 class DestIterator, class DestAccessor>
139 unsigned int labelVolumeSix(triple<SrcIterator, SrcShape, SrcAccessor> src,
140 pair<DestIterator, DestAccessor> dest);
141
142 }
143 \endcode
144 \deprecatedEnd
145
146 <b> Usage:</b>
147
148 <b>\#include</b> <vigra/labelvolume.hxx><br>
149 Namespace: vigra
150
151 \code
152 typedef MultiArray<3,int> IntVolume;
153 IntVolume src(Shape3(w,h,d));
154 IntVolume dest(Shape3(w,h,d));
155
156 // find 6-connected regions
157 int max_region_label = labelVolumeSix(src, dest);
158
159 // find 26-connected regions
160 int max_region_label = labelVolume(src, dest, NeighborCode3DTwentySix());
161 \endcode
162
163 \deprecatedUsage{labelVolume}
164 \code
165 typedef vigra::MultiArray<3,int> IntVolume;
166 IntVolume src(IntVolume::difference_type(w,h,d));
167 IntVolume dest(IntVolume::difference_type(w,h,d));
168
169 // find 6-connected regions
170 int max_region_label = vigra::labelVolumeSix(srcMultiArrayRange(src), destMultiArray(dest));
171
172 // find 26-connected regions
173 int max_region_label = vigra::labelVolume(srcMultiArrayRange(src), destMultiArray(dest), NeighborCode3DTwentySix());
174 \endcode
175 <b> Required Interface:</b>
176 \code
177 SrcIterator src_begin;
178 SrcShape shape;
179 DestIterator dest_begin;
180
181 SrcAccessor src_accessor;
182 DestAccessor dest_accessor;
183
184 SrcAccessor::value_type u = src_accessor(src_begin);
185
186 u == u // first form
187
188 EqualityFunctor equal; // second form
189 equal(u, u) // second form
190
191 int i;
192 dest_accessor.set(i, dest_begin);
193 \endcode
194 \deprecatedEnd
195 */
196 doxygen_overloaded_function(template <...> unsigned int labelVolume)
197
198
199 template <class SrcIterator, class SrcAccessor,class SrcShape,
200 class DestIterator, class DestAccessor,
201 class Neighborhood3D, class EqualityFunctor>
202 unsigned int labelVolume(SrcIterator s_Iter, SrcShape srcShape, SrcAccessor sa,
203 DestIterator d_Iter, DestAccessor da,
204 Neighborhood3D, EqualityFunctor equal)
205 {
206 typedef typename DestAccessor::value_type LabelType;
207
208 //basically needed for iteration and border-checks
209 int w = srcShape[0], h = srcShape[1], d = srcShape[2];
210 int x,y,z;
211
212 // temporary image to store region labels
213 UnionFindArray<LabelType> label;
214
215 //Declare traversers for all three dims at target
216 SrcIterator zs = s_Iter;
217 DestIterator zd = d_Iter;
218
219 // initialize the neighborhood traversers
220 NeighborOffsetCirculator<Neighborhood3D> nce(Neighborhood3D::CausalLast);
221 ++nce;
222 // pass 1: scan image from upper left front to lower right back
223 // to find connected components
224
225 // Each component will be represented by a tree of pixels. Each
226 // pixel contains the scan order address of its parent in the
227 // tree. In order for pass 2 to work correctly, the parent must
228 // always have a smaller scan order address than the child.
229 // Therefore, we can merge trees only at their roots, because the
230 // root of the combined tree must have the smallest scan order
231 // address among all the tree's pixels/ nodes. The root of each
232 // tree is distinguished by pointing to itself (it contains its
233 // own scan order address). This condition is enforced whenever a
234 // new region is found or two regions are merged
235 for(z = 0; z != d; ++z, ++zs.dim2(), ++zd.dim2())
236 {
237 SrcIterator ys(zs);
238 DestIterator yd(zd);
239
240 for(y = 0; y != h; ++y, ++ys.dim1(), ++yd.dim1())
241 {
242 SrcIterator xs(ys);
243 DestIterator xd(yd);
244
245 for(x = 0; x != w; ++x, ++xs.dim0(), ++xd.dim0())
246 {
247 LabelType currentIndex = label.nextFreeIndex();
248
249 //check whether there is a special border treatment to be used or not
250 AtVolumeBorder atBorder = isAtVolumeBorderCausal(x,y,z,w,h,d);
251
252 //We are not at the border!
253 if(atBorder == NotAtBorder)
254 {
255 NeighborOffsetCirculator<Neighborhood3D> nc(Neighborhood3D::CausalFirst);
256
257 do
258 {
259 // if colors are equal
260 if(equal(sa(xs), sa(xs, *nc)))
261 {
262 currentIndex = label.makeUnion(da(xd,*nc), currentIndex);
263 }
264 ++nc;
265 }
266 while(nc!=nce);
267 }
268 else //we are at a border - handle this!!
269 {
270 NeighborOffsetCirculator<Neighborhood3D> nc(Neighborhood3D::nearBorderDirectionsCausal(atBorder,0));
271 int j=0;
272 while(nc.direction() != Neighborhood3D::Error)
273 {
274 int dummy = x+(*nc)[0]; // prevents an apparently incorrect optimization in gcc 4.8
275 if (dummy<0)
276 {
277 std::cerr << "internal error " << dummy << std::endl;
278 }
279 // colors equal???
280 if(equal(sa(xs), sa(xs, *nc)))
281 {
282 currentIndex = label.makeUnion(da(xd,*nc), currentIndex);
283 }
284 nc.turnTo(Neighborhood3D::nearBorderDirectionsCausal(atBorder,++j));
285 }
286 }
287 da.set(label.finalizeIndex(currentIndex), xd);
288 }
289 }
290 }
291
292 LabelType count = label.makeContiguous();
293
294 // pass 2: assign one label to each region (tree)
295 // so that labels form a consecutive sequence 1, 2, ...
296 zd = d_Iter;
297 for(z=0; z != d; ++z, ++zd.dim2())
298 {
299 DestIterator yd(zd);
300
301 for(y=0; y != h; ++y, ++yd.dim1())
302 {
303 DestIterator xd(yd);
304
305 for(x = 0; x != w; ++x, ++xd.dim0())
306 {
307 da.set(label.findLabel(da(xd)), xd);
308 }
309 }
310 }
311 return count;
312 }
313
314 template <class SrcIterator, class SrcAccessor,class SrcShape,
315 class DestIterator, class DestAccessor,
316 class Neighborhood3D>
317 unsigned int labelVolume(SrcIterator s_Iter, SrcShape srcShape, SrcAccessor sa,
318 DestIterator d_Iter, DestAccessor da,
319 Neighborhood3D neighborhood3D)
320 {
321 return labelVolume(s_Iter, srcShape, sa, d_Iter, da, neighborhood3D, std::equal_to<typename SrcAccessor::value_type>());
322 }
323
324 template <class SrcIterator, class SrcShape, class SrcAccessor,
325 class DestIterator, class DestAccessor,
326 class Neighborhood3D>
327 unsigned int labelVolume(triple<SrcIterator, SrcShape, SrcAccessor> src,
328 pair<DestIterator, DestAccessor> dest,
329 Neighborhood3D neighborhood3D)
330 {
331 return labelVolume(src.first, src.second, src.third, dest.first, dest.second, neighborhood3D, std::equal_to<typename SrcAccessor::value_type>());
332 }
333
334 template <class SrcIterator, class SrcShape, class SrcAccessor,
335 class DestIterator, class DestAccessor,
336 class Neighborhood3D, class EqualityFunctor>
337 unsigned int labelVolume(triple<SrcIterator, SrcShape, SrcAccessor> src,
338 pair<DestIterator, DestAccessor> dest,
339 Neighborhood3D neighborhood3D, EqualityFunctor equal)
340 {
341 return labelVolume(src.first, src.second, src.third, dest.first, dest.second, neighborhood3D, equal);
342 }
343
344 template <class T1, class S1,
345 class T2, class S2,
346 class Neighborhood3D, class EqualityFunctor>
347 inline unsigned int
348 labelVolume(MultiArrayView<3, T1, S1> const & source,
349 MultiArrayView<3, T2, S2> dest,
350 Neighborhood3D neighborhood3D,
351 EqualityFunctor equal)
352 {
353 vigra_precondition(source.shape() == dest.shape(),
354 "labelVolume(): shape mismatch between input and output.");
355 return labelVolume(srcMultiArrayRange(source), destMultiArray(dest), neighborhood3D, equal);
356 }
357
358 template <class T1, class S1,
359 class T2, class S2,
360 class Neighborhood3D>
361 inline unsigned int
362 labelVolume(MultiArrayView<3, T1, S1> const & source,
363 MultiArrayView<3, T2, S2> dest,
364 Neighborhood3D neighborhood3D)
365 {
366 vigra_precondition(source.shape() == dest.shape(),
367 "labelVolume(): shape mismatch between input and output.");
368 return labelVolume(srcMultiArrayRange(source), destMultiArray(dest), neighborhood3D, std::equal_to<T1>());
369 }
370
371 /********************************************************/
372 /* */
373 /* labelVolumeSix */
374 /* */
375 /********************************************************/
376
377 /** \brief Find the connected components of a segmented volume
378 using the 6-neighborhood.
379
380 See \ref labelVolume() for detailed documentation.
381
382 */
383 template <class SrcIterator, class SrcAccessor,class SrcShape,
384 class DestIterator, class DestAccessor>
385 unsigned int labelVolumeSix(triple<SrcIterator, SrcShape, SrcAccessor> src,
386 pair<DestIterator, DestAccessor> dest)
387 {
388 return labelVolume(src.first, src.second, src.third, dest.first, dest.second, NeighborCode3DSix(), std::equal_to<typename SrcAccessor::value_type>());
389 }
390
391 template <class T1, class S1,
392 class T2, class S2>
393 unsigned int labelVolumeSix(MultiArrayView<3, T1, S1> const & source,
394 MultiArrayView<3, T2, S2> dest)
395 {
396 return labelVolume(srcMultiArrayRange(source), destMultiArray(dest),
397 NeighborCode3DSix(), std::equal_to<T1>());
398 }
399
400 /********************************************************/
401 /* */
402 /* labelVolumeWithBackground */
403 /* */
404 /********************************************************/
405
406 /** \brief Find the connected components of a segmented volume,
407 excluding the background from labeling.
408
409 This function works like \ref labelVolume(), but considers all background voxels
410 (i.e. voxels having the given '<TT>background_value</TT>') as a single region that
411 is ignored when determining connected components and remains untouched in the
412 destination array. Usually, you will zero-initialize the output array, so that
413 the background gets label 0 (remember that actual region labels start at one).
414
415 Return: the number of regions found (= largest region label)
416
417 See \ref labelMultiArrayWithBackground() for a dimension-independent implementation
418 if this algorithm.
419
420 <b> Declarations:</b>
421
422 pass 3D array views:
423 \code
424 namespace vigra {
425 template <class T1, class S1,
426 class T2, class S2,
427 class Neighborhood3D,
428 class ValueType,
429 class EqualityFunctor = std::equalt_to<T1> >
430 unsigned int
431 labelVolumeWithBackground(MultiArrayView<3, T1, S1> const & source,
432 MultiArrayView<3, T2, S2> dest,
433 Neighborhood3D neighborhood3D,
434 ValueType backgroundValue,
435 EqualityFunctor equal = EqualityFunctor());
436 }
437 \endcode
438
439 \deprecatedAPI{labelVolumeWithBackground}
440 pass \ref MultiIteratorPage "MultiIterators" and \ref DataAccessors :
441 \code
442 namespace vigra {
443
444 template <class SrcIterator, class SrcAccessor,class SrcShape,
445 class DestIterator, class DestAccessor,
446 class Neighborhood3D, class ValueType>
447 unsigned int labelVolumeWithBackground( SrcIterator s_Iter, SrcShape srcShape, SrcAccessor sa,
448 DestIterator d_Iter, DestAccessor da,
449 Neighborhood3D neighborhood3D, ValueType background_value);
450
451 template <class SrcIterator, class SrcAccessor,class SrcShape,
452 class DestIterator, class DestAccessor,
453 class Neighborhood3D, class ValueType, class EqualityFunctor>
454 unsigned int labelVolumeWithBackground( SrcIterator s_Iter, SrcShape srcShape, SrcAccessor sa,
455 DestIterator d_Iter, DestAccessor da,
456 Neighborhood3D neighborhood3D, ValueType background_value,
457 EqualityFunctor equal);
458
459 }
460 \endcode
461 use argument objects in conjunction with \ref ArgumentObjectFactories :
462 \code
463 namespace vigra {
464
465 template <class SrcIterator, class SrcAccessor,class SrcShape,
466 class DestIterator, class DestAccessor,
467 class Neighborhood3D, class ValueType>
468 unsigned int labelVolumeWithBackground( triple<SrcIterator, SrcShape, SrcAccessor> src,
469 pair<DestIterator, DestAccessor> dest,
470 Neighborhood3D neighborhood3D, ValueType background_value);
471
472 template <class SrcIterator, class SrcAccessor,class SrcShape,
473 class DestIterator, class DestAccessor,
474 class Neighborhood3D, class ValueType, class EqualityFunctor>
475 unsigned int labelVolumeWithBackground( triple<SrcIterator, SrcShape, SrcAccessor> src,
476 pair<DestIterator, DestAccessor> dest,
477 Neighborhood3D neighborhood3D, ValueType background_value,
478 EqualityFunctor equal);
479
480 }
481 \endcode
482 \deprecatedEnd
483
484 <b> Usage:</b>
485
486 <b>\#include</b> <vigra/labelvolume.hxx><br>
487 Namespace: vigra
488
489 \code
490 typedef vigra::MultiArray<3,int> IntVolume;
491
492 IntVolume src(Shape3(w,h,d));
493 IntVolume dest(Shape3(w,h,d));
494
495 // find 6-connected regions
496 int max_region_label = labelVolumeWithBackground(src, dest, NeighborCode3DSix(), 0);
497 \endcode
498
499 \deprecatedUsage{labelVolumeWithBackground}
500 \code
501 typedef vigra::MultiArray<3,int> IntVolume;
502 IntVolume src(IntVolume::difference_type(w,h,d));
503 IntVolume dest(IntVolume::difference_type(w,h,d));
504
505 // find 6-connected regions
506 int max_region_label = vigra::labelVolumeWithBackground(
507 srcMultiArrayRange(src), destMultiArray(dest), NeighborCode3DSix(), 0);
508 \endcode
509 <b> Required Interface:</b>
510 \code
511 SrcIterator src_begin;
512 SrcShape shape;
513 DestIterator dest_begin;
514
515 SrcAccessor src_accessor;
516 DestAccessor dest_accessor;
517
518 SrcAccessor::value_type u = src_accessor(src_begin);
519
520 u == u // first form
521
522 EqualityFunctor equal; // second form
523 equal(u, u) // second form
524
525 int i;
526 dest_accessor.set(i, dest_begin);
527 \endcode
528 \deprecatedEnd
529 */
530 doxygen_overloaded_function(template <...> unsigned int labelVolumeWithBackground)
531
532 template <class SrcIterator, class SrcAccessor,class SrcShape,
533 class DestIterator, class DestAccessor,
534 class Neighborhood3D,
535 class ValueType, class EqualityFunctor>
536 unsigned int labelVolumeWithBackground(SrcIterator s_Iter, SrcShape srcShape, SrcAccessor sa,
537 DestIterator d_Iter, DestAccessor da,
538 Neighborhood3D,
539 ValueType backgroundValue, EqualityFunctor equal)
540 {
541 typedef typename DestAccessor::value_type LabelType;
542
543 //basically needed for iteration and border-checks
544 int w = srcShape[0], h = srcShape[1], d = srcShape[2];
545 int x,y,z;
546
547 // temporary image to store region labels
548 UnionFindArray<LabelType> label;
549
550 //Declare traversers for all three dims at target
551 SrcIterator zs = s_Iter;
552 DestIterator zd = d_Iter;
553
554 // initialize the neighborhood traversers
555 NeighborOffsetCirculator<Neighborhood3D> nce(Neighborhood3D::CausalLast);
556 ++nce;
557 // pass 1: scan image from upper left front to lower right back
558 // to find connected components
559
560 // Each component will be represented by a tree of pixels. Each
561 // pixel contains the scan order address of its parent in the
562 // tree. In order for pass 2 to work correctly, the parent must
563 // always have a smaller scan order address than the child.
564 // Therefore, we can merge trees only at their roots, because the
565 // root of the combined tree must have the smallest scan order
566 // address among all the tree's pixels/ nodes. The root of each
567 // tree is distinguished by pointing to itself (it contains its
568 // own scan order address). This condition is enforced whenever a
569 // new region is found or two regions are merged
570 for(z = 0; z != d; ++z, ++zs.dim2(), ++zd.dim2())
571 {
572 SrcIterator ys(zs);
573 DestIterator yd(zd);
574
575 for(y = 0; y != h; ++y, ++ys.dim1(), ++yd.dim1())
576 {
577 SrcIterator xs(ys);
578 DestIterator xd(yd);
579
580 for(x = 0; x != w; ++x, ++xs.dim0(), ++xd.dim0())
581 {
582 if(equal(sa(xs), backgroundValue))
583 {
584 //da.set(label.getIndex(0), xd);
585 da.set(0, xd);
586 continue;
587 }
588
589 LabelType currentIndex = label.nextFreeIndex();
590
591 //check whether there is a special border treatment to be used or not
592 AtVolumeBorder atBorder = isAtVolumeBorderCausal(x,y,z,w,h,d);
593
594 //We are not at the border!
595 if(atBorder == NotAtBorder)
596 {
597 NeighborOffsetCirculator<Neighborhood3D> nc(Neighborhood3D::CausalFirst);
598
599 do
600 {
601 // if colors are equal
602 if(equal(sa(xs), sa(xs, *nc)))
603 {
604 currentIndex = label.makeUnion(da(xd,*nc), currentIndex);
605 }
606 ++nc;
607 }
608 while(nc!=nce);
609 }
610 else //we are at a border - handle this!!
611 {
612 NeighborOffsetCirculator<Neighborhood3D> nc(Neighborhood3D::nearBorderDirectionsCausal(atBorder,0));
613 int j=0;
614 while(nc.direction() != Neighborhood3D::Error)
615 {
616 int dummy = x+(*nc)[0]; // prevents an apparently incorrect optimization in gcc 4.8
617 if (dummy<0)
618 {
619 std::cerr << "internal error " << dummy << std::endl;
620 }
621 // colors equal???
622 if(equal(sa(xs), sa(xs, *nc)))
623 {
624 currentIndex = label.makeUnion(da(xd,*nc), currentIndex);
625 }
626 nc.turnTo(Neighborhood3D::nearBorderDirectionsCausal(atBorder,++j));
627 }
628 }
629 da.set(label.finalizeIndex(currentIndex), xd);
630 }
631 }
632 }
633
634 LabelType count = label.makeContiguous();
635
636 // pass 2: assign one label to each region (tree)
637 // so that labels form a consecutive sequence 1, 2, ...
638 zd = d_Iter;
639 for(z=0; z != d; ++z, ++zd.dim2())
640 {
641 DestIterator yd(zd);
642
643 for(y=0; y != h; ++y, ++yd.dim1())
644 {
645 DestIterator xd(yd);
646
647 for(x = 0; x != w; ++x, ++xd.dim0())
648 {
649 da.set(label.findLabel(da(xd)), xd);
650 }
651 }
652 }
653 return count;
654 }
655
656 template <class SrcIterator, class SrcAccessor,class SrcShape,
657 class DestIterator, class DestAccessor,
658 class Neighborhood3D,
659 class ValueType>
660 inline unsigned int
661 labelVolumeWithBackground(SrcIterator s_Iter, SrcShape srcShape, SrcAccessor sa,
662 DestIterator d_Iter, DestAccessor da,
663 Neighborhood3D neighborhood3D, ValueType backgroundValue)
664 {
665 return labelVolumeWithBackground(s_Iter, srcShape, sa, d_Iter, da, neighborhood3D, backgroundValue, std::equal_to<typename SrcAccessor::value_type>());
666 }
667
668 template <class SrcIterator, class SrcShape, class SrcAccessor,
669 class DestIterator, class DestAccessor,
670 class Neighborhood3D,
671 class ValueType,
672 class EqualityFunctor>
673 inline unsigned int
674 labelVolumeWithBackground(triple<SrcIterator, SrcShape, SrcAccessor> src,
675 pair<DestIterator, DestAccessor> dest,
676 Neighborhood3D neighborhood3D, ValueType backgroundValue, EqualityFunctor equal)
677 {
678 return labelVolumeWithBackground(src.first, src.second, src.third, dest.first, dest.second, neighborhood3D, backgroundValue, equal);
679 }
680
681 template <class SrcIterator, class SrcShape, class SrcAccessor,
682 class DestIterator, class DestAccessor,
683 class Neighborhood3D,
684 class ValueType>
685 inline unsigned int
686 labelVolumeWithBackground(triple<SrcIterator, SrcShape, SrcAccessor> src,
687 pair<DestIterator, DestAccessor> dest,
688 Neighborhood3D neighborhood3D, ValueType backgroundValue)
689 {
690 return labelVolumeWithBackground(src.first, src.second, src.third, dest.first, dest.second,
691 neighborhood3D, backgroundValue, std::equal_to<typename SrcAccessor::value_type>());
692 }
693
694 template <class T1, class S1,
695 class T2, class S2,
696 class Neighborhood3D,
697 class ValueType,
698 class EqualityFunctor>
699 inline unsigned int
700 labelVolumeWithBackground(MultiArrayView<3, T1, S1> const & source,
701 MultiArrayView<3, T2, S2> dest,
702 Neighborhood3D neighborhood3D,
703 ValueType backgroundValue,
704 EqualityFunctor equal)
705 {
706 vigra_precondition(source.shape() == dest.shape(),
707 "labelVolumeWithBackground(): shape mismatch between input and output.");
708 return labelVolumeWithBackground(srcMultiArrayRange(source), destMultiArray(dest),
709 neighborhood3D, backgroundValue, equal);
710 }
711
712 template <class T1, class S1,
713 class T2, class S2,
714 class Neighborhood3D,
715 class ValueType>
716 inline unsigned int
717 labelVolumeWithBackground(MultiArrayView<3, T1, S1> const & source,
718 MultiArrayView<3, T2, S2> dest,
719 Neighborhood3D neighborhood3D,
720 ValueType backgroundValue)
721 {
722 vigra_precondition(source.shape() == dest.shape(),
723 "labelVolumeWithBackground(): shape mismatch between input and output.");
724 return labelVolumeWithBackground(srcMultiArrayRange(source), destMultiArray(dest),
725 neighborhood3D, backgroundValue,
726 std::equal_to<T1>());
727 }
728
729 //@}
730
731 } //end of namespace vigra
732
733 #endif //VIGRA_LABELVOLUME_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.10.0 (Thu Jan 8 2015)