36 #ifndef VIGRA_ACCUMULATOR_HXX
37 #define VIGRA_ACCUMULATOR_HXX
40 #pragma warning (disable: 4503)
43 #include "accumulator-grammar.hxx"
45 #include "metaprogramming.hxx"
46 #include "bit_array.hxx"
47 #include "static_assert.hxx"
48 #include "mathutil.hxx"
50 #include "multi_iterator_coupled.hxx"
52 #include "multi_math.hxx"
53 #include "eigensystem.hxx"
54 #include "histogram.hxx"
55 #include "polygon.hxx"
56 #include "functorexpression.hxx"
57 #include "labelimage.hxx"
388 template <
class T01=void,
class T02=void,
class T03=void,
class T04=void,
class T05=void,
389 class T06=void,
class T07=void,
class T08=void,
class T09=void,
class T10=void,
390 class T11=void,
class T12=void,
class T13=void,
class T14=void,
class T15=void,
391 class T16=void,
class T17=void,
class T18=void,
class T19=void,
class T20=
void>
393 :
public MakeTypeList<
394 typename StandardizeTag<T01>::type, typename StandardizeTag<T02>::type, typename StandardizeTag<T03>::type,
395 typename StandardizeTag<T04>::type, typename StandardizeTag<T05>::type, typename StandardizeTag<T06>::type,
396 typename StandardizeTag<T07>::type, typename StandardizeTag<T08>::type, typename StandardizeTag<T09>::type,
397 typename StandardizeTag<T10>::type, typename StandardizeTag<T11>::type, typename StandardizeTag<T12>::type,
398 typename StandardizeTag<T13>::type, typename StandardizeTag<T14>::type, typename StandardizeTag<T15>::type,
399 typename StandardizeTag<T16>::type, typename StandardizeTag<T17>::type, typename StandardizeTag<T18>::type,
400 typename StandardizeTag<T19>::type, typename StandardizeTag<T20>::type
405 template <
class T01,
class T02,
class T03,
class T04,
class T05,
406 class T06,
class T07,
class T08,
class T09,
class T10,
407 class T11,
class T12,
class T13,
class T14,
class T15,
408 class T16,
class T17,
class T18,
class T19,
class T20>
409 struct StandardizeTag<
Select<T01, T02, T03, T04, T05,
410 T06, T07, T08, T09, T10,
411 T11, T12, T13, T14, T15,
412 T16, T17, T18, T19, T20>,
413 Select<T01, T02, T03, T04, T05,
414 T06, T07, T08, T09, T10,
415 T11, T12, T13, T14, T15,
416 T16, T17, T18, T19, T20> >
418 typedef typename Select<T01, T02, T03, T04, T05,
419 T06, T07, T08, T09, T10,
420 T11, T12, T13, T14, T15,
421 T16, T17, T18, T19, T20>::type type;
424 struct AccumulatorBegin
426 typedef Select<> Dependencies;
428 static std::string name()
430 return "AccumulatorBegin (internal)";
435 template <
class T,
class BASE>
442 struct AccumulatorEnd;
447 struct LabelDispatchTag;
449 template <
class T,
class TAG,
class CHAIN>
450 struct HandleArgSelector;
452 struct Error__Global_statistics_are_only_defined_for_AccumulatorChainArray;
462 typedef Select<> Dependencies;
464 static std::string name()
466 return std::string(
"LabelArg<") +
asString(INDEX) +
"> (internal)";
471 template <
class T,
class BASE>
475 typedef LabelArgTag Tag;
476 typedef void value_type;
477 typedef void result_type;
479 static const int value = INDEX;
480 static const unsigned int workInPass = 0;
488 typedef Select<> Dependencies;
490 static std::string name()
492 return std::string(
"CoordArg<") +
asString(INDEX) +
"> (internal)";
497 template <
class T,
class BASE>
501 typedef CoordArgTag Tag;
502 typedef void value_type;
503 typedef void result_type;
505 static const int value = INDEX;
506 static const unsigned int workInPass = 0;
510 template <
class T,
class TAG,
class NEXT=AccumulatorEnd>
511 struct AccumulatorBase;
513 template <
class Tag,
class A>
516 template <
class Tag,
class A,
class TargetTag=
typename A::Tag>
517 struct LookupDependency;
519 #ifndef _MSC_VER // compiler bug? (causes 'ambiguous overload error')
521 template <
class TAG,
class A>
522 typename LookupTag<TAG, A>::reference
525 template <
class TAG,
class A>
526 typename LookupDependency<TAG, A>::result_type
527 getDependency(A
const & a);
531 namespace acc_detail {
542 struct PushArgTagToTail
547 #define VIGRA_PUSHARGTAG(TAG) \
548 template <int INDEX, class TAIL> \
549 struct PushArgTagToTail<TypeList<TAG<INDEX>, TAIL> > \
551 typedef typename Push<TAIL, TypeList<TAG<INDEX> > >::type type; \
554 VIGRA_PUSHARGTAG(DataArg)
555 VIGRA_PUSHARGTAG(WeightArg)
556 VIGRA_PUSHARGTAG(CoordArg)
557 VIGRA_PUSHARGTAG(LabelArg)
559 #undef VIGRA_PUSHARGTAG
565 struct AddDependencies;
567 template <
class HEAD,
class TAIL>
568 struct AddDependencies<TypeList<HEAD, TAIL> >
570 typedef typename AddDependencies<TAIL>::type TailWithDependencies;
571 typedef typename StandardizeDependencies<HEAD>::type HeadDependencies;
572 typedef typename AddDependencies<HeadDependencies>::type TransitiveHeadDependencies;
573 typedef TypeList<HEAD, TransitiveHeadDependencies> HeadWithDependencies;
574 typedef typename PushUnique<HeadWithDependencies, TailWithDependencies>::type UnsortedDependencies;
575 typedef typename PushArgTagToTail<UnsortedDependencies>::type type;
579 struct AddDependencies<void>
586 template <
class Dependencies>
587 struct ActivateDependencies;
589 template <
class HEAD,
class TAIL>
590 struct ActivateDependencies<TypeList<HEAD, TAIL> >
592 template <
class Chain,
class ActiveFlags>
593 static void exec(ActiveFlags & flags)
595 LookupTag<HEAD, Chain>::type::activateImpl(flags);
596 ActivateDependencies<TAIL>::template exec<Chain>(flags);
599 template <
class Chain,
class ActiveFlags,
class GlobalFlags>
600 static void exec(ActiveFlags & flags, GlobalFlags & gflags)
602 LookupTag<HEAD, Chain>::type::template activateImpl<Chain>(flags, gflags);
603 ActivateDependencies<TAIL>::template exec<Chain>(flags, gflags);
607 template <
class HEAD,
class TAIL>
608 struct ActivateDependencies<TypeList<Global<HEAD>, TAIL> >
610 template <
class Chain,
class ActiveFlags,
class GlobalFlags>
611 static void exec(ActiveFlags & flags, GlobalFlags & gflags)
613 LookupTag<Global<HEAD>, Chain>::type::activateImpl(gflags);
614 ActivateDependencies<TAIL>::template exec<Chain>(flags, gflags);
619 struct ActivateDependencies<void>
621 template <
class Chain,
class ActiveFlags>
622 static void exec(ActiveFlags &)
625 template <
class Chain,
class ActiveFlags,
class GlobalFlags>
626 static void exec(ActiveFlags &, GlobalFlags &)
630 template <
class List>
631 struct SeparateGlobalAndRegionTags;
633 template <
class HEAD,
class TAIL>
634 struct SeparateGlobalAndRegionTags<TypeList<HEAD, TAIL> >
636 typedef SeparateGlobalAndRegionTags<TAIL> Inner;
637 typedef TypeList<HEAD, typename Inner::RegionTags> RegionTags;
638 typedef typename Inner::GlobalTags GlobalTags;
641 template <
class HEAD,
class TAIL>
642 struct SeparateGlobalAndRegionTags<TypeList<Global<HEAD>, TAIL> >
644 typedef SeparateGlobalAndRegionTags<TAIL> Inner;
645 typedef typename Inner::RegionTags RegionTags;
646 typedef TypeList<HEAD, typename Inner::GlobalTags> GlobalTags;
649 template <
int INDEX,
class TAIL>
650 struct SeparateGlobalAndRegionTags<TypeList<DataArg<INDEX>, TAIL> >
652 typedef SeparateGlobalAndRegionTags<TAIL> Inner;
653 typedef TypeList<DataArg<INDEX>,
typename Inner::RegionTags> RegionTags;
654 typedef TypeList<DataArg<INDEX>,
typename Inner::GlobalTags> GlobalTags;
657 template <
int INDEX,
class TAIL>
658 struct SeparateGlobalAndRegionTags<TypeList<LabelArg<INDEX>, TAIL> >
660 typedef SeparateGlobalAndRegionTags<TAIL> Inner;
661 typedef TypeList<LabelArg<INDEX>,
typename Inner::RegionTags> RegionTags;
662 typedef TypeList<LabelArg<INDEX>,
typename Inner::GlobalTags> GlobalTags;
665 template <
int INDEX,
class TAIL>
666 struct SeparateGlobalAndRegionTags<TypeList<WeightArg<INDEX>, TAIL> >
668 typedef SeparateGlobalAndRegionTags<TAIL> Inner;
669 typedef TypeList<WeightArg<INDEX>,
typename Inner::RegionTags> RegionTags;
670 typedef TypeList<WeightArg<INDEX>,
typename Inner::GlobalTags> GlobalTags;
673 template <
int INDEX,
class TAIL>
674 struct SeparateGlobalAndRegionTags<TypeList<CoordArg<INDEX>, TAIL> >
676 typedef SeparateGlobalAndRegionTags<TAIL> Inner;
677 typedef TypeList<CoordArg<INDEX>,
typename Inner::RegionTags> RegionTags;
678 typedef TypeList<CoordArg<INDEX>,
typename Inner::GlobalTags> GlobalTags;
682 struct SeparateGlobalAndRegionTags<void>
684 typedef void RegionTags;
685 typedef void GlobalTags;
694 template <
class Accumulators>
695 struct CollectAccumulatorNames;
697 template <
class HEAD,
class TAIL>
698 struct CollectAccumulatorNames<TypeList<HEAD, TAIL> >
700 template <
class BackInsertable>
701 static void exec(BackInsertable & a,
bool skipInternals=
true)
703 if(!skipInternals || HEAD::name().find(
"internal") == std::string::npos)
704 a.push_back(HEAD::name());
705 CollectAccumulatorNames<TAIL>::exec(a, skipInternals);
710 struct CollectAccumulatorNames<void>
712 template <
class BackInsertable>
713 static void exec(BackInsertable & a,
bool skipInternals=
true)
718 struct ApplyVisitorToTag;
720 template <
class HEAD,
class TAIL>
721 struct ApplyVisitorToTag<TypeList<HEAD, TAIL> >
723 template <
class Accu,
class Visitor>
724 static bool exec(Accu & a, std::string
const & tag, Visitor
const & v)
726 static std::string * name = VIGRA_SAFE_STATIC(name,
new std::string(
normalizeString(HEAD::name())));
729 v.template exec<HEAD>(a);
734 return ApplyVisitorToTag<TAIL>::exec(a, tag, v);
740 struct ApplyVisitorToTag<void>
742 template <
class Accu,
class Visitor>
743 static bool exec(Accu & a, std::string
const & tag, Visitor
const & v)
749 struct ActivateTag_Visitor
751 template <
class TAG,
class Accu>
752 void exec(Accu & a)
const
754 a.template activate<TAG>();
758 struct TagIsActive_Visitor
762 template <
class TAG,
class Accu>
763 void exec(Accu & a)
const
765 result = a.template isActive<TAG>();
776 struct SetHistogramBincount
778 template <
class Accu>
779 static void exec(Accu & a, HistogramOptions
const & options)
783 template <
template <
int>
class Histogram>
784 struct SetHistogramBincount<Histogram<0> >
786 template <
class Accu>
787 static void exec(Accu & a, HistogramOptions
const & options)
789 a.setBinCount(options.binCount);
794 struct ApplyHistogramOptions
796 template <
class Accu>
797 static void exec(Accu & a, HistogramOptions
const & options)
802 struct ApplyHistogramOptions<StandardQuantiles<TAG> >
804 template <
class Accu>
805 static void exec(Accu & a, HistogramOptions
const & options)
809 template <
class TAG,
template <
class>
class MODIFIER>
810 struct ApplyHistogramOptions<MODIFIER<TAG> >
811 :
public ApplyHistogramOptions<TAG>
815 struct ApplyHistogramOptions<IntegerHistogram<0> >
817 template <
class Accu>
818 static void exec(Accu & a, HistogramOptions
const & options)
820 SetHistogramBincount<IntegerHistogram<0> >::exec(a, options);
824 template <
int BinCount>
825 struct ApplyHistogramOptions<UserRangeHistogram<BinCount> >
827 template <
class Accu>
828 static void exec(Accu & a, HistogramOptions
const & options)
830 SetHistogramBincount<UserRangeHistogram<BinCount> >::exec(a, options);
831 if(a.scale_ == 0.0 && options.validMinMax())
832 a.setMinMax(options.minimum, options.maximum);
836 template <
int BinCount>
837 struct ApplyHistogramOptions<AutoRangeHistogram<BinCount> >
839 template <
class Accu>
840 static void exec(Accu & a, HistogramOptions
const & options)
842 SetHistogramBincount<AutoRangeHistogram<BinCount> >::exec(a, options);
843 if(a.scale_ == 0.0 && options.validMinMax())
844 a.setMinMax(options.minimum, options.maximum);
848 template <
int BinCount>
849 struct ApplyHistogramOptions<GlobalRangeHistogram<BinCount> >
851 template <
class Accu>
852 static void exec(Accu & a, HistogramOptions
const & options)
854 SetHistogramBincount<GlobalRangeHistogram<BinCount> >::exec(a, options);
857 if(options.validMinMax())
858 a.setMinMax(options.minimum, options.maximum);
860 a.setRegionAutoInit(options.local_auto_init);
877 template <
unsigned LEVEL,
class GlobalAccumulatorHandle>
878 struct AccumulatorEndImpl
880 typedef typename GlobalAccumulatorHandle::type GlobalAccumulatorType;
882 typedef AccumulatorEnd Tag;
883 typedef void value_type;
884 typedef bool result_type;
885 typedef BitArray<LEVEL> AccumulatorFlags;
887 static const unsigned int workInPass = 0;
888 static const int index = -1;
889 static const unsigned level = LEVEL;
891 AccumulatorFlags active_accumulators_;
892 mutable AccumulatorFlags is_dirty_;
893 GlobalAccumulatorHandle globalAccumulator_;
895 template <
class GlobalAccumulator>
896 void setGlobalAccumulator(GlobalAccumulator
const * a)
898 globalAccumulator_.pointer_ = a;
901 static std::string name()
903 return "AccumulatorEnd (internal)";
906 bool operator()()
const {
return false; }
907 bool get()
const {
return false; }
909 template <
unsigned,
class U>
913 template <
unsigned,
class U>
914 void pass(U
const &,
double)
918 void mergeImpl(U
const &)
922 void resize(U
const &)
926 void setCoordinateOffsetImpl(U
const &)
937 template <
class Flags>
938 static void activateImpl(Flags &)
941 template <
class Accu,
class Flags1,
class Flags2>
942 static void activateImpl(Flags1 &, Flags2 &)
945 template <
class Flags>
946 static bool isActiveImpl(Flags
const &)
951 void applyHistogramOptions(HistogramOptions
const &)
954 static unsigned int passesRequired()
959 static unsigned int passesRequired(AccumulatorFlags
const &)
966 active_accumulators_.clear();
971 void setDirtyImpl()
const
973 is_dirty_.template set<which>();
977 void setCleanImpl()
const
979 is_dirty_.template reset<which>();
983 bool isDirtyImpl()
const
985 return is_dirty_.template test<which>();
990 template <
class A,
unsigned CurrentPass,
bool allowRuntimeActivation,
unsigned WorkPass=A::workInPass>
994 static void exec(A & a, T
const & t)
998 static void exec(A & a, T
const & t,
double weight)
1002 template <
class A,
unsigned CurrentPass>
1003 struct DecoratorImpl<A, CurrentPass, false, CurrentPass>
1006 static void exec(A & a, T
const & t)
1012 static void exec(A & a, T
const & t,
double weight)
1014 a.update(t, weight);
1017 static typename A::result_type
get(A
const & a)
1022 static void mergeImpl(A & a, A
const & o)
1028 static void resize(A & a, T
const & t)
1033 static void applyHistogramOptions(A & a, HistogramOptions
const & options)
1035 ApplyHistogramOptions<typename A::Tag>::exec(a, options);
1038 static unsigned int passesRequired()
1040 static const unsigned int A_workInPass = A::workInPass;
1041 return std::max(A_workInPass, A::InternalBaseType::passesRequired());
1045 template <
class A,
unsigned CurrentPass>
1046 struct DecoratorImpl<A, CurrentPass, true, CurrentPass>
1050 return A::isActiveImpl(getAccumulator<AccumulatorEnd>(a).active_accumulators_);
1054 static void exec(A & a, T
const & t)
1061 static void exec(A & a, T
const & t,
double weight)
1064 a.update(t, weight);
1067 static typename A::result_type
get(A
const & a)
1071 std::string message = std::string(
"get(accumulator): attempt to access inactive statistic '") +
1072 A::Tag::name() +
"'.";
1073 vigra_precondition(
false, message);
1078 static void mergeImpl(A & a, A
const & o)
1085 static void resize(A & a, T
const & t)
1091 static void applyHistogramOptions(A & a, HistogramOptions
const & options)
1094 ApplyHistogramOptions<typename A::Tag>::exec(a, options);
1097 template <
class ActiveFlags>
1098 static unsigned int passesRequired(ActiveFlags
const & flags)
1100 static const unsigned int A_workInPass = A::workInPass;
1101 return A::isActiveImpl(flags)
1102 ? std::max(A_workInPass, A::InternalBaseType::passesRequired(flags))
1103 : A::InternalBaseType::passesRequired(flags);
1109 template <
class T,
class Shape>
1110 void reshapeImpl(T &, Shape
const &)
1113 template <
class T,
class Shape,
class Initial>
1114 void reshapeImpl(T &, Shape
const &, Initial
const & = T())
1117 template <
unsigned int N,
class T,
class Alloc,
class Shape>
1118 void reshapeImpl(MultiArray<N, T, Alloc> & a, Shape
const & s, T
const & initial = T())
1120 MultiArray<N, T, Alloc>(s, initial).swap(a);
1123 template <
class T,
class Alloc,
class Shape>
1124 void reshapeImpl(Matrix<T, Alloc> & a, Shape
const & s, T
const & initial = T())
1126 Matrix<T, Alloc>(s, initial).swap(a);
1129 template <
class T,
class U>
1130 void copyShapeImpl(T
const &, U
const &)
1133 template <
unsigned int N,
class T,
class Alloc,
class U>
1134 void copyShapeImpl(MultiArray<N, T, Alloc>
const & from, U & to)
1136 to.reshape(from.shape());
1139 template <
class T,
class Alloc,
class U>
1140 void copyShapeImpl(Matrix<T, Alloc>
const & from, U & to)
1142 to.reshape(from.shape());
1145 template <
class T,
class U>
1146 bool hasDataImpl(T
const &)
1151 template <
unsigned int N,
class T,
class Str
ide>
1152 bool hasDataImpl(MultiArrayView<N, T, Stride>
const & a)
1158 template <
unsigned int N,
class T,
class Str
ide>
1159 inline typename MultiArrayShape<N>::type
1160 shapeOf(MultiArrayView<N, T, Stride>
const & a)
1165 template <
class T,
int N>
1167 shapeOf(TinyVector<T, N>
const &)
1172 template <
class T,
class NEXT>
1173 inline CoupledHandle<T, NEXT>
const &
1174 shapeOf(CoupledHandle<T, NEXT>
const & t)
1179 #define VIGRA_SHAPE_OF(type) \
1186 VIGRA_SHAPE_OF(
unsigned char)
1187 VIGRA_SHAPE_OF(
signed char)
1188 VIGRA_SHAPE_OF(
unsigned short)
1189 VIGRA_SHAPE_OF(
short)
1190 VIGRA_SHAPE_OF(
unsigned int)
1192 VIGRA_SHAPE_OF(
unsigned long)
1193 VIGRA_SHAPE_OF(
long)
1194 VIGRA_SHAPE_OF(
unsigned long long)
1195 VIGRA_SHAPE_OF(
long long)
1196 VIGRA_SHAPE_OF(
float)
1197 VIGRA_SHAPE_OF(
double)
1198 VIGRA_SHAPE_OF(
long double)
1200 #undef VIGRA_SHAPE_OF
1209 template <
class T,
class GlobalAccumulators,
class RegionAccumulators>
1210 struct LabelDispatch
1212 typedef LabelDispatchTag Tag;
1213 typedef GlobalAccumulators GlobalAccumulatorChain;
1214 typedef RegionAccumulators RegionAccumulatorChain;
1215 typedef typename LookupTag<AccumulatorEnd, RegionAccumulatorChain>::type::AccumulatorFlags ActiveFlagsType;
1216 typedef ArrayVector<RegionAccumulatorChain> RegionAccumulatorArray;
1218 typedef LabelDispatch type;
1219 typedef LabelDispatch & reference;
1220 typedef LabelDispatch
const & const_reference;
1221 typedef GlobalAccumulatorChain InternalBaseType;
1223 typedef T
const & argument_type;
1224 typedef argument_type first_argument_type;
1225 typedef double second_argument_type;
1226 typedef RegionAccumulatorChain & result_type;
1228 static const int index = GlobalAccumulatorChain::index + 1;
1230 template <
class IndexDefinition,
class TagFound=
typename IndexDefinition::Tag>
1231 struct CoordIndexSelector
1233 static const int value = 0;
1236 template <
class IndexDefinition>
1237 struct CoordIndexSelector<IndexDefinition, CoordArgTag>
1239 static const int value = IndexDefinition::value;
1242 static const int coordIndex = CoordIndexSelector<typename LookupTag<CoordArgTag, GlobalAccumulatorChain>::type>::value;
1243 static const int coordSize = CoupledHandleCast<coordIndex, T>::type::value_type::static_size;
1244 typedef TinyVector<double, coordSize> CoordinateType;
1246 GlobalAccumulatorChain next_;
1247 RegionAccumulatorArray regions_;
1248 HistogramOptions region_histogram_options_;
1250 ActiveFlagsType active_region_accumulators_;
1251 CoordinateType coordinateOffset_;
1253 template <
class TAG>
1256 typedef typename LookupTag<TAG, type>::type TargetAccumulator;
1258 static void activate(GlobalAccumulatorChain & globals, RegionAccumulatorArray & regions,
1259 ActiveFlagsType & flags)
1261 TargetAccumulator::template activateImpl<LabelDispatch>(
1262 flags, getAccumulator<AccumulatorEnd>(globals).active_accumulators_);
1263 for(
unsigned int k=0; k<regions.size(); ++k)
1264 getAccumulator<AccumulatorEnd>(regions[k]).active_accumulators_ = flags;
1267 static bool isActive(GlobalAccumulatorChain
const &, ActiveFlagsType
const & flags)
1269 return TargetAccumulator::isActiveImpl(flags);
1273 template <
class TAG>
1274 struct ActivateImpl<Global<TAG> >
1276 static void activate(GlobalAccumulatorChain & globals, RegionAccumulatorArray &, ActiveFlagsType &)
1278 LookupTag<TAG, GlobalAccumulatorChain>::type::activateImpl(getAccumulator<AccumulatorEnd>(globals).active_accumulators_);
1281 static bool isActive(GlobalAccumulatorChain
const & globals, ActiveFlagsType
const &)
1283 return LookupTag<TAG, GlobalAccumulatorChain>::type::isActiveImpl(getAccumulator<AccumulatorEnd>(globals).active_accumulators_);
1287 template <
int INDEX>
1288 struct ActivateImpl<LabelArg<INDEX> >
1290 static void activate(GlobalAccumulatorChain &, RegionAccumulatorArray &, ActiveFlagsType &)
1293 static bool isActive(GlobalAccumulatorChain
const & globals, ActiveFlagsType
const &)
1295 return getAccumulator<LabelArg<INDEX> >(globals).
isActive();
1302 region_histogram_options_(),
1304 active_region_accumulators_()
1307 LabelDispatch(LabelDispatch
const & o)
1309 regions_(o.regions_),
1310 region_histogram_options_(o.region_histogram_options_),
1311 ignore_label_(o.ignore_label_),
1312 active_region_accumulators_(o.active_region_accumulators_)
1314 for(
unsigned int k=0; k<regions_.size(); ++k)
1316 getAccumulator<AccumulatorEnd>(regions_[k]).setGlobalAccumulator(&next_);
1325 void setMaxRegionLabel(
unsigned maxlabel)
1329 unsigned int oldSize = regions_.size();
1330 regions_.resize(maxlabel + 1);
1331 for(
unsigned int k=oldSize; k<regions_.size(); ++k)
1333 getAccumulator<AccumulatorEnd>(regions_[k]).setGlobalAccumulator(&next_);
1334 getAccumulator<AccumulatorEnd>(regions_[k]).active_accumulators_ = active_region_accumulators_;
1335 regions_[k].applyHistogramOptions(region_histogram_options_);
1336 regions_[k].setCoordinateOffsetImpl(coordinateOffset_);
1347 return ignore_label_;
1350 void applyHistogramOptions(HistogramOptions
const & options)
1352 applyHistogramOptions(options, options);
1355 void applyHistogramOptions(HistogramOptions
const & regionoptions,
1356 HistogramOptions
const & globaloptions)
1358 region_histogram_options_ = regionoptions;
1359 for(
unsigned int k=0; k<regions_.size(); ++k)
1361 regions_[k].applyHistogramOptions(region_histogram_options_);
1363 next_.applyHistogramOptions(globaloptions);
1366 void setCoordinateOffsetImpl(CoordinateType
const & offset)
1368 coordinateOffset_ = offset;
1369 for(
unsigned int k=0; k<regions_.size(); ++k)
1371 regions_[k].setCoordinateOffsetImpl(coordinateOffset_);
1373 next_.setCoordinateOffsetImpl(coordinateOffset_);
1376 void setCoordinateOffsetImpl(
MultiArrayIndex k, CoordinateType
const & offset)
1379 "Accumulator::setCoordinateOffset(k, offset): region k does not exist.");
1380 regions_[k].setCoordinateOffsetImpl(offset);
1384 void resize(U
const & t)
1386 if(regions_.size() == 0)
1388 typedef HandleArgSelector<U, LabelArgTag, GlobalAccumulatorChain> LabelHandle;
1389 typedef typename LabelHandle::value_type LabelType;
1390 typedef MultiArrayView<LabelHandle::size, LabelType, StridedArrayTag> LabelArray;
1391 LabelArray labelArray(t.shape(), LabelHandle::getHandle(t).strides(),
1392 const_cast<LabelType *
>(LabelHandle::getHandle(t).ptr()));
1394 LabelType minimum, maximum;
1395 labelArray.minmax(&minimum, &maximum);
1396 setMaxRegionLabel(maximum);
1400 for(
unsigned int k=0; k<regions_.size(); ++k)
1401 regions_[k].resize(t);
1404 template <
unsigned N>
1405 void pass(T
const & t)
1407 typedef HandleArgSelector<T, LabelArgTag, GlobalAccumulatorChain> LabelHandle;
1408 if(LabelHandle::getValue(t) != ignore_label_)
1410 next_.template pass<N>(t);
1411 regions_[LabelHandle::getValue(t)].template pass<N>(t);
1415 template <
unsigned N>
1416 void pass(T
const & t,
double weight)
1418 typedef HandleArgSelector<T, LabelArgTag, GlobalAccumulatorChain> LabelHandle;
1419 if(LabelHandle::getValue(t) != ignore_label_)
1421 next_.template pass<N>(t, weight);
1422 regions_[LabelHandle::getValue(t)].template pass<N>(t, weight);
1426 static unsigned int passesRequired()
1428 return std::max(GlobalAccumulatorChain::passesRequired(), RegionAccumulatorChain::passesRequired());
1431 unsigned int passesRequiredDynamic()
const
1433 return std::max(GlobalAccumulatorChain::passesRequired(getAccumulator<AccumulatorEnd>(next_).active_accumulators_),
1434 RegionAccumulatorChain::passesRequired(active_region_accumulators_));
1441 active_region_accumulators_.clear();
1442 RegionAccumulatorArray().swap(regions_);
1448 template <
class TAG>
1451 ActivateImpl<TAG>::activate(next_, regions_, active_region_accumulators_);
1456 getAccumulator<AccumulatorEnd>(next_).active_accumulators_.set();
1457 active_region_accumulators_.set();
1458 for(
unsigned int k=0; k<regions_.size(); ++k)
1459 getAccumulator<AccumulatorEnd>(regions_[k]).active_accumulators_.set();
1462 template <
class TAG>
1465 return ActivateImpl<TAG>::isActive(next_, active_region_accumulators_);
1468 void mergeImpl(LabelDispatch
const & o)
1470 for(
unsigned int k=0; k<regions_.size(); ++k)
1471 regions_[k].mergeImpl(o.regions_[k]);
1472 next_.mergeImpl(o.next_);
1475 void mergeImpl(
unsigned i,
unsigned j)
1477 regions_[i].mergeImpl(regions_[j]);
1478 regions_[j].reset();
1479 getAccumulator<AccumulatorEnd>(regions_[j]).active_accumulators_ = active_region_accumulators_;
1482 template <
class ArrayLike>
1483 void mergeImpl(LabelDispatch
const & o, ArrayLike
const & labelMapping)
1485 MultiArrayIndex newMaxLabel = std::max<MultiArrayIndex>(maxRegionLabel(), *
argMax(labelMapping.begin(), labelMapping.end()));
1486 setMaxRegionLabel(newMaxLabel);
1487 for(
unsigned int k=0; k<labelMapping.size(); ++k)
1488 regions_[labelMapping[k]].mergeImpl(o.regions_[k]);
1489 next_.mergeImpl(o.next_);
1493 template <
class TargetTag,
class TagList>
1496 template <
class TargetTag,
class HEAD,
class TAIL>
1497 struct FindNextTag<TargetTag, TypeList<HEAD, TAIL> >
1499 typedef typename FindNextTag<TargetTag, TAIL>::type type;
1502 template <
class TargetTag,
class TAIL>
1503 struct FindNextTag<TargetTag, TypeList<TargetTag, TAIL> >
1505 typedef typename TAIL::Head type;
1508 template <
class TargetTag>
1509 struct FindNextTag<TargetTag, TypeList<TargetTag, void> >
1514 template <
class TargetTag>
1515 struct FindNextTag<TargetTag, void>
1521 template <
class TAG,
class CONFIG,
unsigned LEVEL=0>
1522 struct AccumulatorFactory
1524 typedef typename FindNextTag<TAG, typename CONFIG::TagList>::type NextTag;
1525 typedef typename AccumulatorFactory<NextTag, CONFIG, LEVEL+1>::type NextType;
1526 typedef typename CONFIG::InputType InputType;
1537 template <
class T,
class NEXT>
1538 struct ConfigureTag<CoupledHandle<T, NEXT> >
1540 typedef typename StandardizeTag<DataFromHandle<TAG> >::type WrappedTag;
1541 typedef typename IfBool<(!HasModifierPriority<WrappedTag, WeightingPriority>::value && ShouldBeWeighted<WrappedTag>::value),
1542 Weighted<WrappedTag>, WrappedTag>::type type;
1545 typedef typename ConfigureTag<InputType>::type UseTag;
1549 struct AccumulatorBase
1551 typedef AccumulatorBase ThisType;
1553 typedef NextType InternalBaseType;
1554 typedef InputType input_type;
1555 typedef input_type
const & argument_type;
1556 typedef argument_type first_argument_type;
1557 typedef double second_argument_type;
1558 typedef void result_type;
1560 static const unsigned int workInPass = 1;
1561 static const int index = InternalBaseType::index + 1;
1563 InternalBaseType next_;
1565 static std::string name()
1570 template <
class ActiveFlags>
1571 static void activateImpl(ActiveFlags & flags)
1573 flags.template set<index>();
1574 typedef typename StandardizeDependencies<Tag>::type StdDeps;
1575 acc_detail::ActivateDependencies<StdDeps>::template exec<ThisType>(flags);
1578 template <
class Accu,
class ActiveFlags,
class GlobalFlags>
1579 static void activateImpl(ActiveFlags & flags, GlobalFlags & gflags)
1581 flags.template set<index>();
1582 typedef typename StandardizeDependencies<Tag>::type StdDeps;
1583 acc_detail::ActivateDependencies<StdDeps>::template exec<Accu>(flags, gflags);
1586 template <
class ActiveFlags>
1587 static bool isActiveImpl(ActiveFlags & flags)
1589 return flags.template test<index>();
1592 void setDirty()
const
1594 next_.template setDirtyImpl<index>();
1597 template <
int INDEX>
1598 void setDirtyImpl()
const
1600 next_.template setDirtyImpl<INDEX>();
1603 void setClean()
const
1605 next_.template setCleanImpl<index>();
1608 template <
int INDEX>
1609 void setCleanImpl()
const
1611 next_.template setCleanImpl<INDEX>();
1614 bool isDirty()
const
1616 return next_.template isDirtyImpl<index>();
1619 template <
int INDEX>
1620 bool isDirtyImpl()
const
1622 return next_.template isDirtyImpl<INDEX>();
1628 template <
class Shape>
1629 void setCoordinateOffset(Shape
const &)
1632 template <
class Shape>
1633 void reshape(Shape
const &)
1640 void update(U
const &)
1644 void update(U
const &,
double)
1647 template <
class TargetTag>
1648 typename LookupDependency<TargetTag, ThisType>::result_type
1649 call_getDependency()
const
1651 return getDependency<TargetTag>(*this);
1656 typedef typename UseTag::template Impl<InputType, AccumulatorBase> AccumulatorImpl;
1663 :
public AccumulatorImpl
1665 typedef Accumulator type;
1666 typedef Accumulator & reference;
1667 typedef Accumulator
const & const_reference;
1668 typedef AccumulatorImpl A;
1670 static const unsigned int workInPass = A::workInPass;
1671 static const bool allowRuntimeActivation = CONFIG::allowRuntimeActivation;
1674 void resize(T
const & t)
1676 this->next_.resize(t);
1677 DecoratorImpl<Accumulator, workInPass, allowRuntimeActivation>::resize(*
this, t);
1682 this->next_.reset();
1686 typename A::result_type
get()
const
1691 template <
unsigned N,
class T>
1692 void pass(T
const & t)
1694 this->next_.template pass<N>(t);
1695 DecoratorImpl<Accumulator, N, allowRuntimeActivation>::exec(*
this, t);
1698 template <
unsigned N,
class T>
1699 void pass(T
const & t,
double weight)
1701 this->next_.template pass<N>(t, weight);
1702 DecoratorImpl<Accumulator, N, allowRuntimeActivation>::exec(*
this, t, weight);
1705 void mergeImpl(Accumulator
const & o)
1707 DecoratorImpl<Accumulator, Accumulator::workInPass, allowRuntimeActivation>::mergeImpl(*
this, o);
1708 this->next_.mergeImpl(o.next_);
1711 void applyHistogramOptions(HistogramOptions
const & options)
1713 DecoratorImpl<Accumulator, workInPass, allowRuntimeActivation>::applyHistogramOptions(*
this, options);
1714 this->next_.applyHistogramOptions(options);
1717 template <
class SHAPE>
1718 void setCoordinateOffsetImpl(SHAPE
const & offset)
1720 this->setCoordinateOffset(offset);
1721 this->next_.setCoordinateOffsetImpl(offset);
1724 static unsigned int passesRequired()
1726 return DecoratorImpl<Accumulator, workInPass, allowRuntimeActivation>::passesRequired();
1729 template <
class ActiveFlags>
1730 static unsigned int passesRequired(ActiveFlags
const & flags)
1732 return DecoratorImpl<Accumulator, workInPass, allowRuntimeActivation>::passesRequired(flags);
1736 typedef Accumulator type;
1739 template <
class CONFIG,
unsigned LEVEL>
1740 struct AccumulatorFactory<void, CONFIG, LEVEL>
1742 typedef AccumulatorEndImpl<LEVEL, typename CONFIG::GlobalAccumulatorHandle> type;
1745 struct InvalidGlobalAccumulatorHandle
1747 typedef Error__Global_statistics_are_only_defined_for_AccumulatorChainArray type;
1749 InvalidGlobalAccumulatorHandle()
1753 type
const * pointer_;
1759 template <
class T,
class Selected,
bool dynamic=false,
class GlobalHandle=Inval
idGlobalAccumulatorHandle>
1760 struct ConfigureAccumulatorChain
1762 :
public ConfigureAccumulatorChain<T, typename AddDependencies<typename Selected::type>::type, dynamic>
1766 template <
class T,
class HEAD,
class TAIL,
bool dynamic,
class GlobalHandle>
1767 struct ConfigureAccumulatorChain<T, TypeList<HEAD, TAIL>, dynamic, GlobalHandle>
1769 typedef TypeList<HEAD, TAIL> TagList;
1770 typedef T InputType;
1771 static const bool allowRuntimeActivation = dynamic;
1772 typedef GlobalHandle GlobalAccumulatorHandle;
1774 typedef typename AccumulatorFactory<HEAD, ConfigureAccumulatorChain>::type type;
1777 template <
class T,
class Selected,
bool dynamic=false>
1778 struct ConfigureAccumulatorChainArray
1780 :
public ConfigureAccumulatorChainArray<T, typename AddDependencies<typename Selected::type>::type, dynamic>
1784 template <
class T,
class HEAD,
class TAIL,
bool dynamic>
1785 struct ConfigureAccumulatorChainArray<T, TypeList<HEAD, TAIL>, dynamic>
1787 typedef TypeList<HEAD, TAIL> TagList;
1788 typedef SeparateGlobalAndRegionTags<TagList> TagSeparator;
1789 typedef typename TagSeparator::GlobalTags GlobalTags;
1790 typedef typename TagSeparator::RegionTags RegionTags;
1791 typedef typename ConfigureAccumulatorChain<T, GlobalTags, dynamic>::type GlobalAccumulatorChain;
1793 struct GlobalAccumulatorHandle
1795 typedef GlobalAccumulatorChain type;
1797 GlobalAccumulatorHandle()
1801 type
const * pointer_;
1804 typedef typename ConfigureAccumulatorChain<T, RegionTags, dynamic, GlobalAccumulatorHandle>::type RegionAccumulatorChain;
1806 typedef LabelDispatch<T, GlobalAccumulatorChain, RegionAccumulatorChain> type;
1818 template <
class T,
class NEXT>
1819 class AccumulatorChainImpl
1822 typedef NEXT InternalBaseType;
1823 typedef AccumulatorBegin Tag;
1824 typedef typename InternalBaseType::argument_type argument_type;
1825 typedef typename InternalBaseType::first_argument_type first_argument_type;
1826 typedef typename InternalBaseType::second_argument_type second_argument_type;
1827 typedef void value_type;
1828 typedef typename InternalBaseType::result_type result_type;
1830 static const int staticSize = InternalBaseType::index;
1832 InternalBaseType next_;
1836 unsigned int current_pass_;
1838 AccumulatorChainImpl()
1844 void setHistogramOptions(HistogramOptions
const & options)
1846 next_.applyHistogramOptions(options);
1852 void setHistogramOptions(HistogramOptions
const & regionoptions, HistogramOptions
const & globaloptions)
1854 next_.applyHistogramOptions(regionoptions, globaloptions);
1863 template <
class SHAPE>
1864 void setCoordinateOffset(SHAPE
const & offset)
1866 next_.setCoordinateOffsetImpl(offset);
1871 void reset(
unsigned int reset_to_pass = 0)
1873 current_pass_ = reset_to_pass;
1874 if(reset_to_pass == 0)
1878 template <
unsigned N>
1879 void update(T
const & t)
1881 if(current_pass_ == N)
1883 next_.template pass<N>(t);
1885 else if(current_pass_ < N)
1889 next_.resize(acc_detail::shapeOf(t));
1890 next_.template pass<N>(t);
1894 std::string message(
"AccumulatorChain::update(): cannot return to pass ");
1895 message << N <<
" after working on pass " << current_pass_ <<
".";
1896 vigra_precondition(
false, message);
1900 template <
unsigned N>
1901 void update(T
const & t,
double weight)
1903 if(current_pass_ == N)
1905 next_.template pass<N>(t, weight);
1907 else if(current_pass_ < N)
1911 next_.resize(acc_detail::shapeOf(t));
1912 next_.template pass<N>(t, weight);
1916 std::string message(
"AccumulatorChain::update(): cannot return to pass ");
1917 message << N <<
" after working on pass " << current_pass_ <<
".";
1918 vigra_precondition(
false, message);
1924 void operator+=(AccumulatorChainImpl
const & o)
1931 void merge(AccumulatorChainImpl
const & o)
1933 next_.mergeImpl(o.next_);
1936 result_type operator()()
const
1941 void operator()(T
const & t)
1946 void operator()(T
const & t,
double weight)
1948 update<1>(t, weight);
1951 void updatePass2(T
const & t)
1956 void updatePass2(T
const & t,
double weight)
1958 update<2>(t, weight);
1963 void updatePassN(T
const & t,
unsigned int N)
1967 case 1: update<1>(t);
break;
1968 case 2: update<2>(t);
break;
1969 case 3: update<3>(t);
break;
1970 case 4: update<4>(t);
break;
1971 case 5: update<5>(t);
break;
1973 vigra_precondition(
false,
1974 "AccumulatorChain::updatePassN(): 0 < N < 6 required.");
1980 void updatePassN(T
const & t,
double weight,
unsigned int N)
1984 case 1: update<1>(t, weight);
break;
1985 case 2: update<2>(t, weight);
break;
1986 case 3: update<3>(t, weight);
break;
1987 case 4: update<4>(t, weight);
break;
1988 case 5: update<5>(t, weight);
break;
1990 vigra_precondition(
false,
1991 "AccumulatorChain::updatePassN(): 0 < N < 6 required.");
1997 unsigned int passesRequired()
const
1999 return InternalBaseType::passesRequired();
2034 template <
class T,
class Selected,
bool dynamic=false>
2037 :
public AccumulatorChainImpl<T, typename acc_detail::ConfigureAccumulatorChain<T, Selected, dynamic>::type>
2042 typedef typename acc_detail::ConfigureAccumulatorChain<T, Selected, dynamic>::TagList AccumulatorTags;
2046 template <
class U,
int N>
2049 vigra_precondition(this->current_pass_ == 0,
2050 "AccumulatorChain::reshape(): cannot reshape after seeing data. Call AccumulatorChain::reset() first.");
2051 this->next_.resize(s);
2052 this->current_pass_ = 1;
2064 #ifdef DOXYGEN // hide AccumulatorChainImpl from documentation
2076 template <
class SHAPE>
2080 void reset(
unsigned int reset_to_pass = 0);
2083 void operator+=(AccumulatorChainImpl
const & o);
2087 void merge(AccumulatorChainImpl
const & o);
2095 void updatePassN(T
const & t,
double weight,
unsigned int N);
2107 acc_detail::CollectAccumulatorNames<AccumulatorTags>::exec(n);
2113 template <
unsigned int N,
class T1,
class T2,
class T3,
class T4,
class T5,
class Selected,
bool dynamic>
2114 class AccumulatorChain<CoupledArrays<N, T1, T2, T3, T4, T5>, Selected, dynamic>
2115 :
public AccumulatorChain<typename CoupledArrays<N, T1, T2, T3, T4, T5>::HandleType, Selected, dynamic>
2148 template <
class T,
class Selected>
2154 typedef typename DynamicAccumulatorChain::AccumulatorTags AccumulatorTags;
2160 vigra_precondition(activateImpl(tag),
2161 std::string(
"DynamicAccumulatorChain::activate(): Tag '") + tag +
"' not found.");
2166 template <
class TAG>
2169 LookupTag<TAG, DynamicAccumulatorChain>::type::activateImpl(getAccumulator<AccumulatorEnd>(*this).active_accumulators_);
2176 getAccumulator<AccumulatorEnd>(*this).active_accumulators_.set();
2182 acc_detail::TagIsActive_Visitor v;
2183 vigra_precondition(isActiveImpl(tag, v),
2184 std::string(
"DynamicAccumulatorChain::isActive(): Tag '") + tag +
"' not found.");
2190 template <
class TAG>
2193 return LookupTag<TAG, DynamicAccumulatorChain>::type::isActiveImpl(getAccumulator<AccumulatorEnd>(*this).active_accumulators_);
2211 return InternalBaseType::passesRequired(getAccumulator<AccumulatorEnd>(*this).active_accumulators_);
2216 bool activateImpl(std::string tag)
2218 return acc_detail::ApplyVisitorToTag<AccumulatorTags>::exec(*
this,
2222 bool isActiveImpl(std::string tag, acc_detail::TagIsActive_Visitor & v)
const
2224 return acc_detail::ApplyVisitorToTag<AccumulatorTags>::exec(*
this,
normalizeString(tag), v);
2228 template <
unsigned int N,
class T1,
class T2,
class T3,
class T4,
class T5,
class Selected>
2229 class DynamicAccumulatorChain<CoupledArrays<N, T1, T2, T3, T4, T5>, Selected>
2230 :
public DynamicAccumulatorChain<typename CoupledArrays<N, T1, T2, T3, T4, T5>::HandleType, Selected>
2255 template <
class T,
class Selected,
bool dynamic=false>
2258 :
public AccumulatorChainImpl<T, typename acc_detail::ConfigureAccumulatorChainArray<T, Selected, dynamic>::type>
2262 typedef AccumulatorChainImpl<T, typename acc_detail::ConfigureAccumulatorChainArray<T, Selected, dynamic>::type> base_type;
2263 typedef typename acc_detail::ConfigureAccumulatorChainArray<T, Selected, dynamic> Creator;
2264 typedef typename Creator::TagList AccumulatorTags;
2265 typedef typename Creator::GlobalTags GlobalTags;
2266 typedef typename Creator::RegionTags RegionTags;
2272 this->next_.ignoreLabel(l);
2279 return this->next_.ignoredLabel();
2286 this->next_.setMaxRegionLabel(label);
2293 return this->next_.maxRegionLabel();
2300 return this->next_.regions_.size();
2315 "AccumulatorChainArray::merge(): region labels out of range.");
2316 this->next_.mergeImpl(i, j);
2326 "AccumulatorChainArray::merge(): maxRegionLabel must be equal.");
2327 this->next_.mergeImpl(o.next_);
2332 template <
class ArrayLike>
2335 vigra_precondition(labelMapping.size() == o.
regionCount(),
2336 "AccumulatorChainArray::merge(): labelMapping.size() must match regionCount() of RHS.");
2337 this->next_.mergeImpl(o.next_, labelMapping);
2348 using base_type::setCoordinateOffset;
2356 template <
class SHAPE>
2359 this->next_.setCoordinateOffsetImpl(k, offset);
2362 #ifdef DOXYGEN // hide AccumulatorChainImpl from documentation
2373 template <
class SHAPE>
2377 void reset(
unsigned int reset_to_pass = 0);
2380 void operator+=(AccumulatorChainImpl
const & o);
2386 void updatePassN(T
const & t,
double weight,
unsigned int N);
2394 acc_detail::CollectAccumulatorNames<AccumulatorTags>::exec(n);
2400 template <
unsigned int N,
class T1,
class T2,
class T3,
class T4,
class T5,
class Selected,
bool dynamic>
2401 class AccumulatorChainArray<CoupledArrays<N, T1, T2, T3, T4, T5>, Selected, dynamic>
2402 :
public AccumulatorChainArray<typename CoupledArrays<N, T1, T2, T3, T4, T5>::HandleType, Selected, dynamic>
2426 template <
class T,
class Selected>
2431 typedef typename DynamicAccumulatorChainArray::AccumulatorTags AccumulatorTags;
2436 vigra_precondition(activateImpl(tag),
2437 std::string(
"DynamicAccumulatorChainArray::activate(): Tag '") + tag +
"' not found.");
2441 template <
class TAG>
2444 this->next_.template activate<TAG>();
2450 this->next_.activateAll();
2457 acc_detail::TagIsActive_Visitor v;
2458 vigra_precondition(isActiveImpl(tag, v),
2459 std::string(
"DynamicAccumulatorChainArray::isActive(): Tag '") + tag +
"' not found.");
2465 template <
class TAG>
2468 return this->next_.template isActive<TAG>();
2484 return this->next_.passesRequiredDynamic();
2489 bool activateImpl(std::string tag)
2491 return acc_detail::ApplyVisitorToTag<AccumulatorTags>::exec(this->next_,
2495 bool isActiveImpl(std::string tag, acc_detail::TagIsActive_Visitor & v)
const
2497 return acc_detail::ApplyVisitorToTag<AccumulatorTags>::exec(this->next_,
normalizeString(tag), v);
2501 template <
unsigned int N,
class T1,
class T2,
class T3,
class T4,
class T5,
class Selected>
2502 class DynamicAccumulatorChainArray<CoupledArrays<N, T1, T2, T3, T4, T5>, Selected>
2503 :
public DynamicAccumulatorChainArray<typename CoupledArrays<N, T1, T2, T3, T4, T5>::HandleType, Selected>
2512 template <
class TAG>
2513 struct Error__Attempt_to_access_inactive_statistic;
2515 namespace acc_detail {
2520 template <
class TAG,
class A,
class FromTag=
typename A::Tag>
2521 struct LookupTagImpl
2523 :
public LookupTagImpl<TAG, typename A::InternalBaseType>
2528 template <
class TAG,
class A,
class FromTag>
2529 struct LookupTagImpl<TAG, A const, FromTag>
2530 :
public LookupTagImpl<TAG, A>
2532 typedef typename LookupTagImpl<TAG, A>::type
const & reference;
2533 typedef typename LookupTagImpl<TAG, A>::type
const * pointer;
2537 template <
class TAG,
class A>
2538 struct LookupTagImpl<TAG, A, TAG>
2542 typedef A & reference;
2543 typedef A * pointer;
2544 typedef typename A::value_type value_type;
2545 typedef typename A::result_type result_type;
2549 template <
class TAG,
class A>
2550 struct LookupTagImpl<TAG, A const, TAG>
2551 :
public LookupTagImpl<TAG, A, TAG>
2553 typedef typename LookupTagImpl<TAG, A, TAG>::type
const & reference;
2554 typedef typename LookupTagImpl<TAG, A, TAG>::type
const * pointer;
2559 template <
class TAG,
class A>
2560 struct LookupTagImpl<TAG, A, AccumulatorEnd>
2564 typedef A & reference;
2565 typedef A * pointer;
2566 typedef Error__Attempt_to_access_inactive_statistic<TAG> value_type;
2567 typedef Error__Attempt_to_access_inactive_statistic<TAG> result_type;
2572 struct LookupTagImpl<AccumulatorEnd, A, AccumulatorEnd>
2574 typedef AccumulatorEnd Tag;
2576 typedef A & reference;
2577 typedef A * pointer;
2578 typedef void value_type;
2579 typedef void result_type;
2585 template <
class TAG,
class A>
2586 struct LookupTagImpl<Global<TAG>, A, AccumulatorEnd>
2587 :
public LookupTagImpl<TAG, typename A::GlobalAccumulatorType>
2589 typedef Global<TAG> Tag;
2594 template <
class TAG,
class A>
2595 struct LookupTagImpl<TAG, A, LabelDispatchTag>
2596 :
public LookupTagImpl<TAG, typename A::RegionAccumulatorChain>
2602 template <
class TAG,
class A>
2603 struct LookupTagImpl<Global<TAG>, A, LabelDispatchTag>
2604 :
public LookupTagImpl<TAG, typename A::GlobalAccumulatorChain>
2606 typedef Global<TAG> Tag;
2611 struct LookupTagImpl<LabelDispatchTag, A, LabelDispatchTag>
2613 typedef LabelDispatchTag Tag;
2615 typedef A & reference;
2616 typedef A * pointer;
2617 typedef void value_type;
2618 typedef void result_type;
2624 template <
class Tag,
class A>
2626 :
public acc_detail::LookupTagImpl<typename StandardizeTag<Tag>::type, A>
2633 template <
class Tag,
class A,
class TargetTag>
2634 struct LookupDependency
2635 :
public acc_detail::LookupTagImpl<
2636 typename TransferModifiers<TargetTag, typename StandardizeTag<Tag>::type>::type, A>
2640 namespace acc_detail {
2644 template <
class Tag,
class FromTag,
class reference>
2648 static reference exec(A & a)
2650 return CastImpl<Tag, typename A::InternalBaseType::Tag, reference>::exec(a.next_);
2656 return CastImpl<Tag, typename A::InternalBaseType::Tag, reference>::exec(a.next_, label);
2660 template <
class Tag,
class reference>
2661 struct CastImpl<Tag, Tag, reference>
2664 static reference exec(A & a)
2666 return const_cast<reference
>(a);
2672 vigra_precondition(
false,
2673 "getAccumulator(): region accumulators can only be queried for AccumulatorChainArray.");
2678 template <
class Tag,
class reference>
2679 struct CastImpl<Tag, AccumulatorEnd, reference>
2682 static reference exec(A & a)
2694 template <
class Tag,
class reference>
2695 struct CastImpl<Global<Tag>, AccumulatorEnd, reference>
2698 static reference exec(A & a)
2700 return CastImpl<Tag, typename A::GlobalAccumulatorType::Tag, reference>::exec(*a.globalAccumulator_.pointer_);
2704 template <
class reference>
2705 struct CastImpl<AccumulatorEnd, AccumulatorEnd, reference>
2708 static reference exec(A & a)
2720 template <
class Tag,
class reference>
2721 struct CastImpl<Tag, LabelDispatchTag, reference>
2724 static reference exec(A & a)
2726 vigra_precondition(
false,
2727 "getAccumulator(): a region label is required when a region accumulator is queried.");
2728 return CastImpl<Tag, typename A::RegionAccumulatorChain::Tag, reference>::exec(a.regions_[0]);
2734 return CastImpl<Tag, typename A::RegionAccumulatorChain::Tag, reference>::exec(a.regions_[label]);
2738 template <
class Tag,
class reference>
2739 struct CastImpl<Global<Tag>, LabelDispatchTag, reference>
2742 static reference exec(A & a)
2744 return CastImpl<Tag, typename A::GlobalAccumulatorChain::Tag, reference>::exec(a.next_);
2748 template <
class reference>
2749 struct CastImpl<LabelDispatchTag, LabelDispatchTag, reference>
2752 static reference exec(A & a)
2785 template <
class TAG,
class A>
2786 inline typename LookupTag<TAG, A>::reference
2789 typedef typename LookupTag<TAG, A>::Tag StandardizedTag;
2790 typedef typename LookupTag<TAG, A>::reference reference;
2791 return acc_detail::CastImpl<StandardizedTag, typename A::Tag, reference>::exec(a);
2797 template <
class TAG,
class A>
2798 inline typename LookupTag<TAG, A>::reference
2801 typedef typename LookupTag<TAG, A>::Tag StandardizedTag;
2802 typedef typename LookupTag<TAG, A>::reference reference;
2803 return acc_detail::CastImpl<StandardizedTag, typename A::Tag, reference>::exec(a, label);
2817 template <
class TAG,
class A>
2818 inline typename LookupTag<TAG, A>::result_type
2821 return getAccumulator<TAG>(a).
get();
2845 template <
class TAG,
class A>
2846 inline typename LookupTag<TAG, A>::result_type
2849 return getAccumulator<TAG>(a, label).
get();
2856 template <
class TAG,
class A>
2857 inline typename LookupDependency<TAG, A>::result_type
2858 getDependency(A
const & a)
2860 typedef typename LookupDependency<TAG, A>::Tag StandardizedTag;
2861 typedef typename LookupDependency<TAG, A>::reference reference;
2862 return acc_detail::CastImpl<StandardizedTag, typename A::Tag, reference>::exec(a)();
2869 template <
class Tag,
class A>
2873 a.template activate<Tag>();
2880 template <
class Tag,
class A>
2884 return a.template isActive<Tag>();
2962 template <
class ITERATOR,
class ACCUMULATOR>
2965 for(
unsigned int k=1; k <= a.passesRequired(); ++k)
2966 for(ITERATOR i=start; i < end; ++i)
2967 a.updatePassN(*i, k);
2970 template <
unsigned int N,
class T1,
class S1,
2975 typedef typename CoupledIteratorType<N, T1>::type Iterator;
2976 Iterator start = createCoupledIterator(a1),
2977 end = start.getEndIterator();
2981 template <
unsigned int N,
class T1,
class S1,
2985 MultiArrayView<N, T2, S2>
const & a2,
2988 typedef typename CoupledIteratorType<N, T1, T2>::type Iterator;
2989 Iterator start = createCoupledIterator(a1, a2),
2990 end = start.getEndIterator();
2994 template <
unsigned int N,
class T1,
class S1,
2999 MultiArrayView<N, T2, S2>
const & a2,
3000 MultiArrayView<N, T3, S3>
const & a3,
3003 typedef typename CoupledIteratorType<N, T1, T2, T3>::type Iterator;
3004 Iterator start = createCoupledIterator(a1, a2, a3),
3005 end = start.getEndIterator();
3009 template <
unsigned int N,
class T1,
class S1,
3015 MultiArrayView<N, T2, S2>
const & a2,
3016 MultiArrayView<N, T3, S3>
const & a3,
3017 MultiArrayView<N, T4, S4>
const & a4,
3020 typedef typename CoupledIteratorType<N, T1, T2, T3, T4>::type Iterator;
3021 Iterator start = createCoupledIterator(a1, a2, a3, a4),
3022 end = start.getEndIterator();
3026 template <
unsigned int N,
class T1,
class S1,
3033 MultiArrayView<N, T2, S2>
const & a2,
3034 MultiArrayView<N, T3, S3>
const & a3,
3035 MultiArrayView<N, T4, S4>
const & a4,
3036 MultiArrayView<N, T5, S5>
const & a5,
3039 typedef typename CoupledIteratorType<N, T1, T2, T3, T4, T5>::type Iterator;
3040 Iterator start = createCoupledIterator(a1, a2, a3, a4, a5),
3041 end = start.getEndIterator();
3052 struct AccumulatorResultTraits
3055 typedef T element_type;
3056 typedef double element_promote_type;
3057 typedef T MinmaxType;
3058 typedef element_promote_type SumType;
3059 typedef element_promote_type FlatCovarianceType;
3060 typedef element_promote_type CovarianceType;
3063 template <
class T,
int N>
3064 struct AccumulatorResultTraits<TinyVector<T, N> >
3066 typedef TinyVector<T, N> type;
3067 typedef T element_type;
3068 typedef double element_promote_type;
3069 typedef TinyVector<T, N> MinmaxType;
3070 typedef TinyVector<element_promote_type, N> SumType;
3071 typedef TinyVector<element_promote_type, N*(N+1)/2> FlatCovarianceType;
3072 typedef Matrix<element_promote_type> CovarianceType;
3076 template <
class T,
unsigned int RED_IDX,
unsigned int GREEN_IDX,
unsigned int BLUE_IDX>
3077 struct AccumulatorResultTraits<RGBValue<T, RED_IDX, GREEN_IDX, BLUE_IDX> >
3079 typedef RGBValue<T> type;
3080 typedef T element_type;
3081 typedef double element_promote_type;
3082 typedef RGBValue<T> MinmaxType;
3083 typedef RGBValue<element_promote_type> SumType;
3084 typedef TinyVector<element_promote_type, 3*(3+1)/2> FlatCovarianceType;
3085 typedef Matrix<element_promote_type> CovarianceType;
3090 template <
unsigned int N,
class T,
class Str
ide>
3091 struct AccumulatorResultTraits<MultiArrayView<N, T, Stride> >
3093 typedef MultiArrayView<N, T, Stride> type;
3094 typedef T element_type;
3095 typedef double element_promote_type;
3096 typedef MultiArray<N, T> MinmaxType;
3097 typedef MultiArray<N, element_promote_type> SumType;
3098 typedef MultiArray<1, element_promote_type> FlatCovarianceType;
3099 typedef Matrix<element_promote_type> CovarianceType;
3102 template <
unsigned int N,
class T,
class Alloc>
3103 struct AccumulatorResultTraits<MultiArray<N, T, Alloc> >
3105 typedef MultiArrayView<N, T, Alloc> type;
3106 typedef T element_type;
3107 typedef double element_promote_type;
3108 typedef MultiArray<N, T> MinmaxType;
3109 typedef MultiArray<N, element_promote_type> SumType;
3110 typedef MultiArray<1, element_promote_type> FlatCovarianceType;
3111 typedef Matrix<element_promote_type> CovarianceType;
3124 template <
class TAG>
3128 typedef typename StandardizeTag<TAG>::type TargetTag;
3129 typedef typename TargetTag::Dependencies Dependencies;
3131 static std::string name()
3133 return std::string(
"Global<") + TargetTag::name() +
" >";
3143 template <
int INDEX>
3147 typedef Select<> Dependencies;
3149 static std::string name()
3151 return std::string(
"DataArg<") +
asString(INDEX) +
"> (internal)";
3156 template <
class T,
class BASE>
3160 typedef DataArgTag Tag;
3161 typedef void value_type;
3162 typedef void result_type;
3164 static const int value = INDEX;
3165 static const unsigned int workInPass = 0;
3169 namespace acc_detail {
3171 template <
class T,
int DEFAULT,
class TAG,
class IndexDefinition,
3172 class TagFound=
typename IndexDefinition::Tag>
3173 struct HandleArgSelectorImpl
3175 static const int value = DEFAULT;
3176 typedef typename CoupledHandleCast<value, T>::type type;
3177 typedef typename CoupledHandleCast<value, T>::value_type value_type;
3178 static const int size = type::dimensions;
3180 template <
class U,
class NEXT>
3181 static typename CoupledHandleCast<value, CoupledHandle<U, NEXT> >::type
const &
3182 getHandle(CoupledHandle<U, NEXT>
const & t)
3184 return vigra::cast<value>(t);
3187 template <
class U,
class NEXT>
3188 static typename CoupledHandleCast<value, CoupledHandle<U, NEXT> >::type::const_reference
3189 getValue(CoupledHandle<U, NEXT>
const & t)
3191 return vigra::get<value>(t);
3195 template <
class T,
int DEFAULT,
class TAG,
class IndexDefinition>
3196 struct HandleArgSelectorImpl<T, DEFAULT, TAG, IndexDefinition, TAG>
3198 static const int value = IndexDefinition::value;
3199 typedef typename CoupledHandleCast<value, T>::type type;
3200 typedef typename CoupledHandleCast<value, T>::value_type value_type;
3201 static const int size = type::dimensions;
3203 template <
class U,
class NEXT>
3204 static typename CoupledHandleCast<value, CoupledHandle<U, NEXT> >::type
const &
3205 getHandle(CoupledHandle<U, NEXT>
const & t)
3207 return vigra::cast<value>(t);
3210 template <
class U,
class NEXT>
3211 static typename CoupledHandleCast<value, CoupledHandle<U, NEXT> >::type::const_reference
3212 getValue(CoupledHandle<U, NEXT>
const & t)
3214 return vigra::get<value>(t);
3220 template <
class T,
class CHAIN>
3221 struct HandleArgSelector<T, LabelArgTag, CHAIN>
3222 :
public acc_detail::HandleArgSelectorImpl<T, 2, LabelArgTag,
3223 typename LookupTag<LabelArgTag, CHAIN>::type>
3226 template <
class T,
class CHAIN>
3227 struct HandleArgSelector<T, DataArgTag, CHAIN>
3228 :
public acc_detail::HandleArgSelectorImpl<T, 1, DataArgTag,
3229 typename LookupTag<DataArgTag, CHAIN>::type>
3232 template <
class T,
class CHAIN>
3233 struct HandleArgSelector<T, CoordArgTag, CHAIN>
3234 :
public acc_detail::HandleArgSelectorImpl<T, 0, CoordArgTag,
3235 typename LookupTag<CoordArgTag, CHAIN>::type>
3237 typedef acc_detail::HandleArgSelectorImpl<T, 0, CoordArgTag,
3238 typename LookupTag<CoordArgTag, CHAIN>::type> base_type;
3239 typedef TinyVector<double, base_type::size> value_type;
3243 template <
class TAG>
3244 class DataFromHandle
3247 typedef typename StandardizeTag<TAG>::type TargetTag;
3248 typedef typename TargetTag::Dependencies Dependencies;
3250 static std::string name()
3252 return std::string(
"DataFromHandle<") + TargetTag::name() +
" > (internal)";
3257 template <
class T,
class BASE>
3259 :
public TargetTag::template Impl<typename HandleArgSelector<T, DataArgTag, BASE>::value_type, BASE>
3261 typedef HandleArgSelector<T, DataArgTag, BASE> DataHandle;
3262 typedef typename DataHandle::value_type input_type;
3263 typedef input_type
const & argument_type;
3264 typedef argument_type first_argument_type;
3266 typedef typename TargetTag::template Impl<input_type, BASE> ImplType;
3268 using ImplType::reshape;
3270 template <
class U,
class NEXT>
3271 void reshape(CoupledHandle<U, NEXT>
const & t)
3273 ImplType::reshape(acc_detail::shapeOf(DataHandle::getValue(t)));
3276 template <
class U,
class NEXT>
3277 void update(CoupledHandle<U, NEXT>
const & t)
3279 ImplType::update(DataHandle::getValue(t));
3282 template <
class U,
class NEXT>
3283 void update(CoupledHandle<U, NEXT>
const & t,
double weight)
3285 ImplType::update(DataHandle::getValue(t), weight);
3294 template <
class TAG>
3298 typedef typename StandardizeTag<TAG>::type TargetTag;
3299 typedef typename TargetTag::Dependencies Dependencies;
3301 static std::string name()
3303 return std::string(
"Coord<") + TargetTag::name() +
" >";
3308 template <
class T,
class BASE>
3310 :
public TargetTag::template Impl<typename HandleArgSelector<T, CoordArgTag, BASE>::value_type, BASE>
3312 typedef HandleArgSelector<T, CoordArgTag, BASE> CoordHandle;
3313 typedef typename CoordHandle::value_type input_type;
3314 typedef input_type
const & argument_type;
3315 typedef argument_type first_argument_type;
3317 typedef typename TargetTag::template Impl<input_type, BASE> ImplType;
3325 void setCoordinateOffset(input_type
const & offset)
3330 using ImplType::reshape;
3332 template <
class U,
class NEXT>
3333 void reshape(CoupledHandle<U, NEXT>
const & t)
3335 ImplType::reshape(acc_detail::shapeOf(CoordHandle::getValue(t)));
3338 template <
class U,
class NEXT>
3339 void update(CoupledHandle<U, NEXT>
const & t)
3341 ImplType::update(CoordHandle::getValue(t)+offset_);
3344 template <
class U,
class NEXT>
3345 void update(CoupledHandle<U, NEXT>
const & t,
double weight)
3347 ImplType::update(CoordHandle::getValue(t)+offset_, weight);
3356 template <
int INDEX>
3360 typedef Select<> Dependencies;
3362 static std::string name()
3364 return std::string(
"WeightArg<") +
asString(INDEX) +
"> (internal)";
3369 template <
class T,
class BASE>
3373 typedef WeightArgTag Tag;
3374 typedef void value_type;
3375 typedef void result_type;
3377 static const int value = INDEX;
3378 static const unsigned int workInPass = 0;
3384 template <
class TAG>
3388 typedef typename StandardizeTag<TAG>::type TargetTag;
3389 typedef typename TargetTag::Dependencies Dependencies;
3391 static std::string name()
3393 return std::string(
"Weighted<") + TargetTag::name() +
" >";
3398 template <
class IndexDefinition,
class TagFound=
typename IndexDefinition::Tag>
3399 struct WeightIndexSelector
3401 template <
class U,
class NEXT>
3402 static double exec(CoupledHandle<U, NEXT>
const & t)
3408 template <
class IndexDefinition>
3409 struct WeightIndexSelector<IndexDefinition, WeightArgTag>
3411 template <
class U,
class NEXT>
3412 static double exec(CoupledHandle<U, NEXT>
const & t)
3414 return (
double)get<IndexDefinition::value>(t);
3418 template <
class T,
class BASE>
3420 :
public TargetTag::template Impl<T, BASE>
3422 typedef typename TargetTag::template Impl<T, BASE> ImplType;
3424 typedef typename LookupTag<WeightArgTag, BASE>::type FindWeightIndex;
3426 template <
class U,
class NEXT>
3427 void update(CoupledHandle<U, NEXT>
const & t)
3429 ImplType::update(t, WeightIndexSelector<FindWeightIndex>::exec(t));
3438 typedef Select<Mean> Dependencies;
3440 static std::string name()
3442 return "Centralize (internal)";
3447 template <
class U,
class BASE>
3451 static const unsigned int workInPass = 2;
3453 typedef typename AccumulatorResultTraits<U>::element_promote_type element_type;
3454 typedef typename AccumulatorResultTraits<U>::SumType value_type;
3455 typedef value_type
const & result_type;
3457 mutable value_type value_;
3465 value_ = element_type();
3468 template <
class Shape>
3469 void reshape(Shape
const & s)
3471 acc_detail::reshapeImpl(value_, s);
3474 void update(U
const & t)
const
3476 using namespace vigra::multi_math;
3477 value_ = t - getDependency<Mean>(*this);
3480 void update(U
const & t,
double)
const
3485 result_type operator()(U
const & t)
const
3491 result_type operator()()
const
3502 template <
class TAG>
3506 typedef typename StandardizeTag<TAG>::type TargetTag;
3507 typedef Select<Centralize, typename TargetTag::Dependencies> Dependencies;
3509 static std::string name()
3511 return std::string(
"Central<") + TargetTag::name() +
" >";
3516 template <
class U,
class BASE>
3518 :
public TargetTag::template Impl<typename AccumulatorResultTraits<U>::SumType, BASE>
3520 typedef typename TargetTag::template Impl<typename AccumulatorResultTraits<U>::SumType, BASE> ImplType;
3522 static const unsigned int workInPass = 2;
3526 vigra_precondition(
false,
3527 "Central<...>::operator+=(): not supported.");
3531 void update(T
const & t)
3533 ImplType::update(getDependency<Centralize>(*
this));
3537 void update(T
const & t,
double weight)
3539 ImplType::update(getDependency<Centralize>(*
this), weight);
3582 class PrincipalProjection
3585 typedef Select<Centralize, Principal<CoordinateSystem> > Dependencies;
3587 static std::string name()
3589 return "PrincipalProjection (internal)";
3594 template <
class U,
class BASE>
3598 static const unsigned int workInPass = 2;
3600 typedef typename AccumulatorResultTraits<U>::element_promote_type element_type;
3601 typedef typename AccumulatorResultTraits<U>::SumType value_type;
3602 typedef value_type
const & result_type;
3604 mutable value_type value_;
3612 value_ = element_type();
3615 template <
class Shape>
3616 void reshape(Shape
const & s)
3618 acc_detail::reshapeImpl(value_, s);
3621 void update(U
const & t)
const
3623 for(
unsigned int k=0; k<t.size(); ++k)
3625 value_[k] = getDependency<Principal<CoordinateSystem> >(*this)(0, k)*getDependency<Centralize>(*
this)[0];
3626 for(
unsigned int d=1; d<t.size(); ++d)
3627 value_[k] += getDependency<Principal<CoordinateSystem> >(*
this)(d, k)*getDependency<Centralize>(*
this)[d];
3631 void update(U
const & t,
double)
const
3636 result_type operator()(U
const & t)
const
3638 getAccumulator<Centralize>(*this).update(t);
3643 result_type operator()()
const
3654 template <
class TAG>
3658 typedef typename StandardizeTag<TAG>::type TargetTag;
3659 typedef Select<PrincipalProjection, typename TargetTag::Dependencies> Dependencies;
3661 static std::string name()
3663 return std::string(
"Principal<") + TargetTag::name() +
" >";
3668 template <
class U,
class BASE>
3670 :
public TargetTag::template Impl<typename AccumulatorResultTraits<U>::SumType, BASE>
3672 typedef typename TargetTag::template Impl<typename AccumulatorResultTraits<U>::SumType, BASE> ImplType;
3674 static const unsigned int workInPass = 2;
3678 vigra_precondition(
false,
3679 "Principal<...>::operator+=(): not supported.");
3683 void update(T
const & t)
3685 ImplType::update(getDependency<PrincipalProjection>(*
this));
3689 void update(T
const & t,
double weight)
3691 ImplType::update(getDependency<PrincipalProjection>(*
this), weight);
3728 static std::string name()
3730 return "CoordinateSystem";
3735 template <
class U,
class BASE>
3739 typedef double element_type;
3740 typedef Matrix<double> value_type;
3741 typedef value_type
const & result_type;
3751 value_ = element_type();
3754 template <
class Shape>
3755 void reshape(Shape
const & s)
3757 acc_detail::reshapeImpl(value_, s);
3760 result_type operator()()
const
3767 template <
class BASE,
class T,
3768 class ElementType=
typename AccumulatorResultTraits<T>::element_promote_type,
3769 class SumType=
typename AccumulatorResultTraits<T>::SumType>
3773 typedef ElementType element_type;
3774 typedef SumType value_type;
3775 typedef value_type
const & result_type;
3785 value_ = element_type();
3788 template <
class Shape>
3789 void reshape(Shape
const & s)
3791 acc_detail::reshapeImpl(value_, s);
3799 result_type operator()()
const
3810 typedef Select<> Dependencies;
3812 static std::string name()
3814 return "PowerSum<0>";
3819 template <
class T,
class BASE>
3821 :
public SumBaseImpl<BASE, T, double, double>
3823 void update(T
const & t)
3828 void update(T
const & t,
double weight)
3830 this->value_ += weight;
3840 typedef Select<> Dependencies;
3842 static std::string name()
3844 return "PowerSum<1>";
3849 template <
class U,
class BASE>
3851 :
public SumBaseImpl<BASE, U>
3853 void update(U
const & t)
3858 void update(U
const & t,
double weight)
3860 using namespace multi_math;
3862 this->value_ += weight*t;
3871 template <
unsigned N>
3875 typedef Select<> Dependencies;
3877 static std::string name()
3879 return std::string(
"PowerSum<") +
asString(N) +
">";
3884 template <
class U,
class BASE>
3886 :
public SumBaseImpl<BASE, U>
3888 void update(U
const & t)
3890 using namespace vigra::multi_math;
3891 this->value_ += pow(t, (
int)N);
3894 void update(U
const & t,
double weight)
3896 using namespace vigra::multi_math;
3897 this->value_ += weight*pow(t, (
int)N);
3903 class AbsPowerSum<1>
3906 typedef Select<> Dependencies;
3908 static std::string name()
3910 return "AbsPowerSum<1>";
3915 template <
class U,
class BASE>
3917 :
public SumBaseImpl<BASE, U>
3919 void update(U
const & t)
3921 using namespace vigra::multi_math;
3922 this->value_ +=
abs(t);
3925 void update(U
const & t,
double weight)
3927 using namespace vigra::multi_math;
3928 this->value_ += weight*
abs(t);
3937 template <
unsigned N>
3941 typedef Select<> Dependencies;
3943 static std::string name()
3945 return std::string(
"AbsPowerSum<") +
asString(N) +
">";
3950 template <
class U,
class BASE>
3952 :
public SumBaseImpl<BASE, U>
3954 void update(U
const & t)
3956 using namespace vigra::multi_math;
3957 this->value_ += pow(
abs(t), (
int)N);
3960 void update(U
const & t,
double weight)
3962 using namespace vigra::multi_math;
3963 this->value_ += weight*pow(
abs(t), (
int)N);
3968 template <
class BASE,
class VALUE_TYPE,
class U>
3969 struct CachedResultBase
3972 typedef typename AccumulatorResultTraits<U>::element_type element_type;
3973 typedef VALUE_TYPE value_type;
3974 typedef value_type
const & result_type;
3976 mutable value_type value_;
3984 value_ = element_type();
3988 template <
class Shape>
3989 void reshape(Shape
const & s)
3991 acc_detail::reshapeImpl(value_, s);
3999 void update(U
const &)
4004 void update(U
const &,
double)
4013 template <
class TAG>
4017 typedef typename StandardizeTag<TAG>::type TargetTag;
4018 typedef Select<TargetTag, Count> Dependencies;
4020 static std::string name()
4022 return std::string(
"DivideByCount<") + TargetTag::name() +
" >";
4027 template <
class U,
class BASE>
4029 :
public CachedResultBase<BASE, typename LookupDependency<TargetTag, BASE>::value_type, U>
4031 typedef typename CachedResultBase<BASE, typename LookupDependency<TargetTag, BASE>::value_type, U>::result_type result_type;
4033 result_type operator()()
const
4037 using namespace multi_math;
4038 this->value_ = getDependency<TargetTag>(*this) / getDependency<Count>(*this);
4041 return this->value_;
4049 template <
class TAG>
4050 class DivideUnbiased
4053 typedef typename StandardizeTag<TAG>::type TargetTag;
4054 typedef Select<TargetTag, Count> Dependencies;
4056 static std::string name()
4058 return std::string(
"DivideUnbiased<") + TargetTag::name() +
" >";
4063 template <
class U,
class BASE>
4067 typedef typename LookupDependency<TargetTag, BASE>::value_type value_type;
4068 typedef value_type result_type;
4070 result_type operator()()
const
4072 using namespace multi_math;
4073 return getDependency<TargetTag>(*this) / (getDependency<Count>(*this) - 1.0);
4081 template <
class TAG>
4082 class RootDivideByCount
4085 typedef typename StandardizeTag<DivideByCount<TAG> >::type TargetTag;
4086 typedef Select<TargetTag> Dependencies;
4088 static std::string name()
4090 typedef typename StandardizeTag<TAG>::type InnerTag;
4091 return std::string(
"RootDivideByCount<") + InnerTag::name() +
" >";
4096 template <
class U,
class BASE>
4100 typedef typename LookupDependency<TargetTag, BASE>::value_type value_type;
4101 typedef value_type result_type;
4103 result_type operator()()
const
4105 using namespace multi_math;
4106 return sqrt(getDependency<TargetTag>(*
this));
4114 template <
class TAG>
4115 class RootDivideUnbiased
4118 typedef typename StandardizeTag<DivideUnbiased<TAG> >::type TargetTag;
4119 typedef Select<TargetTag> Dependencies;
4121 static std::string name()
4123 typedef typename StandardizeTag<TAG>::type InnerTag;
4124 return std::string(
"RootDivideUnbiased<") + InnerTag::name() +
" >";
4129 template <
class U,
class BASE>
4133 typedef typename LookupDependency<TargetTag, BASE>::value_type value_type;
4134 typedef value_type result_type;
4136 result_type operator()()
const
4138 using namespace multi_math;
4139 return sqrt(getDependency<TargetTag>(*
this));
4152 static std::string name()
4154 return "Central<PowerSum<2> >";
4159 template <
class U,
class BASE>
4161 :
public SumBaseImpl<BASE, U>
4165 using namespace vigra::multi_math;
4166 double n1 = getDependency<Count>(*this), n2 = getDependency<Count>(o);
4169 this->value_ = o.value_;
4173 this->value_ += o.value_ + n1 * n2 / (n1 + n2) *
sq(getDependency<Mean>(*
this) - getDependency<Mean>(o));
4177 void update(U
const & t)
4179 double n = getDependency<Count>(*this);
4182 using namespace vigra::multi_math;
4183 this->value_ += n / (n - 1.0) *
sq(getDependency<Mean>(*
this) - t);
4187 void update(U
const & t,
double weight)
4189 double n = getDependency<Count>(*this);
4192 using namespace vigra::multi_math;
4193 this->value_ += n / (n - weight) *
sq(getDependency<Mean>(*
this) - t);
4207 static std::string name()
4209 return "Central<PowerSum<3> >";
4214 template <
class U,
class BASE>
4216 :
public SumBaseImpl<BASE, U>
4218 typedef typename SumBaseImpl<BASE, U>::value_type value_type;
4220 static const unsigned int workInPass = 2;
4226 using namespace vigra::multi_math;
4227 double n1 = getDependency<Count>(*this), n2 = getDependency<Count>(o);
4230 this->value_ = o.value_;
4235 double weight = n1 * n2 * (n1 - n2) /
sq(n);
4236 value_type delta = getDependency<Mean>(o) - getDependency<Mean>(*
this);
4237 this->value_ += o.value_ + weight * pow(delta, 3) +
4238 3.0 / n * delta * (n1 * getDependency<Sum2Tag>(o) - n2 * getDependency<Sum2Tag>(*
this));
4242 void update(U
const & t)
4244 using namespace vigra::multi_math;
4245 this->value_ += pow(getDependency<Centralize>(*
this), 3);
4248 void update(U
const & t,
double weight)
4250 using namespace vigra::multi_math;
4251 this->value_ += weight*pow(getDependency<Centralize>(*
this), 3);
4263 static std::string name()
4265 return "Central<PowerSum<4> >";
4270 template <
class U,
class BASE>
4272 :
public SumBaseImpl<BASE, U>
4274 typedef typename SumBaseImpl<BASE, U>::value_type value_type;
4276 static const unsigned int workInPass = 2;
4283 using namespace vigra::multi_math;
4284 double n1 = getDependency<Count>(*this), n2 = getDependency<Count>(o);
4287 this->value_ = o.value_;
4292 double n1_2 =
sq(n1);
4293 double n2_2 =
sq(n2);
4295 double weight = n1 * n2 * (n1_2 - n1*n2 + n2_2) / n_2 / n;
4296 value_type delta = getDependency<Mean>(o) - getDependency<Mean>(*
this);
4297 this->value_ += o.value_ + weight * pow(delta, 4) +
4298 6.0 / n_2 *
sq(delta) * (n1_2 * getDependency<Sum2Tag>(o) + n2_2 * getDependency<Sum2Tag>(*
this)) +
4299 4.0 / n * delta * (n1 * getDependency<Sum3Tag>(o) - n2 * getDependency<Sum3Tag>(*this));
4303 void update(U
const & t)
4305 using namespace vigra::multi_math;
4306 this->value_ += pow(getDependency<Centralize>(*
this), 4);
4309 void update(U
const & t,
double weight)
4311 using namespace vigra::multi_math;
4312 this->value_ += weight*pow(getDependency<Centralize>(*
this), 4);
4327 static std::string name()
4334 template <
class U,
class BASE>
4338 static const unsigned int workInPass = 2;
4340 typedef typename LookupDependency<Central<PowerSum<3> >, BASE>::value_type value_type;
4341 typedef value_type result_type;
4343 result_type operator()()
const
4348 using namespace multi_math;
4349 return sqrt(getDependency<Count>(*
this)) * getDependency<Sum3>(*this) / pow(getDependency<Sum2>(*
this), 1.5);
4363 static std::string name()
4365 return "UnbiasedSkewness";
4370 template <
class U,
class BASE>
4374 static const unsigned int workInPass = 2;
4376 typedef typename LookupDependency<Central<PowerSum<3> >, BASE>::value_type value_type;
4377 typedef value_type result_type;
4379 result_type operator()()
const
4381 using namespace multi_math;
4382 double n = getDependency<Count>(*this);
4383 return sqrt(n*(n-1.0)) / (n - 2.0) * getDependency<Skewness>(*this);
4399 static std::string name()
4406 template <
class U,
class BASE>
4410 static const unsigned int workInPass = 2;
4412 typedef typename LookupDependency<Central<PowerSum<4> >, BASE>::value_type value_type;
4413 typedef value_type result_type;
4415 result_type operator()()
const
4420 using namespace multi_math;
4421 return getDependency<Count>(*this) * getDependency<Sum4>(*this) /
sq(getDependency<Sum2>(*
this)) - 3.0;
4435 static std::string name()
4437 return "UnbiasedKurtosis";
4442 template <
class U,
class BASE>
4446 static const unsigned int workInPass = 2;
4448 typedef typename LookupDependency<Central<PowerSum<4> >, BASE>::value_type value_type;
4449 typedef value_type result_type;
4451 result_type operator()()
const
4453 using namespace multi_math;
4454 double n = getDependency<Count>(*this);
4455 return (n-1.0)/((n-2.0)*(n-3.0))*((n+1.0)*getDependency<Kurtosis>(*this) + value_type(6.0));
4460 namespace acc_detail {
4462 template <
class Scatter,
class Sum>
4463 void updateFlatScatterMatrix(Scatter & sc,
Sum const & s,
double w)
4465 int size = s.size();
4468 sc[k] += w*s[i]*s[j];
4471 template <
class Sum>
4472 void updateFlatScatterMatrix(
double & sc,
Sum const & s,
double w)
4477 template <
class Cov,
class Scatter>
4478 void flatScatterMatrixToScatterMatrix(Cov & cov, Scatter
const & sc)
4480 int size = cov.shape(0), k=0;
4487 cov(j,i) = cov(i,j);
4492 template <
class Scatter>
4493 void flatScatterMatrixToScatterMatrix(
double & cov, Scatter
const & sc)
4498 template <
class Cov,
class Scatter>
4499 void flatScatterMatrixToCovariance(Cov & cov, Scatter
const & sc,
double n)
4501 int size = cov.shape(0), k=0;
4504 cov(j,j) = sc[k++] / n;
4507 cov(i,j) = sc[k++] / n;
4508 cov(j,i) = cov(i,j);
4513 template <
class Scatter>
4514 void flatScatterMatrixToCovariance(
double & cov, Scatter
const & sc,
double n)
4531 static std::string name()
4533 return "FlatScatterMatrix";
4538 template <
class U,
class BASE>
4542 typedef typename AccumulatorResultTraits<U>::element_promote_type element_type;
4543 typedef typename AccumulatorResultTraits<U>::FlatCovarianceType value_type;
4544 typedef value_type
const & result_type;
4546 typedef typename AccumulatorResultTraits<U>::SumType SumType;
4558 value_ = element_type();
4561 template <
class Shape>
4562 void reshape(Shape
const & s)
4565 acc_detail::reshapeImpl(value_,
Shape1(size*(size+1)/2));
4566 acc_detail::reshapeImpl(diff_, s);
4571 double n1 = getDependency<Count>(*this), n2 = getDependency<Count>(o);
4578 using namespace vigra::multi_math;
4579 diff_ = getDependency<Mean>(*this) - getDependency<Mean>(o);
4580 acc_detail::updateFlatScatterMatrix(value_, diff_, n1 * n2 / (n1 + n2));
4585 void update(U
const & t)
4590 void update(U
const & t,
double weight)
4595 result_type operator()()
const
4601 void compute(U
const & t,
double weight = 1.0)
4603 double n = getDependency<Count>(*this);
4606 using namespace vigra::multi_math;
4607 diff_ = getDependency<Mean>(*this) - t;
4608 acc_detail::updateFlatScatterMatrix(value_, diff_, n * weight / (n - weight));
4621 static std::string name()
4623 return "DivideByCount<FlatScatterMatrix>";
4628 template <
class U,
class BASE>
4630 :
public CachedResultBase<BASE, typename AccumulatorResultTraits<U>::CovarianceType, U>
4632 typedef CachedResultBase<BASE, typename AccumulatorResultTraits<U>::CovarianceType, U> BaseType;
4633 typedef typename BaseType::result_type result_type;
4635 template <
class Shape>
4636 void reshape(Shape
const & s)
4639 acc_detail::reshapeImpl(this->value_,
Shape2(size,size));
4642 result_type operator()()
const
4646 acc_detail::flatScatterMatrixToCovariance(this->value_, getDependency<FlatScatterMatrix>(*
this), getDependency<Count>(*
this));
4649 return this->value_;
4656 class DivideUnbiased<FlatScatterMatrix>
4659 typedef Select<FlatScatterMatrix, Count> Dependencies;
4661 static std::string name()
4663 return "DivideUnbiased<FlatScatterMatrix>";
4668 template <
class U,
class BASE>
4670 :
public CachedResultBase<BASE, typename AccumulatorResultTraits<U>::CovarianceType, U>
4672 typedef CachedResultBase<BASE, typename AccumulatorResultTraits<U>::CovarianceType, U> BaseType;
4673 typedef typename BaseType::result_type result_type;
4675 template <
class Shape>
4676 void reshape(Shape
const & s)
4679 acc_detail::reshapeImpl(this->value_,
Shape2(size,size));
4682 result_type operator()()
const
4686 acc_detail::flatScatterMatrixToCovariance(this->value_, getDependency<FlatScatterMatrix>(*
this), getDependency<Count>(*
this) - 1.0);
4689 return this->value_;
4701 static std::string name()
4703 return "ScatterMatrixEigensystem";
4708 template <
class U,
class BASE>
4712 typedef typename AccumulatorResultTraits<U>::element_promote_type element_type;
4713 typedef typename AccumulatorResultTraits<U>::SumType EigenvalueType;
4714 typedef typename AccumulatorResultTraits<U>::CovarianceType EigenvectorType;
4715 typedef std::pair<EigenvalueType, EigenvectorType> value_type;
4716 typedef value_type
const & result_type;
4718 mutable value_type value_;
4726 if(!acc_detail::hasDataImpl(value_.second))
4728 acc_detail::copyShapeImpl(o.value_.first, value_.first);
4729 acc_detail::copyShapeImpl(o.value_.second, value_.second);
4734 void update(U
const &)
4739 void update(U
const &,
double)
4746 value_.first = element_type();
4747 value_.second = element_type();
4751 template <
class Shape>
4752 void reshape(Shape
const & s)
4755 acc_detail::reshapeImpl(value_.first,
Shape1(size));
4756 acc_detail::reshapeImpl(value_.second,
Shape2(size,size));
4759 result_type operator()()
const
4763 compute(getDependency<FlatScatterMatrix>(*
this), value_.first, value_.second);
4770 template <
class Flat,
class EW,
class EV>
4771 static void compute(Flat
const & flatScatter, EW & ew, EV & ev)
4773 EigenvectorType scatter(ev.shape());
4774 acc_detail::flatScatterMatrixToScatterMatrix(scatter, flatScatter);
4780 static void compute(
double v,
double & ew,
double & ev)
4795 static std::string name()
4797 return "DivideByCount<ScatterMatrixEigensystem>";
4802 template <
class U,
class BASE>
4806 typedef typename LookupDependency<ScatterMatrixEigensystem, BASE>::type SMImpl;
4807 typedef typename SMImpl::element_type element_type;
4808 typedef typename SMImpl::EigenvalueType EigenvalueType;
4809 typedef typename SMImpl::EigenvectorType EigenvectorType;
4810 typedef std::pair<EigenvalueType, EigenvectorType const &> value_type;
4811 typedef value_type
const & result_type;
4813 mutable value_type value_;
4816 : value_(EigenvalueType(), BASE::template call_getDependency<ScatterMatrixEigensystem>().second)
4824 void update(U
const &)
4829 void update(U
const &,
double)
4836 value_.first = element_type();
4840 template <
class Shape>
4841 void reshape(Shape
const & s)
4844 acc_detail::reshapeImpl(value_.first,
Shape2(size,1));
4847 result_type operator()()
const
4851 value_.first = getDependency<ScatterMatrixEigensystem>(*this).first / getDependency<Count>(*this);
4949 static std::string name()
4951 return "Principal<PowerSum<2> >";
4956 template <
class U,
class BASE>
4960 typedef typename LookupDependency<ScatterMatrixEigensystem, BASE>::type::EigenvalueType value_type;
4961 typedef value_type
const & result_type;
4963 result_type operator()()
const
4965 return getDependency<ScatterMatrixEigensystem>(*this).first;
4980 static std::string name()
4982 return "Principal<CoordinateSystem>";
4987 template <
class U,
class BASE>
4991 typedef typename LookupDependency<ScatterMatrixEigensystem, BASE>::type::EigenvectorType value_type;
4992 typedef value_type
const & result_type;
4994 result_type operator()()
const
4996 return getDependency<ScatterMatrixEigensystem>(*this).second;
5010 static std::string name()
5017 template <
class U,
class BASE>
5021 typedef typename AccumulatorResultTraits<U>::element_type element_type;
5022 typedef typename AccumulatorResultTraits<U>::MinmaxType value_type;
5023 typedef value_type
const & result_type;
5029 value_ = NumericTraits<element_type>::max();
5034 value_ = NumericTraits<element_type>::max();
5037 template <
class Shape>
5038 void reshape(Shape
const & s)
5040 acc_detail::reshapeImpl(value_, s, NumericTraits<element_type>::max());
5045 updateImpl(o.value_);
5048 void update(U
const & t)
5053 void update(U
const & t,
double)
5058 result_type operator()()
const
5065 void updateImpl(T
const & o)
5067 using namespace multi_math;
5068 value_ = min(value_, o);
5071 template <
class T,
class Alloc>
5074 value_ = multi_math::min(value_, o);
5088 static std::string name()
5095 template <
class U,
class BASE>
5099 typedef typename AccumulatorResultTraits<U>::element_type element_type;
5100 typedef typename AccumulatorResultTraits<U>::MinmaxType value_type;
5101 typedef value_type
const & result_type;
5107 value_ = NumericTraits<element_type>::min();
5112 value_ = NumericTraits<element_type>::min();
5115 template <
class Shape>
5116 void reshape(Shape
const & s)
5118 acc_detail::reshapeImpl(value_, s, NumericTraits<element_type>::min());
5123 updateImpl(o.value_);
5126 void update(U
const & t)
5131 void update(U
const & t,
double)
5136 result_type operator()()
const
5143 void updateImpl(T
const & o)
5145 using namespace multi_math;
5146 value_ = max(value_, o);
5149 template <
class T,
class Alloc>
5152 value_ = multi_math::max(value_, o);
5167 static std::string name()
5174 template <
class U,
class BASE>
5178 typedef typename AccumulatorResultTraits<U>::element_type element_type;
5179 typedef typename AccumulatorResultTraits<U>::MinmaxType value_type;
5180 typedef value_type
const & result_type;
5190 value_ = element_type();
5193 template <
class Shape>
5194 void reshape(Shape
const & s)
5196 acc_detail::reshapeImpl(value_, s);
5202 if(reverse(o.value_) < reverse(value_))
5206 void update(U
const & t)
5208 if(getDependency<Count>(*
this) == 1)
5212 void update(U
const & t,
double weight)
5217 result_type operator()()
const
5235 static std::string name()
5242 template <
class U,
class BASE>
5246 typedef typename AccumulatorResultTraits<U>::MinmaxType minmax_type;
5247 typedef std::pair<minmax_type, minmax_type> value_type;
5248 typedef value_type result_type;
5250 result_type operator()()
const
5252 return value_type(getDependency<Minimum>(*
this), getDependency<Maximum>(*
this));
5266 static std::string name()
5268 return "ArgMinWeight";
5273 template <
class U,
class BASE>
5277 typedef typename AccumulatorResultTraits<U>::element_type element_type;
5278 typedef typename AccumulatorResultTraits<U>::MinmaxType value_type;
5279 typedef value_type
const & result_type;
5285 : min_weight_(NumericTraits<double>::max()),
5291 min_weight_ = NumericTraits<double>::max();
5292 value_ = element_type();
5295 template <
class Shape>
5296 void reshape(Shape
const & s)
5298 acc_detail::reshapeImpl(value_, s);
5303 using namespace multi_math;
5304 if(o.min_weight_ < min_weight_)
5306 min_weight_ = o.min_weight_;
5311 void update(U
const & t)
5313 vigra_precondition(
false,
"ArgMinWeight::update() needs weights.");
5316 void update(U
const & t,
double weight)
5318 if(weight < min_weight_)
5320 min_weight_ = weight;
5325 result_type operator()()
const
5341 static std::string name()
5343 return "ArgMaxWeight";
5348 template <
class U,
class BASE>
5352 typedef typename AccumulatorResultTraits<U>::element_type element_type;
5353 typedef typename AccumulatorResultTraits<U>::MinmaxType value_type;
5354 typedef value_type
const & result_type;
5360 : max_weight_(NumericTraits<double>::min()),
5366 max_weight_ = NumericTraits<double>::min();
5367 value_ = element_type();
5370 template <
class Shape>
5371 void reshape(Shape
const & s)
5373 acc_detail::reshapeImpl(value_, s);
5378 using namespace multi_math;
5379 if(o.max_weight_ > max_weight_)
5381 max_weight_ = o.max_weight_;
5386 void update(U
const & t)
5388 vigra_precondition(
false,
"ArgMaxWeight::update() needs weights.");
5391 void update(U
const & t,
double weight)
5393 if(weight > max_weight_)
5395 max_weight_ = weight;
5400 result_type operator()()
const
5408 template <
class BASE,
int BinCount>
5414 typedef double element_type;
5416 typedef value_type
const & result_type;
5419 double left_outliers, right_outliers;
5429 value_ = element_type();
5430 left_outliers = 0.0;
5431 right_outliers = 0.0;
5437 left_outliers += o.left_outliers;
5438 right_outliers += o.right_outliers;
5441 result_type operator()()
const
5447 template <
class BASE>
5448 class HistogramBase<BASE, 0>
5453 typedef double element_type;
5454 typedef MultiArray<1, double> value_type;
5455 typedef value_type
const & result_type;
5458 double left_outliers, right_outliers;
5468 value_ = element_type();
5469 left_outliers = 0.0;
5470 right_outliers = 0.0;
5475 if(value_.size() == 0)
5479 else if(o.value_.size() > 0)
5481 vigra_precondition(value_.size() == o.value_.size(),
5482 "HistogramBase::operator+=(): bin counts must be equal.");
5485 left_outliers += o.left_outliers;
5486 right_outliers += o.right_outliers;
5489 void setBinCount(
int binCount)
5491 vigra_precondition(binCount > 0,
5492 "HistogramBase:.setBinCount(): binCount > 0 required.");
5493 value_type(
Shape1(binCount)).swap(value_);
5496 result_type operator()()
const
5502 template <
class BASE,
int BinCount,
class U=
typename BASE::input_type>
5503 class RangeHistogramBase
5504 :
public HistogramBase<BASE, BinCount>
5507 double scale_, offset_, inverse_scale_;
5509 RangeHistogramBase()
5519 inverse_scale_ = 0.0;
5520 HistogramBase<BASE, BinCount>::reset();
5523 void operator+=(RangeHistogramBase
const & o)
5525 vigra_precondition(scale_ == 0.0 || o.scale_ == 0.0 || (scale_ == o.scale_ && offset_ == o.offset_),
5526 "RangeHistogramBase::operator+=(): cannot merge histograms with different data mapping.");
5532 offset_ = o.offset_;
5533 inverse_scale_ = o.inverse_scale_;
5537 void update(U
const & t)
5542 void update(U
const & t,
double weight)
5544 double m = mapItem(t);
5545 int index = (m == (double)this->value_.size())
5549 this->left_outliers += weight;
5550 else if(index >= (
int)this->value_.size())
5551 this->right_outliers += weight;
5553 this->value_[index] += weight;
5556 void setMinMax(
double mi,
double ma)
5558 vigra_precondition(this->value_.size() > 0,
5559 "RangeHistogramBase::setMinMax(...): setBinCount(...) has not been called.");
5560 vigra_precondition(mi <= ma,
5561 "RangeHistogramBase::setMinMax(...): min <= max required.");
5563 ma += this->value_.size() * NumericTraits<double>::epsilon();
5565 scale_ = (double)this->value_.size() / (ma - mi);
5566 inverse_scale_ = 1.0 / scale_;
5569 double mapItem(
double t)
const
5571 return scale_ * (t - offset_);
5574 double mapItemInverse(
double t)
const
5576 return inverse_scale_ * t + offset_;
5579 template <
class ArrayLike>
5580 void computeStandardQuantiles(
double minimum,
double maximum,
double count,
5581 ArrayLike
const & desiredQuantiles, ArrayLike & res)
const
5587 ArrayVector<double> keypoints, cumhist;
5588 double mappedMinimum = mapItem(minimum);
5589 double mappedMaximum = mapItem(maximum);
5591 keypoints.push_back(mappedMinimum);
5592 cumhist.push_back(0.0);
5594 if(this->left_outliers > 0.0)
5596 keypoints.push_back(0.0);
5597 cumhist.push_back(this->left_outliers);
5600 int size = (int)this->value_.size();
5601 double cumulative = this->left_outliers;
5602 for(
int k=0; k<size; ++k)
5604 if(this->value_[k] > 0.0)
5606 if(keypoints.back() <= k)
5608 keypoints.push_back(k);
5609 cumhist.push_back(cumulative);
5611 cumulative += this->value_[k];
5612 keypoints.push_back(k+1);
5613 cumhist.push_back(cumulative);
5617 if(this->right_outliers > 0.0)
5619 if(keypoints.back() != size)
5621 keypoints.push_back(size);
5622 cumhist.push_back(cumulative);
5624 keypoints.push_back(mappedMaximum);
5625 cumhist.push_back(count);
5629 keypoints.back() = mappedMaximum;
5630 cumhist.back() = count;
5633 int quantile = 0, end = (int)desiredQuantiles.size();
5635 if(desiredQuantiles[0] == 0.0)
5640 if(desiredQuantiles[end-1] == 1.0)
5642 res[end-1] = maximum;
5647 double qcount = count * desiredQuantiles[quantile];
5648 while(quantile < end)
5650 if(cumhist[point] < qcount && cumhist[point+1] >= qcount)
5652 double t = (qcount - cumhist[point]) / (cumhist[point+1] - cumhist[point]) * (keypoints[point+1] - keypoints[point]);
5653 res[quantile] = mapItemInverse(t + keypoints[point]);
5655 qcount = count * desiredQuantiles[quantile];
5673 template <
int BinCount>
5674 class IntegerHistogram
5678 typedef Select<> Dependencies;
5680 static std::string name()
5682 return std::string(
"IntegerHistogram<") +
asString(BinCount) +
">";
5687 template <
class U,
class BASE>
5689 :
public HistogramBase<BASE, BinCount>
5691 void update(
int index)
5694 ++this->left_outliers;
5695 else if(index >= (
int)this->value_.size())
5696 ++this->right_outliers;
5698 ++this->value_[index];
5701 void update(
int index,
double weight)
5705 vigra_precondition(
false,
"IntegerHistogram::update(): weighted histograms not supported, use another histogram type.");
5708 template <
class ArrayLike>
5709 void computeStandardQuantiles(
double minimum,
double maximum,
double count,
5710 ArrayLike
const & desiredQuantiles, ArrayLike & res)
const
5712 int quantile = 0, end = (int)desiredQuantiles.size();
5714 if(desiredQuantiles[0] == 0.0)
5719 if(desiredQuantiles[end-1] == 1.0)
5721 res[end-1] = maximum;
5726 int currentBin = 0, size = (int)this->value_.size();
5727 double cumulative1 = this->left_outliers,
5728 cumulative2 = this->value_[currentBin] + cumulative1;
5732 double qcount = desiredQuantiles[quantile]*count + 1.0;
5734 while(quantile < end)
5736 if(cumulative2 == qcount)
5738 res[quantile] = currentBin;
5740 qcount = desiredQuantiles[quantile]*count + 1.0;
5742 else if(cumulative2 > qcount)
5744 if(cumulative1 > qcount)
5746 res[quantile] = minimum;
5748 if(cumulative1 + 1.0 > qcount)
5750 res[quantile] = currentBin - 1 + qcount -
std::floor(qcount);
5754 res[quantile] = currentBin;
5757 qcount = desiredQuantiles[quantile]*count + 1.0;
5759 else if(currentBin == size-1)
5761 res[quantile] = maximum;
5763 qcount = desiredQuantiles[quantile]*count + 1.0;
5768 cumulative1 = cumulative2;
5769 cumulative2 += this->value_[currentBin];
5786 template <
int BinCount>
5787 class UserRangeHistogram
5791 typedef Select<> Dependencies;
5793 static std::string name()
5795 return std::string(
"UserRangeHistogram<") +
asString(BinCount) +
">";
5800 template <
class U,
class BASE>
5802 :
public RangeHistogramBase<BASE, BinCount, U>
5804 void update(U
const & t)
5809 void update(U
const & t,
double weight)
5811 vigra_precondition(this->scale_ != 0.0,
5812 "UserRangeHistogram::update(): setMinMax(...) has not been called.");
5814 RangeHistogramBase<BASE, BinCount, U>::update(t, weight);
5828 template <
int BinCount>
5829 class AutoRangeHistogram
5833 typedef Select<Minimum, Maximum> Dependencies;
5835 static std::string name()
5837 return std::string(
"AutoRangeHistogram<") +
asString(BinCount) +
">";
5842 template <
class U,
class BASE>
5844 :
public RangeHistogramBase<BASE, BinCount, U>
5846 static const unsigned int workInPass = LookupDependency<Minimum, BASE>::type::workInPass + 1;
5848 void update(U
const & t)
5853 void update(U
const & t,
double weight)
5855 if(this->scale_ == 0.0)
5856 this->setMinMax(getDependency<Minimum>(*
this), getDependency<Maximum>(*
this));
5858 RangeHistogramBase<BASE, BinCount, U>::update(t, weight);
5872 template <
int BinCount>
5873 class GlobalRangeHistogram
5877 typedef Select<Global<Minimum>, Global<Maximum>, Minimum, Maximum> Dependencies;
5879 static std::string name()
5881 return std::string(
"GlobalRangeHistogram<") +
asString(BinCount) +
">";
5886 template <
class U,
class BASE>
5888 :
public RangeHistogramBase<BASE, BinCount, U>
5890 static const unsigned int workInPass = LookupDependency<Minimum, BASE>::type::workInPass + 1;
5892 bool useLocalMinimax_;
5895 : useLocalMinimax_(false)
5898 void setRegionAutoInit(
bool locally)
5901 useLocalMinimax_ = locally;
5904 void update(U
const & t)
5909 void update(U
const & t,
double weight)
5911 if(this->scale_ == 0.0)
5913 if(useLocalMinimax_)
5914 this->setMinMax(getDependency<Minimum>(*
this), getDependency<Maximum>(*
this));
5916 this->setMinMax(getDependency<Global<Minimum> >(*
this), getDependency<Global<Maximum> >(*
this));
5919 RangeHistogramBase<BASE, BinCount, U>::update(t, weight);
5928 template <
class HistogramAccumulator>
5929 class StandardQuantiles
5933 typedef typename StandardizeTag<HistogramAccumulator>::type HistogramTag;
5934 typedef Select<HistogramTag, Minimum, Maximum, Count> Dependencies;
5936 static std::string name()
5938 return std::string(
"StandardQuantiles<") + HistogramTag::name() +
" >";
5943 template <
class U,
class BASE>
5945 :
public CachedResultBase<BASE, TinyVector<double, 7>, U>
5947 typedef typename CachedResultBase<BASE, TinyVector<double, 7>, U>::result_type result_type;
5948 typedef typename CachedResultBase<BASE, TinyVector<double, 7>, U>::value_type value_type;
5950 static const unsigned int workInPass = LookupDependency<HistogramTag, BASE>::type::workInPass;
5952 result_type operator()()
const
5956 double desiredQuantiles[] = {0.0, 0.1, 0.25, 0.5, 0.75, 0.9, 1.0 };
5957 getAccumulator<HistogramTag>(*this).computeStandardQuantiles(getDependency<Minimum>(*
this), getDependency<Maximum>(*
this),
5958 getDependency<Count>(*
this), value_type(desiredQuantiles),
5962 return this->value_;
5968 struct feature_RegionContour_can_only_be_computed_for_2D_arrays
5969 : vigra::staticAssert::AssertBool<N==2>
5981 static std::string name()
5983 return std::string(
"RegionContour");
5988 template <
class T,
class BASE>
5992 typedef HandleArgSelector<T, LabelArgTag, BASE> LabelHandle;
5995 typedef value_type
const & result_type;
5998 value_type contour_;
6005 void setCoordinateOffset(point_type
const & offset)
6010 template <
class U,
class NEXT>
6013 VIGRA_STATIC_ASSERT((feature_RegionContour_can_only_be_computed_for_2D_arrays<
6015 if(getDependency<Count>(*
this) == 1)
6018 extractContour(LabelHandle::getHandle(t).arrayView(), t.point(), contour_);
6019 contour_ += offset_;
6023 template <
class U,
class NEXT>
6031 vigra_precondition(
false,
6032 "RegionContour::operator+=(): RegionContour cannot be merged.");
6035 result_type operator()()
const
6054 static std::string name()
6056 return std::string(
"RegionPerimeter");
6061 template <
class T,
class BASE>
6065 typedef double value_type;
6066 typedef value_type result_type;
6068 result_type operator()()
const
6070 return getDependency<RegionContour>(*this).length();
6087 static std::string name()
6089 return std::string(
"RegionCircularity");
6094 template <
class T,
class BASE>
6098 typedef double value_type;
6099 typedef value_type result_type;
6101 result_type operator()()
const
6103 return 2.0*
sqrt(M_PI*getDependency<RegionContour>(*this).area()) / getDependency<RegionContour>(*this).length();
6119 static std::string name()
6121 return std::string(
"RegionEccentricity");
6126 template <
class T,
class BASE>
6130 typedef double value_type;
6131 typedef value_type result_type;
6133 result_type operator()()
const
6135 double M = getDependency<RegionRadii>(*this).front(),
6136 m = getDependency<RegionRadii>(*this).back();
6137 return sqrt(1.0 -
sq(m/M));
6143 struct feature_ConvexHull_can_only_be_computed_for_2D_arrays
6144 : vigra::staticAssert::AssertBool<N==2>
6156 static std::string name()
6158 return std::string(
"ConvexHull");
6163 template <
class T,
class BASE>
6167 static const unsigned int workInPass = 2;
6169 typedef HandleArgSelector<T, LabelArgTag, BASE> LabelHandle;
6172 typedef Impl value_type;
6173 typedef value_type
const & result_type;
6175 polygon_type convex_hull_;
6176 point_type input_center_, convex_hull_center_, defect_center_;
6177 double convexity_, rugosity_, mean_defect_displacement_,
6178 defect_area_mean_, defect_area_variance_, defect_area_skewness_, defect_area_kurtosis_;
6179 int convexity_defect_count_;
6181 bool features_computed_;
6186 , convex_hull_center_()
6190 , mean_defect_displacement_()
6191 , defect_area_mean_()
6192 , defect_area_variance_()
6193 , defect_area_skewness_()
6194 , defect_area_kurtosis_()
6195 , convexity_defect_count_()
6196 , convexity_defect_area_()
6197 , features_computed_(
false)
6200 template <
class U,
class NEXT>
6203 VIGRA_STATIC_ASSERT((feature_ConvexHull_can_only_be_computed_for_2D_arrays<
6205 if(!features_computed_)
6207 using namespace functor;
6208 Shape2 start = getDependency<Coord<Minimum> >(*this),
6209 stop = getDependency<Coord<Maximum> >(*this) +
Shape2(1);
6210 point_type offset(start);
6211 input_center_ = getDependency<RegionCenter>(*this);
6214 convex_hull_.clear();
6215 convexHull(getDependency<RegionContour>(*
this), convex_hull_);
6216 convex_hull_center_ = centroid(convex_hull_);
6218 convexity_ = getDependency<RegionContour>(*this).area() / convex_hull_.area();
6219 rugosity_ = getDependency<RegionContour>(*this).length() / convex_hull_.length();
6222 fillPolygon(convex_hull_ - offset, convex_hull_difference, 1);
6224 LabelHandle::getHandle(t).arrayView().subarray(start, stop),
6225 convex_hull_difference,
6226 ifThenElse(Arg2() == Param(label), Param(0), Arg1()));
6229 convexity_defect_count_ =
6232 if (convexity_defect_count_ != 0)
6236 convexity_defects_stats.ignoreLabel(0);
6239 double total_defect_area = 0.0;
6240 mean_defect_displacement_ = 0.0;
6241 defect_center_ = point_type();
6242 for (
int k = 1; k <= convexity_defect_count_; ++k)
6244 double area = get<Count>(convexity_defects_stats, k);
6245 point_type center = get<RegionCenter>(convexity_defects_stats, k) + offset;
6247 convexity_defect_area_.push_back(area);
6248 total_defect_area += area;
6249 defect_center_ += area*center;
6250 mean_defect_displacement_ += area*
norm(input_center_ - center);
6252 sort(convexity_defect_area_.begin(), convexity_defect_area_.end(),
6253 std::greater<MultiArrayIndex>());
6254 mean_defect_displacement_ /= total_defect_area;
6255 defect_center_ /= total_defect_area;
6260 convexity_defect_area_.end(), defect_area_stats);
6262 defect_area_mean_ = convexity_defect_count_ > 0
6263 ? get<Mean>(defect_area_stats)
6265 defect_area_variance_ = convexity_defect_count_ > 1
6266 ? get<UnbiasedVariance>(defect_area_stats)
6268 defect_area_skewness_ = convexity_defect_count_ > 2
6269 ? get<UnbiasedSkewness>(defect_area_stats)
6271 defect_area_kurtosis_ = convexity_defect_count_ > 3
6272 ? get<UnbiasedKurtosis>(defect_area_stats)
6276 features_computed_ =
true;
6280 template <
class U,
class NEXT>
6288 vigra_precondition(
false,
6289 "ConvexHull::operator+=(): ConvexHull features cannot be merged.");
6292 result_type operator()()
const
6300 polygon_type
const & hull()
const
6302 return convex_hull_;
6308 double inputArea()
const
6310 vigra_precondition(features_computed_,
6311 "ConvexHull: features must be calculated first.");
6312 return getDependency<RegionContour>(*this).area();
6318 double hullArea()
const
6320 vigra_precondition(features_computed_,
6321 "ConvexHull: features must be calculated first.");
6322 return convex_hull_.area();
6328 double inputPerimeter()
const
6330 vigra_precondition(features_computed_,
6331 "ConvexHull: features must be calculated first.");
6332 return getDependency<RegionContour>(*this).length();
6338 double hullPerimeter()
const
6340 vigra_precondition(features_computed_,
6341 "ConvexHull: features must be calculated first.");
6342 return convex_hull_.length();
6348 point_type
const & inputCenter()
const
6350 return input_center_;
6356 point_type
const & hullCenter()
const
6358 return convex_hull_center_;
6364 point_type
const & convexityDefectCenter()
const
6366 return defect_center_;
6374 double convexity()
const
6376 vigra_precondition(features_computed_,
6377 "ConvexHull: features must be calculated first.");
6386 double rugosity()
const
6388 vigra_precondition(features_computed_,
6389 "ConvexHull: features must be calculated first.");
6397 int convexityDefectCount()
const
6399 vigra_precondition(features_computed_,
6400 "ConvexHull: features must be calculated first.");
6401 return convexity_defect_count_;
6407 double convexityDefectAreaMean()
const
6409 vigra_precondition(features_computed_,
6410 "ConvexHull: features must be calculated first.");
6411 return defect_area_mean_;
6417 double convexityDefectAreaVariance()
const
6419 vigra_precondition(features_computed_,
6420 "ConvexHull: features must be calculated first.");
6421 return defect_area_variance_;
6427 double convexityDefectAreaSkewness()
const
6429 vigra_precondition(features_computed_,
6430 "ConvexHull: features must be calculated first.");
6431 return defect_area_skewness_;
6437 double convexityDefectAreaKurtosis()
const
6439 vigra_precondition(features_computed_,
6440 "ConvexHull: features must be calculated first.");
6441 return defect_area_kurtosis_;
6448 double meanDefectDisplacement()
const
6450 vigra_precondition(features_computed_,
6451 "ConvexHull: features must be calculated first.");
6452 return mean_defect_displacement_;
6460 vigra_precondition(features_computed_,
6461 "ConvexHull: features must be calculated first.");
6462 return convexity_defect_area_;
6470 #endif // VIGRA_ACCUMULATOR_HXX