37 #ifndef VIGRA_LABELIMAGE_HXX
38 #define VIGRA_LABELIMAGE_HXX
43 #include "stdimage.hxx"
44 #include "union_find.hxx"
45 #include "sized_int.hxx"
46 #include "multi_shape.hxx"
187 template <
class SrcIterator,
class SrcAccessor,
188 class DestIterator,
class DestAccessor,
189 class EqualityFunctor>
190 unsigned int labelImage(SrcIterator upperlefts,
191 SrcIterator lowerrights, SrcAccessor sa,
192 DestIterator upperleftd, DestAccessor da,
193 bool eight_neighbors, EqualityFunctor equal)
195 typedef typename DestAccessor::value_type LabelType;
197 int w = lowerrights.x - upperlefts.x;
198 int h = lowerrights.y - upperlefts.y;
201 const Diff2D neighbor[] = {
208 const int left = 0, top = 2, topright = 3;
209 int step = eight_neighbors ? 1 : 2;
211 SrcIterator ys = upperlefts;
212 DestIterator yd = upperleftd;
214 UnionFindArray<LabelType> label;
231 for(y = 0; y != h; ++y, ++ys.y, ++yd.y)
234 DestIterator xd = yd;
236 int endNeighbor = (y == 0) ? left : (eight_neighbors ? topright : top);
238 for(x = 0; x != w; ++x, ++xs.x, ++xd.x)
240 int beginNeighbor = (x == 0) ? top : left;
241 if(x == w-1 && endNeighbor == topright) endNeighbor = top;
243 for(i=beginNeighbor; i<=endNeighbor; i+=step)
245 if(equal(sa(xs), sa(xs, neighbor[i])))
247 LabelType neighborIndex = label.findIndex(da(xd,neighbor[i]));
249 for(
int j=i+2; j<=endNeighbor; j+=step)
251 if(equal(sa(xs), sa(xs, neighbor[j])))
253 neighborIndex = label.makeUnion(da(xd, neighbor[j]), neighborIndex);
257 da.set(neighborIndex, xd);
264 da.set(label.makeNewIndex(), xd);
271 unsigned int count = label.makeContiguous();
274 for(y=0; y != h; ++y, ++yd.y)
276 typename DestIterator::row_iterator xd = yd.rowIterator();
277 for(x = 0; x != w; ++x, ++xd)
279 da.set(label.findLabel(da(xd)), xd);
285 template <
class SrcIterator,
class SrcAccessor,
286 class DestIterator,
class DestAccessor>
288 unsigned int labelImage(SrcIterator upperlefts,
289 SrcIterator lowerrights, SrcAccessor sa,
290 DestIterator upperleftd, DestAccessor da,
291 bool eight_neighbors)
293 return labelImage(upperlefts, lowerrights, sa,
294 upperleftd, da, eight_neighbors,
295 std::equal_to<typename SrcAccessor::value_type>());
298 template <
class SrcIterator,
class SrcAccessor,
299 class DestIterator,
class DestAccessor,
300 class EqualityFunctor>
302 labelImage(triple<SrcIterator, SrcIterator, SrcAccessor> src,
303 pair<DestIterator, DestAccessor> dest,
304 bool eight_neighbors, EqualityFunctor equal)
306 return labelImage(src.first, src.second, src.third,
307 dest.first, dest.second, eight_neighbors, equal);
310 template <
class SrcIterator,
class SrcAccessor,
311 class DestIterator,
class DestAccessor>
313 labelImage(triple<SrcIterator, SrcIterator, SrcAccessor> src,
314 pair<DestIterator, DestAccessor> dest,
315 bool eight_neighbors)
317 return labelImage(src.first, src.second, src.third,
318 dest.first, dest.second, eight_neighbors,
319 std::equal_to<typename SrcAccessor::value_type>());
322 template <
class T1,
class S1,
324 class EqualityFunctor>
326 labelImage(MultiArrayView<2, T1, S1>
const & src,
327 MultiArrayView<2, T2, S2> dest,
328 bool eight_neighbors, EqualityFunctor equal)
330 vigra_precondition(src.shape() == dest.shape(),
331 "labelImage(): shape mismatch between input and output.");
333 destImage(dest), eight_neighbors, equal);
336 template <
class T1,
class S1,
339 labelImage(MultiArrayView<2, T1, S1>
const & src,
340 MultiArrayView<2, T2, S2> dest,
341 bool eight_neighbors)
344 destImage(dest), eight_neighbors,
345 std::equal_to<T1>());
488 template <
class SrcIterator,
class SrcAccessor,
489 class DestIterator,
class DestAccessor,
490 class ValueType,
class EqualityFunctor>
492 SrcIterator upperlefts,
493 SrcIterator lowerrights, SrcAccessor sa,
494 DestIterator upperleftd, DestAccessor da,
495 bool eight_neighbors,
496 ValueType background_value, EqualityFunctor equal)
498 int w = lowerrights.x - upperlefts.x;
499 int h = lowerrights.y - upperlefts.y;
502 const Diff2D neighbor[] = {
509 const int left = 0, top = 2, topright = 3;
510 int step = eight_neighbors ? 1 : 2;
512 SrcIterator ys(upperlefts);
516 typedef BasicImage<IntBiggest> TmpImage;
517 TmpImage labelimage(w, h);
518 TmpImage::ScanOrderIterator label = labelimage.begin();
519 TmpImage::Iterator yt = labelimage.upperLeft();
520 TmpImage::Iterator xt(yt);
525 for(y = 0; y != h; ++y, ++ys.y, ++yt.y)
530 int endNeighbor = (y == 0) ? left : (eight_neighbors ? topright : top);
532 for(x = 0; x != w; ++x, ++xs.x, ++xt.x)
534 if(equal(sa(xs), background_value))
540 int beginNeighbor = (x == 0) ? top : left;
541 if(x == w-1 && endNeighbor == topright) endNeighbor = top;
543 for(i=beginNeighbor; i<=endNeighbor; i+=step)
545 if(equal(sa(xs), sa(xs, neighbor[i])))
549 for(
int j=i+2; j<=endNeighbor; j+=step)
551 if(equal(sa(xs), sa(xs, neighbor[j])))
555 if(neighborIndex != neighborLabel1)
558 while(neighborIndex != label[neighborIndex])
560 neighborIndex = label[neighborIndex];
562 while(neighborLabel1 != label[neighborLabel1])
564 neighborLabel1 = label[neighborLabel1];
568 if(neighborLabel1 < neighborIndex)
570 label[neighborIndex] = neighborLabel1;
571 neighborIndex = neighborLabel1;
573 else if(neighborIndex < neighborLabel1)
575 label[neighborLabel1] = neighborIndex;
599 DestIterator yd(upperleftd);
603 for(y=0; y != h; ++y, ++yd.y)
606 for(x = 0; x != w; ++x, ++xd.x, ++i)
608 if(label[i] == -1)
continue;
616 label[i] = label[label[i]];
618 da.set(label[i]+1, xd);
625 template <
class SrcIterator,
class SrcAccessor,
626 class DestIterator,
class DestAccessor,
630 SrcIterator upperlefts,
631 SrcIterator lowerrights, SrcAccessor sa,
632 DestIterator upperleftd, DestAccessor da,
633 bool eight_neighbors,
634 ValueType background_value)
638 eight_neighbors, background_value,
639 std::equal_to<typename SrcAccessor::value_type>());
642 template <
class SrcIterator,
class SrcAccessor,
643 class DestIterator,
class DestAccessor,
644 class ValueType,
class EqualityFunctor>
647 pair<DestIterator, DestAccessor> dest,
648 bool eight_neighbors,
649 ValueType background_value, EqualityFunctor equal)
652 dest.first, dest.second,
653 eight_neighbors, background_value, equal);
656 template <
class SrcIterator,
class SrcAccessor,
657 class DestIterator,
class DestAccessor,
661 pair<DestIterator, DestAccessor> dest,
662 bool eight_neighbors,
663 ValueType background_value)
666 dest.first, dest.second,
667 eight_neighbors, background_value,
668 std::equal_to<typename SrcAccessor::value_type>());
671 template <
class T1,
class S1,
673 class ValueType,
class EqualityFunctor>
676 MultiArrayView<2, T2, S2> dest,
677 bool eight_neighbors,
678 ValueType background_value, EqualityFunctor equal)
680 vigra_precondition(src.shape() == dest.shape(),
681 "labelImageWithBackground(): shape mismatch between input and output.");
684 eight_neighbors, background_value, equal);
687 template <
class T1,
class S1,
692 MultiArrayView<2, T2, S2> dest,
693 bool eight_neighbors,
694 ValueType background_value)
696 vigra_precondition(src.shape() == dest.shape(),
697 "labelImageWithBackground(): shape mismatch between input and output.");
700 eight_neighbors, background_value,
701 std::equal_to<T1>());
711 enum EdgeImageLabelPolicy { CopyRegionLabels, EdgeOverlayOnly };
865 template <
class SrcIterator,
class SrcAccessor,
866 class DestIterator,
class DestAccessor,
class DestValue>
868 SrcIterator sul, SrcIterator slr, SrcAccessor sa,
869 DestIterator dul, DestAccessor da,
870 DestValue edge_marker,
871 EdgeImageLabelPolicy labelPolicy = CopyRegionLabels)
873 int w = slr.x - sul.x;
874 int h = slr.y - sul.y;
877 const Diff2D right(1,0);
878 const Diff2D left(-1,0);
879 const Diff2D bottomright(1,1);
880 const Diff2D bottom(0,1);
881 const Diff2D top(0,-1);
883 SrcIterator iy = sul;
884 DestIterator dy = dul;
886 for(y=0; y<h-1; ++y, ++iy.y, dy.y+=2)
889 DestIterator dx = dy;
891 for(x=0; x<w-1; ++x, ++ix.x, dx.x+=2)
893 if(labelPolicy == CopyRegionLabels)
896 da.set(sa(ix), dx, bottomright);
899 if(sa(ix, right) != sa(ix))
901 da.set(edge_marker, dx, right);
903 else if(labelPolicy == CopyRegionLabels)
905 da.set(sa(ix), dx, right);
907 if(sa(ix, bottom) != sa(ix))
909 da.set(edge_marker, dx, bottom);
911 else if(labelPolicy == CopyRegionLabels)
913 da.set(sa(ix), dx, bottom);
918 if(labelPolicy == CopyRegionLabels)
922 if(sa(ix, bottom) != sa(ix))
924 da.set(edge_marker, dx, bottom);
926 else if(labelPolicy == CopyRegionLabels)
928 da.set(sa(ix), dx, bottom);
933 DestIterator dx = dy;
935 for(x=0; x<w-1; ++x, ++ix.x, dx.x+=2)
937 if(labelPolicy == CopyRegionLabels)
941 if(sa(ix, right) != sa(ix))
943 da.set(edge_marker, dx, right);
945 else if(labelPolicy == CopyRegionLabels)
947 da.set(sa(ix), dx, right);
950 if(labelPolicy == CopyRegionLabels)
954 dy = dul + Diff2D(1,1);
956 const Diff2D dist[] = {right, top, left, bottom };
958 for(y=0; y<h-1; ++y, dy.y+=2)
960 DestIterator dx = dy;
962 for(x=0; x<w-1; ++x, dx.x+=2)
967 if(da(dx, dist[i]) == edge_marker)
break;
970 if(i < 4) da.set(edge_marker, dx);
975 template <
class SrcIterator,
class SrcAccessor,
976 class DestIterator,
class DestAccessor,
class DestValue>
979 pair<DestIterator, DestAccessor> dest,
980 DestValue edge_marker,
981 EdgeImageLabelPolicy labelPolicy = CopyRegionLabels)
984 dest.first, dest.second,
985 edge_marker, labelPolicy);
988 template <
class T1,
class S1,
989 class T2,
class S2,
class DestValue>
992 MultiArrayView<2, T2, S2> dest,
993 DestValue edge_marker,
994 EdgeImageLabelPolicy labelPolicy = CopyRegionLabels)
996 vigra_precondition(2*src.shape()-Shape2(1) == dest.shape(),
997 "regionImageToCrackEdgeImage(): shape mismatch between input and output.");
1127 template <
class SrcIterator,
class SrcAccessor,
1128 class DestIterator,
class DestAccessor,
class DestValue>
1130 SrcIterator sul, SrcIterator slr, SrcAccessor sa,
1131 DestIterator dul, DestAccessor da,
1132 DestValue edge_marker)
1134 int w = slr.x - sul.x;
1135 int h = slr.y - sul.y;
1138 const Diff2D right(1,0);
1139 const Diff2D left(-1,0);
1140 const Diff2D bottomright(1,1);
1141 const Diff2D bottom(0,1);
1142 const Diff2D top(0,-1);
1144 SrcIterator iy = sul;
1145 DestIterator dy = dul;
1147 for(y=0; y<h-1; ++y, ++iy.y, ++dy.y)
1149 SrcIterator ix = iy;
1150 DestIterator dx = dy;
1152 for(x=0; x<w-1; ++x, ++ix.x, ++dx.x)
1154 if(sa(ix, right) != sa(ix))
1156 da.set(edge_marker, dx);
1158 if(sa(ix, bottom) != sa(ix))
1160 da.set(edge_marker, dx);
1164 if(sa(ix, bottom) != sa(ix))
1166 da.set(edge_marker, dx);
1170 SrcIterator ix = iy;
1171 DestIterator dx = dy;
1173 for(x=0; x<w-1; ++x, ++ix.x, ++dx.x)
1175 if(sa(ix, right) != sa(ix))
1177 da.set(edge_marker, dx);
1182 template <
class SrcIterator,
class SrcAccessor,
1183 class DestIterator,
class DestAccessor,
class DestValue>
1186 pair<DestIterator, DestAccessor> dest,
1187 DestValue edge_marker)
1190 dest.first, dest.second,
1194 template <
class T1,
class S1,
1195 class T2,
class S2,
class DestValue>
1198 MultiArrayView<2, T2, S2> dest,
1199 DestValue edge_marker)
1201 vigra_precondition(src.shape() == dest.shape(),
1202 "regionImageToEdgeImage(): shape mismatch between input and output.");
1212 #endif // VIGRA_LABELIMAGE_HXX
unsigned int labelImage(...)
Find the connected components of a segmented image.
unsigned int labelImageWithBackground(...)
Find the connected components of a segmented image, excluding the background from labeling...
void regionImageToEdgeImage(...)
Transform a labeled image into an edge image.
doxygen_overloaded_function(template<...> void separableConvolveBlockwise) template< unsigned int N
Separated convolution on ChunkedArrays.
void regionImageToCrackEdgeImage(...)
Transform a labeled image into a crack edge (interpixel edge) image.
detail::SelectBiggestIntegerType< detail::SignedIntTypes >::type IntBiggest
the biggest signed integer type of the system
Definition: sized_int.hxx:188