37 #ifndef VIGRA_FLATMORPHOLOGY_HXX
38 #define VIGRA_FLATMORPHOLOGY_HXX
42 #include "utilities.hxx"
43 #include "multi_shape.hxx"
155 template <
class SrcIterator,
class SrcAccessor,
156 class DestIterator,
class DestAccessor>
159 SrcIterator lowerright1, SrcAccessor sa,
160 DestIterator upperleft2, DestAccessor da,
161 int radius,
float rank)
163 vigra_precondition((rank >= 0.0) && (rank <= 1.0),
164 "discRankOrderFilter(): Rank must be between 0 and 1"
167 vigra_precondition(radius >= 0,
168 "discRankOrderFilter(): Radius must be >= 0.");
170 int i, x, y, xmax, ymax, xx, yy;
171 int rankpos, winsize, leftsum;
176 std::vector<int> struct_function(radius+1);
177 struct_function[0] = radius;
179 double r2 = (double)radius*radius;
180 for(i=1; i<=radius; ++i)
182 double r = (double) i - 0.5;
186 int w = lowerright1.x - upperleft1.x;
187 int h = lowerright1.y - upperleft1.y;
189 SrcIterator ys(upperleft1);
190 DestIterator yd(upperleft2);
192 for(y=0; y<h; ++y, ++ys.y, ++yd.y)
204 for(i=0; i<256; ++i) hist[i] = 0;
208 ymax = (y1 < radius) ? y1 : radius;
209 for(yy=0; yy<=ymax; ++yy)
211 xmax = (x1 < struct_function[yy]) ? x1 : struct_function[yy];
212 for(xx=0; xx<=xmax; ++xx)
214 hist[sa(xs, Diff2D(xx, yy))]++;
219 ymax = (y0 < radius) ? y0 : radius;
220 for(yy=1; yy<=ymax; ++yy)
222 xmax = (x1 < struct_function[yy]) ? x1 : struct_function[yy];
223 for(xx=0; xx<=xmax; ++xx)
225 hist[sa(xs, Diff2D(xx, -yy))]++;
244 if((
float)(hist[i]+leftsum) / winsize >= rank)
break;
256 for(x=1; x<w; ++x, ++xs.x, ++xd.x)
265 yy = (y1 < radius) ? y1 : radius;
269 xx = struct_function[yy]+1;
272 cur = sa(xs, Diff2D(-xx, yy));
275 if(cur < rankpos) leftsum--;
278 yy = (y0 < radius) ? y0 : radius;
282 xx = struct_function[yy]+1;
285 cur = sa(xs, Diff2D(-xx, -yy));
288 if(cur < rankpos) leftsum--;
293 yy = (y1 < radius) ? y1 : radius;
297 xx = struct_function[yy];
300 cur = sa(xs, Diff2D(xx, yy));
303 if(cur < rankpos) leftsum++;
306 yy = (y0 < radius) ? y0 : radius;
310 xx = struct_function[yy];
313 cur = sa(xs, Diff2D(xx, -yy));
316 if(cur < rankpos) leftsum++;
326 for(i=rankpos; i<256; i++)
335 for(i=rankpos-1; i>=0; i--)
338 if(leftsum == 0)
break;
345 if((
float)leftsum / winsize < rank)
348 for(i=rankpos; i<256; i++)
350 if((
float)(hist[i]+leftsum) / winsize >= rank)
break;
358 for(i=rankpos-1; i>=0; i--)
361 if((
float)leftsum / winsize < rank)
break;
372 template <
class SrcIterator,
class SrcAccessor,
373 class DestIterator,
class DestAccessor>
376 pair<DestIterator, DestAccessor> dest,
377 int radius,
float rank)
380 dest.first, dest.second,
384 template <
class T1,
class S1,
388 MultiArrayView<2, T2, S2> dest,
389 int radius,
float rank)
391 vigra_precondition(src.shape() == dest.shape(),
392 "discRankOrderFilter(): shape mismatch between input and output.");
449 doxygen_overloaded_function(template <...>
void discErosion)
451 template <
class SrcIterator,
class SrcAccessor,
452 class DestIterator,
class DestAccessor>
455 SrcIterator lowerright1, SrcAccessor sa,
456 DestIterator upperleft2, DestAccessor da,
459 vigra_precondition(radius >= 0,
"discErosion(): Radius must be >= 0.");
462 upperleft2, da, radius, 0.0);
465 template <
class SrcIterator,
class SrcAccessor,
466 class DestIterator,
class DestAccessor>
468 discErosion(triple<SrcIterator, SrcIterator, SrcAccessor> src,
469 pair<DestIterator, DestAccessor> dest,
472 vigra_precondition(radius >= 0,
"discErosion(): Radius must be >= 0.");
475 dest.first, dest.second,
479 template <
class T1,
class S1,
483 MultiArrayView<2, T2, S2> dest,
486 vigra_precondition(src.shape() == dest.shape(),
487 "discErosion(): shape mismatch between input and output.");
488 discErosion(srcImageRange(src), destImage(dest), radius);
542 doxygen_overloaded_function(template <...>
void discDilation)
544 template <
class SrcIterator,
class SrcAccessor,
545 class DestIterator,
class DestAccessor>
548 SrcIterator lowerright1, SrcAccessor sa,
549 DestIterator upperleft2, DestAccessor da,
552 vigra_precondition(radius >= 0,
"discDilation(): Radius must be >= 0.");
555 upperleft2, da, radius, 1.0);
558 template <
class SrcIterator,
class SrcAccessor,
559 class DestIterator,
class DestAccessor>
561 discDilation(triple<SrcIterator, SrcIterator, SrcAccessor> src,
562 pair<DestIterator, DestAccessor> dest,
565 vigra_precondition(radius >= 0,
"discDilation(): Radius must be >= 0.");
568 dest.first, dest.second,
572 template <
class T1,
class S1,
576 MultiArrayView<2, T2, S2> dest,
579 vigra_precondition(src.shape() == dest.shape(),
580 "discDilation(): shape mismatch between input and output.");
581 discDilation(srcImageRange(src), destImage(dest), radius);
635 doxygen_overloaded_function(template <...>
void discMedian)
637 template <
class SrcIterator,
class SrcAccessor,
638 class DestIterator,
class DestAccessor>
641 SrcIterator lowerright1, SrcAccessor sa,
642 DestIterator upperleft2, DestAccessor da,
645 vigra_precondition(radius >= 0,
"discMedian(): Radius must be >= 0.");
648 upperleft2, da, radius, 0.5);
651 template <
class SrcIterator,
class SrcAccessor,
652 class DestIterator,
class DestAccessor>
654 discMedian(triple<SrcIterator, SrcIterator, SrcAccessor> src,
655 pair<DestIterator, DestAccessor> dest,
658 vigra_precondition(radius >= 0,
"discMedian(): Radius must be >= 0.");
661 dest.first, dest.second,
665 template <
class T1,
class S1,
668 discMedian(MultiArrayView<2, T1, S1>
const & src,
669 MultiArrayView<2, T2, S2> dest,
672 vigra_precondition(src.shape() == dest.shape(),
673 "discMedian(): shape mismatch between input and output.");
674 discMedian(srcImageRange(src), destImage(dest), radius);
796 template <
class SrcIterator,
class SrcAccessor,
797 class MaskIterator,
class MaskAccessor,
798 class DestIterator,
class DestAccessor>
801 SrcIterator lowerright1, SrcAccessor sa,
802 MaskIterator upperleftm, MaskAccessor mask,
803 DestIterator upperleft2, DestAccessor da,
804 int radius,
float rank)
806 vigra_precondition((rank >= 0.0) && (rank <= 1.0),
807 "discRankOrderFilter(): Rank must be between 0 and 1"
810 vigra_precondition(radius >= 0,
"discRankOrderFilter(): Radius must be >= 0.");
812 int i, x, y, xmax, ymax, xx, yy;
813 int rankpos, winsize, leftsum;
818 std::vector<int> struct_function(radius+1);
819 struct_function[0] = radius;
821 double r2 = (double)radius*radius;
822 for(i=1; i<=radius; ++i)
824 double r = (double) i - 0.5;
828 int w = lowerright1.x - upperleft1.x;
829 int h = lowerright1.y - upperleft1.y;
831 SrcIterator ys(upperleft1);
832 MaskIterator ym(upperleftm);
833 DestIterator yd(upperleft2);
835 for(y=0; y<h; ++y, ++ys.y, ++yd.y, ++ym.y)
848 for(i=0; i<256; ++i) hist[i] = 0;
854 ymax = (y1 < radius) ? y1 : radius;
855 for(yy=0; yy<=ymax; ++yy)
857 xmax = (x1 < struct_function[yy]) ? x1 : struct_function[yy];
858 for(xx=0; xx<=xmax; ++xx)
869 ymax = (y0 < radius) ? y0 : radius;
870 for(yy=1; yy<=ymax; ++yy)
872 xmax = (x1 < struct_function[yy]) ? x1 : struct_function[yy];
873 for(xx=0; xx<=xmax; ++xx)
899 if((
float)(hist[i]+leftsum) / winsize >= rank)
break;
913 for(x=1; x<w; ++x, ++xs.x, ++xd.x, ++xm.x)
922 yy = (y1 < radius) ? y1 : radius;
926 xx = struct_function[yy]+1;
935 if(cur < rankpos) leftsum--;
939 yy = (y0 < radius) ? y0 : radius;
943 xx = struct_function[yy]+1;
946 Diff2D pos(-xx, -yy);
952 if(cur < rankpos) leftsum--;
958 yy = (y1 < radius) ? y1 : radius;
962 xx = struct_function[yy];
971 if(cur < rankpos) leftsum++;
975 yy = (y0 < radius) ? y0 : radius;
979 xx = struct_function[yy];
988 if(cur < rankpos) leftsum++;
1001 for(i=rankpos; i<256; i++)
1010 for(i=rankpos-1; i>=0; i--)
1013 if(leftsum == 0)
break;
1020 if((
float)leftsum / winsize < rank)
1023 for(i=rankpos; i<256; i++)
1025 if((
float)(hist[i]+leftsum) / winsize >= rank)
break;
1033 for(i=rankpos-1; i>=0; i--)
1036 if((
float)leftsum / winsize < rank)
break;
1042 da.set(rankpos, xd);
1053 template <
class SrcIterator,
class SrcAccessor,
1054 class MaskIterator,
class MaskAccessor,
1055 class DestIterator,
class DestAccessor>
1058 pair<MaskIterator, MaskAccessor> mask,
1059 pair<DestIterator, DestAccessor> dest,
1060 int radius,
float rank)
1063 mask.first, mask.second,
1064 dest.first, dest.second,
1068 template <
class T1,
class S1,
1073 MultiArrayView<2, TM, SM>
const & mask,
1074 MultiArrayView<2, T2, S2> dest,
1075 int radius,
float rank)
1077 vigra_precondition(src.shape() == mask.shape() && src.shape() == dest.shape(),
1078 "discRankOrderFilterWithMask(): shape mismatch between input and output.");
1145 template <
class SrcIterator,
class SrcAccessor,
1146 class MaskIterator,
class MaskAccessor,
1147 class DestIterator,
class DestAccessor>
1150 SrcIterator lowerright1, SrcAccessor sa,
1151 MaskIterator upperleftm, MaskAccessor mask,
1152 DestIterator upperleft2, DestAccessor da,
1155 vigra_precondition(radius >= 0,
"discErosionWithMask(): Radius must be >= 0.");
1163 template <
class SrcIterator,
class SrcAccessor,
1164 class MaskIterator,
class MaskAccessor,
1165 class DestIterator,
class DestAccessor>
1168 pair<MaskIterator, MaskAccessor> mask,
1169 pair<DestIterator, DestAccessor> dest,
1172 vigra_precondition(radius >= 0,
"discErosionWithMask(): Radius must be >= 0.");
1175 mask.first, mask.second,
1176 dest.first, dest.second,
1180 template <
class T1,
class S1,
1185 MultiArrayView<2, TM, SM>
const & mask,
1186 MultiArrayView<2, T2, S2> dest,
1189 vigra_precondition(src.shape() == mask.shape() && src.shape() == dest.shape(),
1190 "discErosionWithMask(): shape mismatch between input and output.");
1254 template <
class SrcIterator,
class SrcAccessor,
1255 class MaskIterator,
class MaskAccessor,
1256 class DestIterator,
class DestAccessor>
1259 SrcIterator lowerright1, SrcAccessor sa,
1260 MaskIterator upperleftm, MaskAccessor mask,
1261 DestIterator upperleft2, DestAccessor da,
1264 vigra_precondition(radius >= 0,
"discDilationWithMask(): Radius must be >= 0.");
1272 template <
class SrcIterator,
class SrcAccessor,
1273 class MaskIterator,
class MaskAccessor,
1274 class DestIterator,
class DestAccessor>
1277 pair<MaskIterator, MaskAccessor> mask,
1278 pair<DestIterator, DestAccessor> dest,
1281 vigra_precondition(radius >= 0,
"discDilationWithMask(): Radius must be >= 0.");
1284 mask.first, mask.second,
1285 dest.first, dest.second,
1289 template <
class T1,
class S1,
1294 MultiArrayView<2, TM, SM>
const & mask,
1295 MultiArrayView<2, T2, S2> dest,
1298 vigra_precondition(src.shape() == mask.shape() && src.shape() == dest.shape(),
1299 "discDilationWithMask(): shape mismatch between input and output.");
1363 template <
class SrcIterator,
class SrcAccessor,
1364 class MaskIterator,
class MaskAccessor,
1365 class DestIterator,
class DestAccessor>
1368 SrcIterator lowerright1, SrcAccessor sa,
1369 MaskIterator upperleftm, MaskAccessor mask,
1370 DestIterator upperleft2, DestAccessor da,
1373 vigra_precondition(radius >= 0,
"discMedianWithMask(): Radius must be >= 0.");
1381 template <
class SrcIterator,
class SrcAccessor,
1382 class MaskIterator,
class MaskAccessor,
1383 class DestIterator,
class DestAccessor>
1386 pair<MaskIterator, MaskAccessor> mask,
1387 pair<DestIterator, DestAccessor> dest,
1390 vigra_precondition(radius >= 0,
"discMedianWithMask(): Radius must be >= 0.");
1393 mask.first, mask.second,
1394 dest.first, dest.second,
1398 template <
class T1,
class S1,
1403 MultiArrayView<2, TM, SM>
const & mask,
1404 MultiArrayView<2, T2, S2> dest,
1407 vigra_precondition(src.shape() == mask.shape() && src.shape() == dest.shape(),
1408 "discMedianWithMask(): shape mismatch between input and output.");
1416 #endif // VIGRA_FLATMORPHOLOGY_HXX