vigra - vigra/accumulator-grammar.hxx Source File

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

vigra/accumulator-grammar.hxx |

    00001 /************************************************************************/
    00002 /*                                                                      */
    00003 /*               Copyright 2011-2012 by Ullrich Koethe                  */
    00004 /*                                                                      */
    00005 /*    This file is part of the VIGRA computer vision library.           */
    00006 /*    The VIGRA Website is                                              */
    00007 /*        http://hci.iwr.uni-heidelberg.de/vigra/                       */
    00008 /*    Please direct questions, bug reports, and contributions to        */
    00009 /*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
    00010 /*        vigra@informatik.uni-hamburg.de                               */
    00011 /*                                                                      */
    00012 /*    Permission is hereby granted, free of charge, to any person       */
    00013 /*    obtaining a copy of this software and associated documentation    */
    00014 /*    files (the "Software"), to deal in the Software without           */
    00015 /*    restriction, including without limitation the rights to use,      */
    00016 /*    copy, modify, merge, publish, distribute, sublicense, and/or      */
    00017 /*    sell copies of the Software, and to permit persons to whom the    */
    00018 /*    Software is furnished to do so, subject to the following          */
    00019 /*    conditions:                                                       */
    00020 /*                                                                      */
    00021 /*    The above copyright notice and this permission notice shall be    */
    00022 /*    included in all copies or substantial portions of the             */
    00023 /*    Software.                                                         */
    00024 /*                                                                      */
    00025 /*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
    00026 /*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
    00027 /*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
    00028 /*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
    00029 /*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
    00030 /*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
    00031 /*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
    00032 /*    OTHER DEALINGS IN THE SOFTWARE.                                   */
    00033 /*                                                                      */
    00034 /************************************************************************/
    00035
    00036 #ifndef VIGRA_ACCUMULATOR_GRAMMAR_HXX
    00037 #define VIGRA_ACCUMULATOR_GRAMMAR_HXX
    00038
    00039 #ifdef _MSC_VER
    00040 #pragma warning (disable: 4503)
    00041 #endif
    00042
    00043 #include "config.hxx"
    00044 #include "metaprogramming.hxx"
    00045
    00046 namespace vigra {
    00047
    00048 namespace acc {
    00049
    00050 /**************************************************************************/
    00051 /*                                                                        */
    00052 /*                      irreducible basic accumulators                    */
    00053 /*                                                                        */
    00054 /**************************************************************************/
    00055
    00056
    00057 class CoordinateSystem;                        // returns an identity matrix of appropriate size
    00058
    00059 template <unsigned N> class PowerSum;          // sum over powers of values
    00060 template <unsigned N> class AbsPowerSum;       // sum over powers of absolute values
    00061
    00062 class Skewness;                                // skewness
    00063 class UnbiasedSkewness;                        // unbiased estimator for skewness
    00064 class Kurtosis;                                // excess kurtosis
    00065 class UnbiasedKurtosis;                        // unbiased estimator for excess kurtosis
    00066 class FlatScatterMatrix;                       // flattened upper-triangular part of the scatter matrix
    00067 class ScatterMatrixEigensystem;                // eigenvalues and eigenvectors of the scatter matrix
    00068
    00069     // in all histogram classes: set bin count at runtime if BinCount == 0
    00070 template <int BinCount> class IntegerHistogram;      // use data values directly as bin indices
    00071 template <int BinCount> class UserRangeHistogram;    // set min/max explicitly at runtime
    00072 template <int BinCount> class AutoRangeHistogram;    // get min/max from accumulators
    00073 template <int BinCount> class GlobalRangeHistogram;  // like AutoRangeHistogram, but use global min/max rather than region min/max
    00074
    00075 class Minimum;                                 // minimum
    00076 class Maximum;                                 // maximum
    00077 template <class Hist> class StandardQuantiles; // compute (min, 10%, 25%, 50%, 75%, 90%, max) quantiles from
    00078                                                // min/max accumulators and given histogram
    00079
    00080 class ArgMinWeight;                            // store the value (or coordinate) where weight was minimal
    00081 class ArgMaxWeight;                            // store the value (or coordinate) where weight was maximal
    00082
    00083     // FIXME: not yet implemented
    00084 template <unsigned NDim> class MultiHistogram; // multi-dimensional histogram
    00085                                                // (always specify number of bins at runtime)
    00086
    00087 class Centralize;                              // cache centralized values
    00088 class PrincipalProjection;                     // cache values after principal projection
    00089     // FIXME: not yet implemented
    00090 class Whiten;                                  // cache values after whitening
    00091 class RangeMapping;                            // map value from [min, max] to another range and cache result (e.g. for histogram creation)
    00092
    00093 template <int INDEX>  class DataArg;           // specifiy the index of the data member in a CoupledHandle
    00094 template <int INDEX>  class WeightArg;         // specifiy the index of the weight member in a CoupledHandle
    00095 template <int INDEX>  class LabelArg;          // specifiy the index of the label member in a CoupledHandle
    00096 template <int INDEX>  class CoordArg;          // specifiy the index of the coord member in a CoupledHandle
    00097
    00098 /*
    00099 Quantiles other than minimum and maximum require more thought:
    00100 --------------------------------------------------------------
    00101  * Exact quantiles can be found in time O(n) using recursive partitioning (quickselect),
    00102    but this requires the data (or an auxiliary index array) to be re-arranged.
    00103  * Exact quantiles can be found in time O(k*n) using recursive histogram refinement,
    00104    were k = O(log(n)/log(BinCount)) is the expected number of required passes over the
    00105    data, provided that bins are filled approximately evenly. If data can be re-arranged,
    00106    such that we remember the items corresponding to each bin, running time reduces to O(n)
    00107    (this is Tibshirani's 'binmedian' algorithm). For the median, Tibshirani proves that
    00108    the initial histogram only needs to cover the interval [Mean-StdDev, Mean+StdDev].
    00109  * Both strategies can be combined: perform k passes to reduce bin size to about
    00110    n/(BinCount)^k, and then perform quickselect on an auxiliary array of size
    00111    O(n/(BinCount)^k) which has been filled during the final pass.
    00112  * Good approximate results can be obtained by early stopping of histogram refinement
    00113    (Tibshirani's 'binapprox' algorithm). A 2-pass algorithm for the median achieves
    00114    accuracy of StdDev/BinCount: Mean and StdDev are computed during pass 1,
    00115    and a histogram over [Mean-StdDev, Mean+StdDev] during pass 2.
    00116  * A 1-pass approximation method is described in Chen et al. However, it assumes that
    00117    samples arrive in random order which is usually not true in image data.
    00118 */
    00119
    00120 /**************************************************************************/
    00121 /*                                                                        */
    00122 /*                  modifiers for composite accumulators                  */
    00123 /*                                                                        */
    00124 /**************************************************************************/
    00125
    00126    // data normalization w.r.t. number of samples
    00127 template <class A>    class DivideByCount;       //  A / count
    00128 template <class A>    class RootDivideByCount;   //  sqrt(A / count)
    00129 template <class A>    class DivideUnbiased;      //  A / (count - 1)
    00130 template <class A>    class RootDivideUnbiased;  //  sqrt(A / (count - 1))
    00131
    00132     // data access
    00133 template <class A> class Coord;           // use pixel coordinate instead of pixel value (index 0 of CoupledHandle)
    00134 template <class A> class Weighted;        // use (value, weight) pairs (index 1 and 2 of CoupledHandle)
    00135 template <class A> class CoordWeighted;   // use (coord, weight) pairs(index 0 and end of CoupledHandle)
    00136 template <class A> class DataFromHandle;  // extract data from index 1 of a CoupledHandle
    00137
    00138     // data preparation
    00139 template <class A> class Central;    // subtract mean
    00140 template <class A> class Principal;  // subtract mean and rotate to principal coordinates
    00141
    00142     // FIXME: not implemented yet
    00143 template <class A> class Whitened;   // transform to principal coordinates and scale to unit variance
    00144
    00145 template <class A> class Global;     // compute statistic A globally rather than per region
    00146
    00147 /**************************************************************************/
    00148 /*                                                                        */
    00149 /*                   alias names for important features                   */
    00150 /*                                                                        */
    00151 /**************************************************************************/
    00152
    00153 /** \brief Alias. Count. */
    00154 typedef PowerSum<0>                                 Count;
    00155 /** \brief Alias. Sum. */
    00156 typedef PowerSum<1>                                 Sum;
    00157 /** \brief Alias. Sum of squares. */
    00158 typedef PowerSum<2>                                 SumOfSquares;
    00159
    00160 /** \brief Alias. Mean. */
    00161 typedef DivideByCount<Sum>                          Mean;
    00162 /** \brief Alias. Root mean square. */
    00163 typedef RootDivideByCount<SumOfSquares>             RootMeanSquares;
    00164
    00165 // desired pseudocode (unfortunately not legal in C++)
    00166 //
    00167 //     template <unsigned N>
    00168 //     typedef DivideByCount<PowerSum<N> >          Moment;
    00169 //
    00170 // actual definition (desired behavior is realised by rules below)
    00171 //
    00172 /** \brief Alias. Moment<N>. */
    00173 template <unsigned N> class                         Moment;
    00174 /** \brief Alias. CentralMoment<N>. */
    00175 template <unsigned N> class                         CentralMoment;
    00176
    00177 /** \brief Alias. Sum of squared differences. */
    00178 typedef Central<PowerSum<2> >                       SumOfSquaredDifferences;
    00179 /** \brief Alias. Sum of squared differences. */
    00180 typedef SumOfSquaredDifferences                     SSD;
    00181
    00182 /** \brief Alias. Variance. */
    00183 typedef DivideByCount<Central<PowerSum<2> > >       Variance;
    00184 /** \brief Alias. Standard deviation. */
    00185 typedef RootDivideByCount<Central<PowerSum<2> > >   StdDev;
    00186 /** \brief Alias. Unbiased variance. */
    00187 typedef DivideUnbiased<Central<PowerSum<2> > >      UnbiasedVariance;
    00188 /** \brief Alias. Unbiased standard deviation. */
    00189 typedef RootDivideUnbiased<Central<PowerSum<2> > >  UnbiasedStdDev;
    00190
    00191 /** \brief Alias. Covariance. */
    00192 typedef DivideByCount<FlatScatterMatrix>            Covariance;
    00193 /** \brief Alias. Unbiased covariance. */
    00194 typedef DivideUnbiased<FlatScatterMatrix>           UnbiasedCovariance;
    00195 /** \brief Alias. Covariance eigensystem. */
    00196 typedef DivideByCount<ScatterMatrixEigensystem>     CovarianceEigensystem;
    00197
    00198 /** \brief Alias. Absolute sum. */
    00199 typedef AbsPowerSum<1>                              AbsSum;
    00200 /** \brief Alias. Sum of absolute differences. */
    00201 typedef Central<AbsSum>                             SumOfAbsDifferences;
    00202 /** \brief Alias. Mean absolute deviation. */
    00203 typedef DivideByCount<SumOfAbsDifferences>          MeanAbsoluteDeviation;
    00204
    00205 /** \brief Alias. Region center. */
    00206 typedef Coord<Mean>                                 RegionCenter;
    00207 /** \brief Alias. Region radii. */
    00208 typedef Coord<Principal<StdDev> >                   RegionRadii;
    00209 /** \brief Alias. Region axes. */
    00210 typedef Coord<Principal<CoordinateSystem> >         RegionAxes;
    00211
    00212 /** \brief Alias. Center of mass. */
    00213 typedef Weighted<RegionCenter>                      CenterOfMass;
    00214 /** \brief Alias. Moments of inertia. */
    00215 typedef Weighted<Coord<Principal<Variance> > >      MomentsOfInertia;
    00216 /** \brief Alias. Axes of inertia. */
    00217 typedef Weighted<RegionAxes>                        AxesOfInertia;
    00218
    00219 /**************************************************************************/
    00220 /*                                                                        */
    00221 /*                        Tag standardization rules                       */
    00222 /*                                                                        */
    00223 /**************************************************************************/
    00224
    00225 namespace detail {
    00226
    00227 template <class A>
    00228 struct ModifierRule
    00229 {
    00230     typedef A type;
    00231 };
    00232
    00233 } // namespace detail
    00234
    00235 template <class A>
    00236 struct Error___Tag_modifiers_of_same_kind_must_not_be_combined;
    00237
    00238     // apply rules as long as the Tag type changes ...
    00239 template <class A, class S=typename detail::ModifierRule<A>::type>
    00240 struct StandardizeTag
    00241 {
    00242     typedef typename StandardizeTag<S>::type type;
    00243 };
    00244
    00245     // ... and stop otherwise ...
    00246 template <class A>
    00247 struct StandardizeTag<A, A>
    00248 {
    00249     typedef A type;
    00250 };
    00251
    00252     // ... or fail when the tag spec was non-conforming
    00253 template <class A, class B>
    00254 struct StandardizeTag<A, Error___Tag_modifiers_of_same_kind_must_not_be_combined<B> >
    00255     : public Error___Tag_modifiers_of_same_kind_must_not_be_combined<B>
    00256 {};
    00257
    00258 namespace detail {
    00259
    00260     // Assign priorities to modifiers to determine their standard order (by ascending priority).
    00261     // SubstitutionMask determines which modifiers must be automatically transferred to dependencies.
    00262 enum { MinPriority = 1,
    00263        AccumulatorPriority = 32,
    00264        PrepareDataPriority = 16,
    00265        NormalizePriority = 8,
    00266        AccessDataPriority = 4,
    00267        WeightingPriority = 2,
    00268        GlobalPriority = 1,
    00269        MaxPriority = 32,
    00270        SubstitutionMask = PrepareDataPriority | AccessDataPriority | WeightingPriority | GlobalPriority };
    00271
    00272 template <class A>
    00273 struct ModifierPriority
    00274 {
    00275     static const int value = AccumulatorPriority;
    00276 };
    00277
    00278 #define VIGRA_MODIFIER_PRIORITY(MODIFIER, VALUE) \
    00279 template <class A> \
    00280 struct ModifierPriority<MODIFIER<A> > \
    00281 { \
    00282     static const int value = VALUE; \
    00283 };
    00284
    00285 VIGRA_MODIFIER_PRIORITY(Global, GlobalPriority)
    00286
    00287 VIGRA_MODIFIER_PRIORITY(Weighted, WeightingPriority)
    00288
    00289 VIGRA_MODIFIER_PRIORITY(Coord, AccessDataPriority)
    00290 VIGRA_MODIFIER_PRIORITY(DataFromHandle, AccessDataPriority)
    00291
    00292 VIGRA_MODIFIER_PRIORITY(DivideByCount, NormalizePriority)
    00293 VIGRA_MODIFIER_PRIORITY(RootDivideByCount, NormalizePriority)
    00294 VIGRA_MODIFIER_PRIORITY(DivideUnbiased, NormalizePriority)
    00295 VIGRA_MODIFIER_PRIORITY(RootDivideUnbiased, NormalizePriority)
    00296
    00297 VIGRA_MODIFIER_PRIORITY(Central, PrepareDataPriority)
    00298 VIGRA_MODIFIER_PRIORITY(Principal, PrepareDataPriority)
    00299 VIGRA_MODIFIER_PRIORITY(Whitened, PrepareDataPriority)
    00300
    00301     // explicitly set priority for base accumulators that look like modifiers
    00302 VIGRA_MODIFIER_PRIORITY(StandardQuantiles, AccumulatorPriority)
    00303
    00304 #undef VIGRA_MODIFIER_PRIORITY
    00305
    00306     // check if the tag A contains a modifier with TARGET_PRIORITY
    00307 template <class A, int TARGET_PRIORITY, int PRIORITY=ModifierPriority<A>::value>
    00308 struct HasModifierPriority
    00309 {
    00310     typedef VigraFalseType type;
    00311     static const bool value = false;
    00312 };
    00313
    00314 template <class A, int TARGET_PRIORITY>
    00315 struct HasModifierPriority<A, TARGET_PRIORITY, TARGET_PRIORITY>
    00316 {
    00317     typedef VigraTrueType type;
    00318     static const bool value = true;
    00319 };
    00320
    00321 template <class A, template <class> class B, int TARGET_PRIORITY, int PRIORITY>
    00322 struct HasModifierPriority<B<A>, TARGET_PRIORITY, PRIORITY>
    00323 : public HasModifierPriority<A, TARGET_PRIORITY>
    00324 {};
    00325
    00326 template <class A, template <class> class B, int TARGET_PRIORITY>
    00327 struct HasModifierPriority<B<A>, TARGET_PRIORITY, TARGET_PRIORITY>
    00328 {
    00329     typedef VigraTrueType type;
    00330     static const bool value = true;
    00331 };
    00332
    00333     // three-way compare
    00334 template <class A, class B>
    00335 struct ModifierCompare
    00336 {
    00337     static const int p1 = ModifierPriority<A>::value;
    00338     static const int p2 = ModifierPriority<B>::value;
    00339     static const int value = p1 < p2
    00340                                 ? -1
    00341                                 : p2 < p1
    00342                                      ? 1
    00343                                      : 0;
    00344 };
    00345
    00346 template <class A>
    00347 struct ModifierCompareToInner;
    00348
    00349 template <class A, template <class> class B>
    00350 struct ModifierCompareToInner<B<A> >
    00351 : public ModifierCompare<B<A>, A>
    00352 {};
    00353
    00354     // sort modifiers by ascending priority
    00355 template <class A, int compare=ModifierCompareToInner<A>::value>
    00356 struct ModifierOrder;
    00357
    00358     // do nothing if the order is correct (compare == -1)
    00359 template <class A>
    00360 struct ModifierOrder<A, -1>
    00361 {
    00362     typedef A type;
    00363 };
    00364
    00365     // fail if there are two modifiers with the same priority (compare == 0)
    00366 template <class A, template <class> class B, template <class> class C>
    00367 struct ModifierOrder<C<B<A> >, 0>
    00368 {
    00369     typedef Error___Tag_modifiers_of_same_kind_must_not_be_combined<C<B<A> > > type;
    00370 };
    00371
    00372     // sort if the order is reversed (compare == 1)
    00373 template <class A, template <class> class B, template <class> class C>
    00374 struct ModifierOrder<C<B<A> >, 1>
    00375 {
    00376     typedef B<C<A> > type;
    00377 };
    00378
    00379 #define VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(OUTER, INNER, RESULT) \
    00380 template <class A> \
    00381 struct ModifierOrder<OUTER<INNER<A > >, 0> \
    00382 { \
    00383     typedef RESULT<A > type; \
    00384 };
    00385
    00386     // drop duplicates
    00387 VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(Central, Central, Central)
    00388 VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(Principal, Principal, Principal)
    00389 VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(Whitened, Whitened, Whitened)
    00390
    00391     // the strongest data preparation modifier takes precendence
    00392 VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(Principal, Central, Principal)
    00393 VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(Whitened, Central, Whitened)
    00394 VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(Whitened, Principal, Whitened)
    00395
    00396     // Coord takes precendence over DataFromHandle
    00397 VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS(DataFromHandle, Coord, Coord)
    00398
    00399 #undef VIGRA_CLEANUP_DATA_PREPARATION_MODIFIERS
    00400
    00401     // drop duplicates
    00402 template <class A, template <class> class B>
    00403 struct ModifierRule<B<B<A> > >
    00404 {
    00405     typedef B<A> type;
    00406 };
    00407
    00408 template <class A, int PRIORITY=ModifierPriority<A>::value>
    00409 struct RecurseModifier;
    00410
    00411 template <class A, template <class> class B, int PRIORITY>
    00412 struct RecurseModifier<B<A>, PRIORITY>
    00413 {
    00414     typedef typename ModifierOrder<B<typename StandardizeTag<A>::type> >::type type;
    00415 };
    00416
    00417 template <class A, template <class> class B>
    00418 struct RecurseModifier<B<A>, AccumulatorPriority>
    00419 {
    00420     typedef B<A> type;
    00421 };
    00422
    00423     // recurse down the modifier chain, but only of B is actually a modifier,
    00424     // and not a templated base accumulator (i.e. do not recurse if B's
    00425     // priority is 'AccumulatorPriority')
    00426 template <class A, template <class> class B>
    00427 struct ModifierRule<B<A> >
    00428 : public RecurseModifier<B<A> >
    00429 {};
    00430
    00431     // reduce the SOURCE modifier to the TARGET modifier,
    00432     // using the given TEMPLATE arguments
    00433     // (this is a work-around for the lack of templated typedef in C++)
    00434 #define VIGRA_REDUCE_MODFIER(TEMPLATE, SOURCE, TARGET) \
    00435 template <TEMPLATE > \
    00436 struct ModifierRule<SOURCE > \
    00437 { \
    00438     typedef TARGET type; \
    00439 };
    00440
    00441 #define VIGRA_VOID
    00442
    00443     // centralizing doesn't change the CoordinateSystem
    00444 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Central<CoordinateSystem>, CoordinateSystem)
    00445     // whitened CoordinateSystem are the same as principal CoordinateSystem
    00446 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Whitened<CoordinateSystem>, Principal<CoordinateSystem>)
    00447
    00448     // counting modified data is the same as counting data, except for weighted data and global counting
    00449 VIGRA_REDUCE_MODFIER(template <class> class A, A<Count>, Count)
    00450 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Weighted<Count>, Weighted<Count>)
    00451 VIGRA_REDUCE_MODFIER(VIGRA_VOID, CoordWeighted<Count>, Weighted<Count>)
    00452 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Global<Count>, Global<Count>)
    00453
    00454     // reduce aliases that typedef can't handle
    00455 VIGRA_REDUCE_MODFIER(unsigned N, Moment<N>, DivideByCount<PowerSum<N> >)
    00456 VIGRA_REDUCE_MODFIER(unsigned N, CentralMoment<N>, DivideByCount<Central<PowerSum<N> > >)
    00457 VIGRA_REDUCE_MODFIER(class A, CoordWeighted<A>, Weighted<Coord<A> >)
    00458
    00459     // reduce statistics that are inherently centered
    00460 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Central<Centralize>, Centralize)
    00461 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Central<Skewness>, Skewness)
    00462 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Central<Kurtosis>, Kurtosis)
    00463 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Central<FlatScatterMatrix>, FlatScatterMatrix)
    00464 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Central<ScatterMatrixEigensystem>, ScatterMatrixEigensystem)
    00465
    00466 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Principal<Centralize>, PrincipalProjection)
    00467 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Whitened<Centralize>, Whiten)
    00468 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Principal<PrincipalProjection>, PrincipalProjection)
    00469 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Whitened<PrincipalProjection>, Whiten)
    00470 VIGRA_REDUCE_MODFIER(VIGRA_VOID, Whitened<Whiten>, Whiten)
    00471
    00472     // reduce even absolute powers to plain powers
    00473 template <unsigned N>
    00474 struct ModifierRule<AbsPowerSum<N> >
    00475 {
    00476     typedef typename IfBool<(N % 2 == 0), PowerSum<N>, AbsPowerSum<N> >::type type;
    00477 };
    00478
    00479 #undef VIGRA_VOID
    00480 #undef VIGRA_REDUCE_MODFIER
    00481
    00482 template <class A>
    00483 struct ShouldBeWeighted
    00484 {
    00485     typedef VigraFalseType type;
    00486     static const bool value = false;
    00487 };
    00488
    00489 template <>
    00490 struct ShouldBeWeighted<ArgMinWeight>
    00491 {
    00492     typedef VigraTrueType type;
    00493     static const bool value = true;
    00494 };
    00495
    00496 template <>
    00497 struct ShouldBeWeighted<ArgMaxWeight>
    00498 {
    00499     typedef VigraTrueType type;
    00500     static const bool value = true;
    00501 };
    00502
    00503 template <class A, template <class> class B>
    00504 struct ShouldBeWeighted<B<A> >
    00505 : public ShouldBeWeighted<A>
    00506 {};
    00507
    00508 } // namespace detail
    00509
    00510 template <class A>
    00511 struct IsCoordinateFeature
    00512 {
    00513     typedef VigraFalseType type;
    00514     static const bool value = false;
    00515 };
    00516
    00517 template <class A, template <class> class B>
    00518 struct IsCoordinateFeature<B<A> >
    00519 {
    00520     typedef typename IsCoordinateFeature<A>::type type;
    00521     static const bool value = IsCoordinateFeature<A>::value;
    00522 };
    00523
    00524 template <class A>
    00525 struct IsCoordinateFeature<Coord<A> >
    00526 {
    00527     typedef VigraTrueType type;
    00528     static const bool value = true;
    00529 };
    00530
    00531 template <class A>
    00532 struct IsPrincipalFeature
    00533 {
    00534     typedef VigraFalseType type;
    00535     static const bool value = false;
    00536 };
    00537
    00538 template <class A, template <class> class B>
    00539 struct IsPrincipalFeature<B<A> >
    00540 {
    00541     typedef typename IsPrincipalFeature<A>::type type;
    00542     static const bool value = IsPrincipalFeature<A>::value;
    00543 };
    00544
    00545 template <class A>
    00546 struct IsPrincipalFeature<Principal<A> >
    00547 {
    00548     typedef VigraTrueType type;
    00549     static const bool value = true;
    00550 };
    00551
    00552 template <class A>
    00553 struct IsPrincipalFeature<Whitened<A> >
    00554 {
    00555     typedef VigraTrueType type;
    00556     static const bool value = true;
    00557 };
    00558
    00559 /**************************************************************************/
    00560 /*                                                                        */
    00561 /*                           Tag transfer rules                           */
    00562 /*                                                                        */
    00563 /**************************************************************************/
    00564
    00565 namespace detail {
    00566
    00567 template <class A>
    00568 struct DefaultModifier;
    00569
    00570 template <class A>
    00571 struct ModifierPriority<DefaultModifier<A> >
    00572 {
    00573     static const int value = ModifierPriority<A>::value << 1;
    00574 };
    00575
    00576 template <class A, int TargetPriority, int Priority=ModifierPriority<A>::value>
    00577 struct InsertDefaultModifier
    00578 {
    00579     typedef DefaultModifier<typename InsertDefaultModifier<A, (TargetPriority << 1)>::type> type;
    00580 };
    00581
    00582 template <class A, int TargetPriority>
    00583 struct InsertDefaultModifier<A, TargetPriority, TargetPriority>
    00584 {
    00585     typedef A type;
    00586 };
    00587
    00588 template <class A, int TargetPriority, int Priority=ModifierPriority<A>::value>
    00589 struct TagLongForm;
    00590
    00591 template <class A, int TargetPriority>
    00592 struct TagLongForm<A, TargetPriority, MaxPriority>
    00593 {
    00594     typedef typename InsertDefaultModifier<A, TargetPriority>::type type;
    00595 };
    00596
    00597 template <class A, template <class> class B, int TargetPriority>
    00598 struct TagLongForm<B<A>, TargetPriority, MaxPriority>
    00599 {
    00600     typedef typename InsertDefaultModifier<B<A>, TargetPriority>::type type;
    00601 };
    00602
    00603 template <class A, template <class> class B, int TargetPriority, int Priority>
    00604 struct TagLongForm<B<A>, TargetPriority, Priority>
    00605 {
    00606     typedef typename TagLongForm<A, (Priority << 1)>::type Inner;
    00607     typedef typename InsertDefaultModifier<B<Inner>, TargetPriority>::type type;
    00608 };
    00609
    00610 template <class A, template <class> class B, int TargetPriority>
    00611 struct TagLongForm<B<A>, TargetPriority, TargetPriority>
    00612 {
    00613     typedef typename TagLongForm<A, (TargetPriority << 1)>::type Inner;
    00614     typedef B<Inner> type;
    00615 };
    00616
    00617 template <class A>
    00618 struct LongModifierRule
    00619 {
    00620     typedef A type;
    00621 };
    00622
    00623     // apply rules as long as the Tag type changes ...
    00624 template <class A, class S=typename LongModifierRule<A>::type>
    00625 struct StandardizeTagLongForm
    00626 {
    00627     typedef typename StandardizeTagLongForm<S>::type type;
    00628 };
    00629
    00630     // ... and stop otherwise ...
    00631 template <class A>
    00632 struct StandardizeTagLongForm<A, A>
    00633 {
    00634     typedef A type;
    00635 };
    00636
    00637 template <class A, template <class> class B>
    00638 struct LongModifierRule<B<A> >
    00639 {
    00640     typedef B<typename LongModifierRule<A>::type> type;
    00641 };
    00642
    00643 template <class A>
    00644 struct LongModifierRule<DefaultModifier<A> >
    00645 {
    00646     typedef A type;
    00647 };
    00648
    00649 #define VIGRA_DROP_DATA_PREPARATION_MODIFIERS(SOURCE, TARGET) \
    00650 template <> \
    00651 struct LongModifierRule<SOURCE > \
    00652 { \
    00653     typedef TARGET type; \
    00654 };
    00655
    00656 VIGRA_DROP_DATA_PREPARATION_MODIFIERS(Central<Sum>, Sum)
    00657 VIGRA_DROP_DATA_PREPARATION_MODIFIERS(Principal<Sum>, Sum)
    00658 VIGRA_DROP_DATA_PREPARATION_MODIFIERS(Whitened<Sum>, Sum)
    00659 VIGRA_DROP_DATA_PREPARATION_MODIFIERS(Principal<FlatScatterMatrix>, FlatScatterMatrix)
    00660 VIGRA_DROP_DATA_PREPARATION_MODIFIERS(Whitened<FlatScatterMatrix>, FlatScatterMatrix)
    00661 VIGRA_DROP_DATA_PREPARATION_MODIFIERS(Principal<ScatterMatrixEigensystem>, ScatterMatrixEigensystem)
    00662 VIGRA_DROP_DATA_PREPARATION_MODIFIERS(Whitened<ScatterMatrixEigensystem>, ScatterMatrixEigensystem)
    00663
    00664 #undef VIGRA_DROP_DATA_PREPARATION_MODIFIERS
    00665
    00666 template <class A>
    00667 struct CheckSubstitutionFlag
    00668 {
    00669     static const bool value = (ModifierPriority<A>::value & SubstitutionMask) != 0;
    00670 };
    00671
    00672 template <class A, class B,
    00673           bool substitute=CheckSubstitutionFlag<A>::value>
    00674 struct SubstituteModifiers;
    00675
    00676 template <class A, class B>
    00677 struct SubstituteModifiers<A, B, false>
    00678 {
    00679     typedef B type;
    00680 };
    00681
    00682 template <class A0, template <class> class A1, class B0, template <class> class B1>
    00683 struct SubstituteModifiers<A1<A0>, B1<B0>, true>
    00684 {
    00685     typedef A1<typename SubstituteModifiers<A0, B0>::type> type;
    00686 };
    00687
    00688 template <class A0, class B0, template <class> class B1>
    00689 struct SubstituteModifiers<DefaultModifier<A0>, B1<B0>, true>
    00690 {
    00691     typedef B1<typename SubstituteModifiers<A0, B0>::type> type;
    00692 };
    00693
    00694 template <class A0, template <class> class A1, class B0, template <class> class B1>
    00695 struct SubstituteModifiers<A1<A0>, B1<B0>, false>
    00696 {
    00697     typedef B1<typename SubstituteModifiers<A0, B0>::type> type;
    00698 };
    00699
    00700 } // namespace detail
    00701
    00702 template <class A, class B>
    00703 struct TransferModifiers
    00704 {
    00705     typedef typename StandardizeTag<A>::type StdA;
    00706     typedef typename StandardizeTag<B>::type StdB;
    00707     typedef typename detail::TagLongForm<StdA, detail::MinPriority>::type AA;
    00708     typedef typename detail::TagLongForm<StdB, detail::MinPriority>::type BB;
    00709     typedef typename detail::SubstituteModifiers<AA, BB>::type AB;
    00710     typedef typename detail::StandardizeTagLongForm<AB>::type StdAB;
    00711     typedef typename StandardizeTag<StdAB>::type type;
    00712 };
    00713
    00714 template <class A, class HEAD, class TAIL>
    00715 struct TransferModifiers<A, TypeList<HEAD, TAIL> >
    00716 {
    00717     typedef TypeList<typename TransferModifiers<A, HEAD>::type,
    00718                      typename TransferModifiers<A, TAIL>::type> type;
    00719 };
    00720
    00721 template <class A>
    00722 struct TransferModifiers<A, void>
    00723 {
    00724     typedef void type;
    00725 };
    00726
    00727 template <class TargetTag, class A=typename TargetTag::Dependencies>
    00728 struct StandardizeDependencies
    00729 #ifndef DOXYGEN
    00730 : public StandardizeDependencies<TargetTag, typename A::type>
    00731 #endif
    00732 {};
    00733
    00734 template <class TargetTag, class HEAD, class TAIL>
    00735 struct StandardizeDependencies<TargetTag, TypeList<HEAD, TAIL> >
    00736 {
    00737     typedef typename StandardizeTag<TargetTag>::type Target;
    00738     typedef typename TransferModifiers<Target, TypeList<HEAD, TAIL> >::type type;
    00739 };
    00740
    00741 template <class TargetTag>
    00742 struct StandardizeDependencies<TargetTag, void>
    00743 {
    00744     typedef void type;
    00745 };
    00746
    00747 }} // namespace vigra::acc
    00748
    00749 #endif // VIGRA_ACCUMULATOR_GRAMMAR_HXX

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python vigra 1.9.0 (Tue Nov 6 2012)