37#ifndef VIGRA_SEPARABLECONVOLUTION_HXX
38#define VIGRA_SEPARABLECONVOLUTION_HXX
42#include "numerictraits.hxx"
43#include "imageiteratoradapter.hxx"
44#include "bordertreatment.hxx"
45#include "gaussians.hxx"
46#include "array_vector.hxx"
47#include "multi_shape.hxx"
51template <
class ARITHTYPE>
64template <
class SrcIterator,
class SrcAccessor,
65 class DestIterator,
class DestAccessor,
66 class KernelIterator,
class KernelAccessor>
67void internalConvolveLineOptimistic(SrcIterator is, SrcIterator iend, SrcAccessor sa,
68 DestIterator
id, DestAccessor da,
69 KernelIterator kernel, KernelAccessor ka,
70 int kleft,
int kright)
72 typedef typename PromoteTraits<
73 typename SrcAccessor::value_type,
74 typename KernelAccessor::value_type>::Promote SumType;
76 int w = std::distance( is, iend );
77 int kw = kright - kleft + 1;
78 for(
int x=0; x<w; ++x, ++is, ++id)
80 SrcIterator iss = is + (-kright);
81 KernelIterator ik = kernel + kright;
82 SumType
sum = NumericTraits<SumType>::zero();
84 for(
int k = 0; k < kw; ++k, --ik, ++iss)
86 sum += ka(ik) * sa(iss);
89 da.set(detail::RequiresExplicitCast<
typename
90 DestAccessor::value_type>::cast(
sum),
id);
97template <
class SrcIterator,
class SrcAccessor,
98 class DestIterator,
class DestAccessor>
100copyLineWithBorderTreatment(SrcIterator is, SrcIterator iend, SrcAccessor sa,
101 DestIterator
id, DestAccessor da,
103 int kleft,
int kright,
104 BorderTreatmentMode borderTreatment)
106 int w = std::distance( is, iend );
107 int leftBorder = start - kright;
108 int rightBorder = stop - kleft;
109 int copyEnd = std::min(w, rightBorder);
113 switch(borderTreatment)
115 case BORDER_TREATMENT_WRAP:
117 for(; leftBorder<0; ++leftBorder, ++id)
118 da.set(sa(iend, leftBorder),
id);
121 case BORDER_TREATMENT_AVOID:
131 case BORDER_TREATMENT_REFLECT:
133 for(; leftBorder<0; ++leftBorder, ++id)
134 da.set(sa(is, -leftBorder),
id);
137 case BORDER_TREATMENT_REPEAT:
139 for(; leftBorder<0; ++leftBorder, ++id)
143 case BORDER_TREATMENT_CLIP:
145 vigra_precondition(
false,
146 "copyLineWithBorderTreatment() internal error: not applicable to BORDER_TREATMENT_CLIP.");
149 case BORDER_TREATMENT_ZEROPAD:
151 for(; leftBorder<0; ++leftBorder, ++id)
152 da.set(NumericTraits<typename DestAccessor::value_type>::zero(),
id);
157 vigra_precondition(
false,
158 "copyLineWithBorderTreatment(): Unknown border treatment mode.");
163 SrcIterator iss = is + leftBorder;
164 vigra_invariant( leftBorder < copyEnd,
165 "copyLineWithBorderTreatment(): assertion failed.");
166 for(; leftBorder<copyEnd; ++leftBorder, ++id, ++iss)
169 if(copyEnd < rightBorder)
171 switch(borderTreatment)
173 case BORDER_TREATMENT_WRAP:
175 for(; copyEnd<rightBorder; ++copyEnd, ++id, ++is)
179 case BORDER_TREATMENT_AVOID:
184 case BORDER_TREATMENT_REFLECT:
187 for(; copyEnd<rightBorder; ++copyEnd, ++id, --iss)
191 case BORDER_TREATMENT_REPEAT:
194 for(; copyEnd<rightBorder; ++copyEnd, ++id)
198 case BORDER_TREATMENT_CLIP:
200 vigra_precondition(
false,
201 "copyLineWithBorderTreatment() internal error: not applicable to BORDER_TREATMENT_CLIP.");
204 case BORDER_TREATMENT_ZEROPAD:
206 for(; copyEnd<rightBorder; ++copyEnd, ++id)
207 da.set(NumericTraits<typename DestAccessor::value_type>::zero(),
id);
212 vigra_precondition(
false,
213 "copyLineWithBorderTreatment(): Unknown border treatment mode.");
227template <
class SrcIterator,
class SrcAccessor,
228 class DestIterator,
class DestAccessor,
229 class KernelIterator,
class KernelAccessor>
230void internalConvolveLineWrap(SrcIterator is, SrcIterator iend, SrcAccessor sa,
231 DestIterator
id, DestAccessor da,
232 KernelIterator kernel, KernelAccessor ka,
233 int kleft,
int kright,
234 int start = 0,
int stop = 0)
236 int w = std::distance( is, iend );
238 typedef typename PromoteTraits<
239 typename SrcAccessor::value_type,
240 typename KernelAccessor::value_type>::Promote SumType;
242 SrcIterator ibegin = is;
248 for(
int x=start; x<stop; ++x, ++is, ++id)
250 KernelIterator ik = kernel + kright;
251 SumType
sum = NumericTraits<SumType>::zero();
256 SrcIterator iss = iend + x0;
258 for(; x0; ++x0, --ik, ++iss)
260 sum += ka(ik) * sa(iss);
266 SrcIterator isend = iend;
267 for(; iss != isend ; --ik, ++iss)
269 sum += ka(ik) * sa(iss);
272 int x0 = -kleft - w + x + 1;
275 for(; x0; --x0, --ik, ++iss)
277 sum += ka(ik) * sa(iss);
282 SrcIterator isend = is + (1 - kleft);
283 for(; iss != isend ; --ik, ++iss)
285 sum += ka(ik) * sa(iss);
289 else if(w-x <= -kleft)
291 SrcIterator iss = is + (-kright);
292 SrcIterator isend = iend;
293 for(; iss != isend ; --ik, ++iss)
295 sum += ka(ik) * sa(iss);
298 int x0 = -kleft - w + x + 1;
301 for(; x0; --x0, --ik, ++iss)
303 sum += ka(ik) * sa(iss);
308 SrcIterator iss = is - kright;
309 SrcIterator isend = is + (1 - kleft);
310 for(; iss != isend ; --ik, ++iss)
312 sum += ka(ik) * sa(iss);
316 da.set(detail::RequiresExplicitCast<
typename
317 DestAccessor::value_type>::cast(
sum),
id);
327template <
class SrcIterator,
class SrcAccessor,
328 class DestIterator,
class DestAccessor,
329 class KernelIterator,
class KernelAccessor,
331void internalConvolveLineClip(SrcIterator is, SrcIterator iend, SrcAccessor sa,
332 DestIterator
id, DestAccessor da,
333 KernelIterator kernel, KernelAccessor ka,
334 int kleft,
int kright, Norm
norm,
335 int start = 0,
int stop = 0)
337 int w = std::distance( is, iend );
339 typedef typename PromoteTraits<
340 typename SrcAccessor::value_type,
341 typename KernelAccessor::value_type>::Promote SumType;
343 SrcIterator ibegin = is;
349 for(
int x=start; x<stop; ++x, ++is, ++id)
351 KernelIterator ik = kernel + kright;
352 SumType
sum = NumericTraits<SumType>::zero();
357 Norm clipped = NumericTraits<Norm>::zero();
359 for(; x0; ++x0, --ik)
364 SrcIterator iss = ibegin;
367 SrcIterator isend = iend;
368 for(; iss != isend ; --ik, ++iss)
370 sum += ka(ik) * sa(iss);
373 int x0 = -kleft - w + x + 1;
375 for(; x0; --x0, --ik)
382 SrcIterator isend = is + (1 - kleft);
383 for(; iss != isend ; --ik, ++iss)
385 sum += ka(ik) * sa(iss);
391 else if(w-x <= -kleft)
393 SrcIterator iss = is + (-kright);
394 SrcIterator isend = iend;
395 for(; iss != isend ; --ik, ++iss)
397 sum += ka(ik) * sa(iss);
400 Norm clipped = NumericTraits<Norm>::zero();
402 int x0 = -kleft - w + x + 1;
404 for(; x0; --x0, --ik)
413 SrcIterator iss = is + (-kright);
414 SrcIterator isend = is + (1 - kleft);
415 for(; iss != isend ; --ik, ++iss)
417 sum += ka(ik) * sa(iss);
421 da.set(detail::RequiresExplicitCast<
typename
422 DestAccessor::value_type>::cast(
sum),
id);
432template <
class SrcIterator,
class SrcAccessor,
433 class DestIterator,
class DestAccessor,
434 class KernelIterator,
class KernelAccessor>
435void internalConvolveLineZeropad(SrcIterator is, SrcIterator iend, SrcAccessor sa,
436 DestIterator
id, DestAccessor da,
437 KernelIterator kernel, KernelAccessor ka,
438 int kleft,
int kright,
439 int start = 0,
int stop = 0)
441 int w = std::distance( is, iend );
443 typedef typename PromoteTraits<
444 typename SrcAccessor::value_type,
445 typename KernelAccessor::value_type>::Promote SumType;
447 SrcIterator ibegin = is;
453 for(
int x=start; x<stop; ++x, ++is, ++id)
455 SumType
sum = NumericTraits<SumType>::zero();
459 KernelIterator ik = kernel + x;
460 SrcIterator iss = ibegin;
464 SrcIterator isend = iend;
465 for(; iss != isend ; --ik, ++iss)
467 sum += ka(ik) * sa(iss);
472 SrcIterator isend = is + (1 - kleft);
473 for(; iss != isend ; --ik, ++iss)
475 sum += ka(ik) * sa(iss);
479 else if(w-x <= -kleft)
481 KernelIterator ik = kernel + kright;
482 SrcIterator iss = is + (-kright);
483 SrcIterator isend = iend;
484 for(; iss != isend ; --ik, ++iss)
486 sum += ka(ik) * sa(iss);
491 KernelIterator ik = kernel + kright;
492 SrcIterator iss = is + (-kright);
493 SrcIterator isend = is + (1 - kleft);
494 for(; iss != isend ; --ik, ++iss)
496 sum += ka(ik) * sa(iss);
500 da.set(detail::RequiresExplicitCast<
typename
501 DestAccessor::value_type>::cast(
sum),
id);
511template <
class SrcIterator,
class SrcAccessor,
512 class DestIterator,
class DestAccessor,
513 class KernelIterator,
class KernelAccessor>
514void internalConvolveLineReflect(SrcIterator is, SrcIterator iend, SrcAccessor sa,
515 DestIterator
id, DestAccessor da,
516 KernelIterator kernel, KernelAccessor ka,
517 int kleft,
int kright,
518 int start = 0,
int stop = 0)
520 int w = std::distance( is, iend );
522 typedef typename PromoteTraits<
523 typename SrcAccessor::value_type,
524 typename KernelAccessor::value_type>::Promote SumType;
526 SrcIterator ibegin = is;
532 for(
int x=start; x<stop; ++x, ++is, ++id)
534 KernelIterator ik = kernel + kright;
535 SumType
sum = NumericTraits<SumType>::zero();
540 SrcIterator iss = ibegin - x0;
542 for(; x0; ++x0, --ik, --iss)
544 sum += ka(ik) * sa(iss);
549 SrcIterator isend = iend;
550 for(; iss != isend ; --ik, ++iss)
552 sum += ka(ik) * sa(iss);
555 int x0 = -kleft - w + x + 1;
558 for(; x0; --x0, --ik, --iss)
560 sum += ka(ik) * sa(iss);
565 SrcIterator isend = is + (1 - kleft);
566 for(; iss != isend ; --ik, ++iss)
568 sum += ka(ik) * sa(iss);
572 else if(w-x <= -kleft)
574 SrcIterator iss = is + (-kright);
575 SrcIterator isend = iend;
576 for(; iss != isend ; --ik, ++iss)
578 sum += ka(ik) * sa(iss);
581 int x0 = -kleft - w + x + 1;
584 for(; x0; --x0, --ik, --iss)
586 sum += ka(ik) * sa(iss);
591 SrcIterator iss = is + (-kright);
592 SrcIterator isend = is + (1 - kleft);
593 for(; iss != isend ; --ik, ++iss)
595 sum += ka(ik) * sa(iss);
599 da.set(detail::RequiresExplicitCast<
typename
600 DestAccessor::value_type>::cast(
sum),
id);
610template <
class SrcIterator,
class SrcAccessor,
611 class DestIterator,
class DestAccessor,
612 class KernelIterator,
class KernelAccessor>
613void internalConvolveLineRepeat(SrcIterator is, SrcIterator iend, SrcAccessor sa,
614 DestIterator
id, DestAccessor da,
615 KernelIterator kernel, KernelAccessor ka,
616 int kleft,
int kright,
617 int start = 0,
int stop = 0)
619 int w = std::distance( is, iend );
621 typedef typename PromoteTraits<
622 typename SrcAccessor::value_type,
623 typename KernelAccessor::value_type>::Promote SumType;
625 SrcIterator ibegin = is;
631 for(
int x=start; x<stop; ++x, ++is, ++id)
633 KernelIterator ik = kernel + kright;
634 SumType
sum = NumericTraits<SumType>::zero();
639 SrcIterator iss = ibegin;
641 for(; x0; ++x0, --ik)
643 sum += ka(ik) * sa(iss);
648 SrcIterator isend = iend;
649 for(; iss != isend ; --ik, ++iss)
651 sum += ka(ik) * sa(iss);
654 int x0 = -kleft - w + x + 1;
657 for(; x0; --x0, --ik)
659 sum += ka(ik) * sa(iss);
664 SrcIterator isend = is + (1 - kleft);
665 for(; iss != isend ; --ik, ++iss)
667 sum += ka(ik) * sa(iss);
671 else if(w-x <= -kleft)
673 SrcIterator iss = is + (-kright);
674 SrcIterator isend = iend;
675 for(; iss != isend ; --ik, ++iss)
677 sum += ka(ik) * sa(iss);
680 int x0 = -kleft - w + x + 1;
683 for(; x0; --x0, --ik)
685 sum += ka(ik) * sa(iss);
690 SrcIterator iss = is + (-kright);
691 SrcIterator isend = is + (1 - kleft);
692 for(; iss != isend ; --ik, ++iss)
694 sum += ka(ik) * sa(iss);
698 da.set(detail::RequiresExplicitCast<
typename
699 DestAccessor::value_type>::cast(
sum),
id);
709template <
class SrcIterator,
class SrcAccessor,
710 class DestIterator,
class DestAccessor,
711 class KernelIterator,
class KernelAccessor>
712void internalConvolveLineAvoid(SrcIterator is, SrcIterator iend, SrcAccessor sa,
713 DestIterator
id, DestAccessor da,
714 KernelIterator kernel, KernelAccessor ka,
715 int kleft,
int kright,
716 int start = 0,
int stop = 0)
718 int w = std::distance( is, iend );
725 id += kright - start;
736 typedef typename PromoteTraits<
737 typename SrcAccessor::value_type,
738 typename KernelAccessor::value_type>::Promote SumType;
742 for(
int x=start; x<stop; ++x, ++is, ++id)
744 KernelIterator ik = kernel + kright;
745 SumType
sum = NumericTraits<SumType>::zero();
747 SrcIterator iss = is + (-kright);
748 SrcIterator isend = is + (1 - kleft);
749 for(; iss != isend ; --ik, ++iss)
751 sum += ka(ik) * sa(iss);
754 da.set(detail::RequiresExplicitCast<
typename
755 DestAccessor::value_type>::cast(
sum),
id);
901template <
class SrcIterator,
class SrcAccessor,
902 class DestIterator,
class DestAccessor,
903 class KernelIterator,
class KernelAccessor>
904void convolveLine(SrcIterator is, SrcIterator iend, SrcAccessor sa,
905 DestIterator
id, DestAccessor da,
906 KernelIterator ik, KernelAccessor ka,
907 int kleft,
int kright, BorderTreatmentMode border,
908 int start = 0,
int stop = 0)
910 vigra_precondition(kleft <= 0,
911 "convolveLine(): kleft must be <= 0.\n");
912 vigra_precondition(kright >= 0,
913 "convolveLine(): kright must be >= 0.\n");
916 int w = std::distance( is, iend );
918 vigra_precondition(w >= std::max(kright, -kleft) + 1,
919 "convolveLine(): kernel longer than line.\n");
922 vigra_precondition(0 <= start && start < stop && stop <= w,
923 "convolveLine(): invalid subrange (start, stop).\n");
925 typedef typename PromoteTraits<
926 typename SrcAccessor::value_type,
927 typename KernelAccessor::value_type>::Promote SumType;
931 case BORDER_TREATMENT_WRAP:
933 internalConvolveLineWrap(is, iend, sa,
id, da, ik, ka, kleft, kright, start, stop);
936 case BORDER_TREATMENT_AVOID:
938 internalConvolveLineAvoid(is, iend, sa,
id, da, ik, ka, kleft, kright, start, stop);
941 case BORDER_TREATMENT_REFLECT:
943 internalConvolveLineReflect(is, iend, sa,
id, da, ik, ka, kleft, kright, start, stop);
946 case BORDER_TREATMENT_REPEAT:
948 internalConvolveLineRepeat(is, iend, sa,
id, da, ik, ka, kleft, kright, start, stop);
951 case BORDER_TREATMENT_CLIP:
954 typedef typename KernelAccessor::value_type KT;
955 KT
norm = NumericTraits<KT>::zero();
956 KernelIterator iik = ik + kleft;
957 for(
int i=kleft; i<=kright; ++i, ++iik)
960 vigra_precondition(
norm != NumericTraits<KT>::zero(),
961 "convolveLine(): Norm of kernel must be != 0"
962 " in mode BORDER_TREATMENT_CLIP.\n");
964 internalConvolveLineClip(is, iend, sa,
id, da, ik, ka, kleft, kright,
norm, start, stop);
967 case BORDER_TREATMENT_ZEROPAD:
969 internalConvolveLineZeropad(is, iend, sa,
id, da, ik, ka, kleft, kright, start, stop);
974 vigra_precondition(0,
975 "convolveLine(): Unknown border treatment mode.\n");
980template <
class SrcIterator,
class SrcAccessor,
981 class DestIterator,
class DestAccessor,
982 class KernelIterator,
class KernelAccessor>
984void convolveLine(triple<SrcIterator, SrcIterator, SrcAccessor> src,
985 pair<DestIterator, DestAccessor> dest,
986 tuple5<KernelIterator, KernelAccessor,
987 int,
int, BorderTreatmentMode> kernel,
988 int start = 0,
int stop = 0)
991 dest.first, dest.second,
992 kernel.first, kernel.second,
993 kernel.third, kernel.fourth, kernel.fifth, start, stop);
1090template <
class SrcIterator,
class SrcAccessor,
1091 class DestIterator,
class DestAccessor,
1092 class KernelIterator,
class KernelAccessor>
1094 SrcIterator slowerright, SrcAccessor sa,
1095 DestIterator dupperleft, DestAccessor da,
1096 KernelIterator ik, KernelAccessor ka,
1097 int kleft,
int kright, BorderTreatmentMode border)
1099 vigra_precondition(kleft <= 0,
1100 "separableConvolveX(): kleft must be <= 0.\n");
1101 vigra_precondition(kright >= 0,
1102 "separableConvolveX(): kright must be >= 0.\n");
1104 int w = slowerright.x - supperleft.x;
1105 int h = slowerright.y - supperleft.y;
1107 vigra_precondition(w >= std::max(kright, -kleft) + 1,
1108 "separableConvolveX(): kernel longer than line\n");
1112 for(y=0; y<h; ++y, ++supperleft.y, ++dupperleft.y)
1114 typename SrcIterator::row_iterator rs = supperleft.rowIterator();
1115 typename DestIterator::row_iterator rd = dupperleft.rowIterator();
1118 ik, ka, kleft, kright, border);
1122template <
class SrcIterator,
class SrcAccessor,
1123 class DestIterator,
class DestAccessor,
1124 class KernelIterator,
class KernelAccessor>
1127 pair<DestIterator, DestAccessor> dest,
1128 tuple5<KernelIterator, KernelAccessor,
1129 int,
int, BorderTreatmentMode> kernel)
1132 dest.first, dest.second,
1133 kernel.first, kernel.second,
1134 kernel.third, kernel.fourth, kernel.fifth);
1137template <
class T1,
class S1,
1145 vigra_precondition(src.shape() == dest.shape(),
1146 "separableConvolveX(): shape mismatch between input and output.");
1148 destImage(dest), kernel1d(kernel));
1245template <
class SrcIterator,
class SrcAccessor,
1246 class DestIterator,
class DestAccessor,
1247 class KernelIterator,
class KernelAccessor>
1249 SrcIterator slowerright, SrcAccessor sa,
1250 DestIterator dupperleft, DestAccessor da,
1251 KernelIterator ik, KernelAccessor ka,
1252 int kleft,
int kright, BorderTreatmentMode border)
1254 vigra_precondition(kleft <= 0,
1255 "separableConvolveY(): kleft must be <= 0.\n");
1256 vigra_precondition(kright >= 0,
1257 "separableConvolveY(): kright must be >= 0.\n");
1259 int w = slowerright.x - supperleft.x;
1260 int h = slowerright.y - supperleft.y;
1262 vigra_precondition(h >= std::max(kright, -kleft) + 1,
1263 "separableConvolveY(): kernel longer than line\n");
1267 for(x=0; x<w; ++x, ++supperleft.x, ++dupperleft.x)
1269 typename SrcIterator::column_iterator cs = supperleft.columnIterator();
1270 typename DestIterator::column_iterator cd = dupperleft.columnIterator();
1273 ik, ka, kleft, kright, border);
1277template <
class SrcIterator,
class SrcAccessor,
1278 class DestIterator,
class DestAccessor,
1279 class KernelIterator,
class KernelAccessor>
1282 pair<DestIterator, DestAccessor> dest,
1283 tuple5<KernelIterator, KernelAccessor,
1284 int,
int, BorderTreatmentMode> kernel)
1287 dest.first, dest.second,
1288 kernel.first, kernel.second,
1289 kernel.third, kernel.fourth, kernel.fifth);
1292template <
class T1,
class S1,
1300 vigra_precondition(src.shape() == dest.shape(),
1301 "separableConvolveY(): shape mismatch between input and output.");
1303 destImage(dest), kernel1d(kernel));
1370template <
class ARITHTYPE =
double>
1411 : iter_(i), base_(i),
1412 count_(count), sum_(count),
1417#if _MSC_VER >= 1900 || __cplusplus >= 201103L
1420 throw(PreconditionViolation)
1423 vigra_precondition(count_ == 1 || count_ == sum_,
1424 "Kernel1D::initExplicitly(): "
1425 "Wrong number of init values.");
1450 static value_type one() {
return NumericTraits<value_type>::one(); }
1460 border_treatment_(BORDER_TREATMENT_REFLECT),
1463 kernel_.push_back(norm_);
1469 : kernel_(k.kernel_),
1472 border_treatment_(k.border_treatment_),
1495 border_treatment_ = k.border_treatment_;
1497 kernel_ = k.kernel_;
1520 int size = right_ - left_ + 1;
1521 for(
unsigned int i=0; i<kernel_.size(); ++i) kernel_[i] = v;
1522 norm_ = (double)
size*v;
1524 return InitProxy(kernel_.begin(),
size, norm_);
1557 void initGaussian(
double std_dev, value_type
norm,
double windowRatio = 0.0);
1740 this->
initExplicitly(-2, 2) = 0.03134, 0.24, 0.45732, 0.24, 0.03134;
1768 this->
initExplicitly(-2, 2) = 0.04255, 0.241, 0.4329, 0.241, 0.04255;
1796 this->
initExplicitly(-2, 2) = 0.0243, 0.23556, 0.48028, 0.23556, 0.0243;
1831 vigra_precondition(a >= 0.0 && a <= 0.125,
1832 "Kernel1D::initBurtFilter(): 0 <= a <= 0.125 required.");
2067 this->
initExplicitly(-2, 2) = 0.22075, 0.117, -0.6755, 0.117, 0.22075;
2107 vigra_precondition(
left <= 0,
2108 "Kernel1D::initExplicitly(): left border must be <= 0.");
2109 vigra_precondition(
right >= 0,
2110 "Kernel1D::initExplicitly(): right border must be >= 0.");
2130 return kernel_.begin() -
left();
2148 return kernel_[location -
left()];
2151 const_reference
operator[](
int location)
const
2153 return kernel_[location -
left()];
2166 int size()
const {
return right_ - left_ + 1; }
2171 {
return border_treatment_; }
2176 { border_treatment_ = new_mode; }
2186 normalize(value_type
norm,
unsigned int derivativeOrder = 0,
double offset = 0.0);
2205 InternalVector kernel_;
2207 BorderTreatmentMode border_treatment_;
2211template <
class ARITHTYPE>
2213 unsigned int derivativeOrder,
2216 typedef typename NumericTraits<value_type>::RealPromote TmpType;
2220 TmpType
sum = NumericTraits<TmpType>::zero();
2222 if(derivativeOrder == 0)
2224 for(; k < kernel_.end(); ++k)
2231 unsigned int faculty = 1;
2232 for(
unsigned int i = 2; i <= derivativeOrder; ++i)
2234 for(
double x =
left() + offset; k < kernel_.end(); ++x, ++k)
2236 sum = TmpType(
sum + *k * VIGRA_CSTD::pow(-x,
int(derivativeOrder)) / faculty);
2240 vigra_precondition(
sum != NumericTraits<value_type>::zero(),
2241 "Kernel1D<ARITHTYPE>::normalize(): "
2242 "Cannot normalize a kernel with sum = 0");
2245 k = kernel_.begin();
2246 for(; k != kernel_.end(); ++k)
2256template <
class ARITHTYPE>
2262 vigra_precondition(std_dev >= 0.0,
2263 "Kernel1D::initGaussian(): Standard deviation must be >= 0.");
2264 vigra_precondition(windowRatio >= 0.0,
2265 "Kernel1D::initGaussian(): windowRatio must be >= 0.");
2273 if (windowRatio == 0.0)
2274 radius = (int)(3.0 * std_dev + 0.5);
2276 radius = (int)(windowRatio * std_dev + 0.5);
2281 kernel_.erase(kernel_.begin(), kernel_.end());
2282 kernel_.reserve(radius*2+1);
2284 for(ARITHTYPE x = -(ARITHTYPE)radius; x <= (ARITHTYPE)radius; ++x)
2286 kernel_.push_back(gauss(x));
2293 kernel_.erase(kernel_.begin(), kernel_.end());
2294 kernel_.push_back(1.0);
2305 border_treatment_ = BORDER_TREATMENT_REFLECT;
2310template <
class ARITHTYPE>
2315 vigra_precondition(std_dev >= 0.0,
2316 "Kernel1D::initDiscreteGaussian(): Standard deviation must be >= 0.");
2321 int radius = (int)(3.0*std_dev + 0.5);
2325 double f = 2.0 / std_dev / std_dev;
2328 int maxIndex = (int)(2.0 * (radius + 5.0 * VIGRA_CSTD::sqrt((
double)radius)) + 0.5);
2329 InternalVector warray(maxIndex+1);
2330 warray[maxIndex] = 0.0;
2331 warray[maxIndex-1] = 1.0;
2333 for(
int i = maxIndex-2; i >= radius; --i)
2335 warray[i] = warray[i+2] + f * (i+1) * warray[i+1];
2336 if(warray[i] > 1.0e40)
2338 warray[i+1] /= warray[i];
2345 double er = VIGRA_CSTD::exp(-radius*radius / (2.0*std_dev*std_dev));
2346 warray[radius+1] = er * warray[radius+1] / warray[radius];
2347 warray[radius] = er;
2349 for(
int i = radius-1; i >= 0; --i)
2351 warray[i] = warray[i+2] + f * (i+1) * warray[i+1];
2355 double scale =
norm / (2*er - warray[0]);
2360 for(
int i=0; i<=radius; ++i)
2362 c[i] = c[-i] = warray[i] * scale;
2367 kernel_.erase(kernel_.begin(), kernel_.end());
2368 kernel_.push_back(
norm);
2376 border_treatment_ = BORDER_TREATMENT_REFLECT;
2381template <
class ARITHTYPE>
2388 vigra_precondition(order >= 0,
2389 "Kernel1D::initGaussianDerivative(): Order must be >= 0.");
2397 vigra_precondition(std_dev > 0.0,
2398 "Kernel1D::initGaussianDerivative(): "
2399 "Standard deviation must be > 0.");
2400 vigra_precondition(windowRatio >= 0.0,
2401 "Kernel1D::initGaussianDerivative(): windowRatio must be >= 0.");
2407 if(windowRatio == 0.0)
2408 radius = (int)((3.0 + 0.5 * order) * std_dev + 0.5);
2410 radius = (int)(windowRatio * std_dev + 0.5);
2416 kernel_.reserve(radius*2+1);
2421 for(ARITHTYPE x = -(ARITHTYPE)radius; x <= (ARITHTYPE)radius; ++x)
2423 kernel_.push_back(gauss(x));
2424 dc += kernel_[kernel_.size()-1];
2426 dc = ARITHTYPE(dc / (2.0*radius + 1.0));
2432 for(
unsigned int i=0; i < kernel_.size(); ++i)
2448 border_treatment_ = BORDER_TREATMENT_REFLECT;
2453template <
class ARITHTYPE>
2458 vigra_precondition(radius > 0,
2459 "Kernel1D::initBinomial(): Radius must be > 0.");
2462 InternalVector(radius*2+1).swap(kernel_);
2463 typename InternalVector::iterator x = kernel_.begin() + radius;
2467 for(
int j=radius-1; j>=-radius; --j)
2469 x[j] = 0.5 * x[j+1];
2470 for(
int i=j+1; i<radius; ++i)
2472 x[i] = 0.5 * (x[i] + x[i+1]);
2482 border_treatment_ = BORDER_TREATMENT_REFLECT;
2487template <
class ARITHTYPE>
2492 vigra_precondition(radius > 0,
2493 "Kernel1D::initAveraging(): Radius must be > 0.");
2496 double scale = 1.0 / (radius * 2 + 1);
2499 kernel_.erase(kernel_.begin(), kernel_.end());
2500 kernel_.reserve(radius*2+1);
2502 for(
int i=0; i<=radius*2+1; ++i)
2504 kernel_.push_back(scale *
norm);
2512 border_treatment_ = BORDER_TREATMENT_CLIP;
2517template <
class ARITHTYPE>
2521 kernel_.erase(kernel_.begin(), kernel_.end());
2524 kernel_.push_back(ARITHTYPE(0.5 *
norm));
2525 kernel_.push_back(ARITHTYPE(0.0 *
norm));
2526 kernel_.push_back(ARITHTYPE(-0.5 *
norm));
2534 border_treatment_ = BORDER_TREATMENT_REFLECT;
2545template <
class KernelIterator,
class KernelAccessor>
2547tuple5<KernelIterator, KernelAccessor, int, int, BorderTreatmentMode>
2548kernel1d(KernelIterator ik, KernelAccessor ka,
2549 int kleft,
int kright, BorderTreatmentMode border)
2552 tuple5<KernelIterator, KernelAccessor, int, int, BorderTreatmentMode>(
2553 ik, ka, kleft, kright, border);
2559 int, int, BorderTreatmentMode>
2565 int, int, BorderTreatmentMode>(
2568 k.left(), k.right(),
2569 k.borderTreatment());
2575 int, int, BorderTreatmentMode>
2576kernel1d(
Kernel1D<T> const & k, BorderTreatmentMode border)
2581 int, int, BorderTreatmentMode>(
2584 k.left(), k.right(),
const_iterator begin() const
Definition array_vector.hxx:223
Definition array_vector.hxx:514
Definition gaussians.hxx:64
Generic 1 dimensional convolution kernel.
Definition separableconvolution.hxx:1372
void initBinomial(int radius)
Definition separableconvolution.hxx:1858
void initOptimalFirstDerivativeSmoothing5()
Definition separableconvolution.hxx:1766
void initSecondDifference3()
Definition separableconvolution.hxx:2004
void initOptimalSecondDerivativeSmoothing3()
Definition separableconvolution.hxx:1712
InternalVector::reference reference
Definition separableconvolution.hxx:1382
void initBurtFilter(double a=0.04785)
Definition separableconvolution.hxx:1829
void initDiscreteGaussian(double std_dev)
Definition separableconvolution.hxx:1589
void initBackwardDifference()
Definition separableconvolution.hxx:1960
void initOptimalFirstDerivative5()
Definition separableconvolution.hxx:2036
int right() const
Definition separableconvolution.hxx:2162
value_type norm() const
Definition separableconvolution.hxx:2180
reference operator[](int location)
Definition separableconvolution.hxx:2146
Kernel1D(Kernel1D< U > const &k)
Definition separableconvolution.hxx:1479
void initGaussian(double std_dev, value_type norm, double windowRatio=0.0)
Definition separableconvolution.hxx:2258
InitProxy operator=(value_type const &v)
Definition separableconvolution.hxx:1518
void initSymmetricGradient()
Definition separableconvolution.hxx:1913
BorderTreatmentMode borderTreatment() const
Definition separableconvolution.hxx:2170
void setBorderTreatment(BorderTreatmentMode new_mode)
Definition separableconvolution.hxx:2175
StandardAccessor< ARITHTYPE > Accessor
Definition separableconvolution.hxx:1402
void initOptimalSmoothing5()
Definition separableconvolution.hxx:1738
ConstAccessor accessor() const
Definition separableconvolution.hxx:2198
void initGaussianDerivative(double std_dev, int order)
Definition separableconvolution.hxx:1631
void normalize(value_type norm, unsigned int derivativeOrder=0, double offset=0.0)
Definition separableconvolution.hxx:2212
void initDiscreteGaussian(double std_dev, value_type norm)
Definition separableconvolution.hxx:2312
InternalVector::value_type value_type
Definition separableconvolution.hxx:1378
void initGaussianDerivative(double std_dev, int order, value_type norm, double windowRatio=0.0)
Definition separableconvolution.hxx:2383
InternalVector::iterator iterator
Definition separableconvolution.hxx:1394
~Kernel1D()
Definition separableconvolution.hxx:1529
void initSymmetricDifference()
Definition separableconvolution.hxx:1983
void initAveraging(int radius)
Definition separableconvolution.hxx:1884
StandardConstAccessor< ARITHTYPE > ConstAccessor
Definition separableconvolution.hxx:1406
Kernel1D(Kernel1D const &k)
Definition separableconvolution.hxx:1468
void initOptimalSecondDerivative5()
Definition separableconvolution.hxx:2065
InternalVector::const_iterator const_iterator
Definition separableconvolution.hxx:1398
InternalVector::const_reference const_reference
Definition separableconvolution.hxx:1386
void initAveraging(int radius, value_type norm)
Definition separableconvolution.hxx:2489
void initSymmetricGradient(value_type norm)
Definition separableconvolution.hxx:1903
void initGaussian(double std_dev)
Definition separableconvolution.hxx:1561
void initOptimalSecondDerivativeSmoothing5()
Definition separableconvolution.hxx:1794
int left() const
Definition separableconvolution.hxx:2158
Accessor accessor()
Definition separableconvolution.hxx:2202
Kernel1D()
Definition separableconvolution.hxx:1456
void initBinomial(int radius, value_type norm)
Definition separableconvolution.hxx:2455
void normalize()
Definition separableconvolution.hxx:2191
void initForwardDifference()
Definition separableconvolution.hxx:1936
InternalVector::iterator Iterator
Definition separableconvolution.hxx:1390
Kernel1D & initExplicitly(int left, int right)
Definition separableconvolution.hxx:2105
void initOptimalSmoothing3()
Definition separableconvolution.hxx:1656
void initOptimalFirstDerivativeSmoothing3()
Definition separableconvolution.hxx:1684
int size() const
Definition separableconvolution.hxx:2166
iterator center()
Definition separableconvolution.hxx:2128
Kernel1D & operator=(Kernel1D const &k)
Definition separableconvolution.hxx:1489
Base class for, and view to, MultiArray.
Definition multi_array.hxx:705
Encapsulate access to the values an iterator points to.
Definition accessor.hxx:134
Encapsulate read access to the values an iterator points to.
Definition accessor.hxx:270
void convolveLine(...)
Performs a 1-dimensional convolution of the source signal using the given kernel.
void separableConvolveX(...)
Performs a 1 dimensional convolution in x direction.
FFTWComplex< R >::NormType norm(const FFTWComplex< R > &a)
norm (= magnitude)
Definition fftw3.hxx:1037
void separableConvolveY(...)
Performs a 1 dimensional convolution in y direction.
NumericTraits< V >::Promote sum(TinyVectorBase< V, SIZE, D1, D2 > const &l)
sum of the vector's elements
Definition tinyvector.hxx:2073