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

| vigra/recursiveconvolution.hxx |
--- | --- | ---

    00001 /************************************************************************/
    00002 /*                                                                      */
    00003 /*               Copyright 1998-2002 by Ullrich Koethe                  */
    00004 /*       Cognitive Systems Group, University of Hamburg, Germany        */
    00005 /*                                                                      */
    00006 /*    This file is part of the VIGRA computer vision library.           */
    00007 /*    ( Version 1.3.2, Jan 27 2005 )                                    */
    00008 /*    You may use, modify, and distribute this software according       */
    00009 /*    to the terms stated in the LICENSE file included in               */
    00010 /*    the VIGRA distribution.                                           */
    00011 /*                                                                      */
    00012 /*    The VIGRA Website is                                              */
    00013 /*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
    00014 /*    Please direct questions, bug reports, and contributions to        */
    00015 /*        koethe@informatik.uni-hamburg.de                              */
    00016 /*                                                                      */
    00017 /*  THIS SOFTWARE IS PROVIDED AS IS AND WITHOUT ANY EXPRESS OR          */
    00018 /*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED      */
    00019 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */
    00020 /*                                                                      */
    00021 /************************************************************************/
    00022
    00023
    00024 #ifndef VIGRA_RECURSIVECONVOLUTION_HXX
    00025 #define VIGRA_RECURSIVECONVOLUTION_HXX
    00026
    00027 #include <cmath>
    00028 #include <vector>
    00029 #include "vigra/utilities.hxx"
    00030 #include "vigra/numerictraits.hxx"
    00031 #include "vigra/imageiteratoradapter.hxx"
    00032 #include "vigra/bordertreatment.hxx"
    00033
    00034 namespace vigra {
    00035
    00036 /********************************************************/
    00037 /*                                                      */
    00038 /*         Recursive convolution functions              */
    00039 /*                                                      */
    00040 /********************************************************/
    00041
    00042 /** \addtogroup RecursiveConvolution Recursive convolution functions
    00043
    00044     First order recursive filters and their specialization for
    00045     the exponential filter and its derivatives (1D and separable 2D).
    00046     These filters are very fast, and the speed does not depend on the
    00047     filter size.
    00048 */
    00049 //@{
    00050
    00051 /********************************************************/
    00052 /*                                                      */
    00053 /*                   recursiveFilterLine                */
    00054 /*                                                      */
    00055 /********************************************************/
    00056
    00057 /** \brief Performs a 1-dimensional recursive convolution of the source signal.
    00058
    00059     The function performs a causal and an anti-causal first or second order
    00060     recursive filtering with the given filter parameter <TT>b1</TT> and
    00061     border treatment <TT>border</TT> (first order filter, <TT>b2 = 0</TT>) or parameters
    00062     <TT>b1, b2</TT> and <TT>BORDER_TREATMENT_REFLECT</TT> (second order filter). Thus,
    00063     the result is always a filtering with linear phase.
    00064     \f[
    00065         \begin{array}{rcl}
    00066         a_{i, causal} & = & source_i + b1 * a_{i-1, causal} + b2 * a_{i-2, causal} \\
    00067         a_{i, anticausal} & = & source_i + b1 * a_{i+1, anticausal} + b2 * a_{i+2, anticausal} \\
    00068         dest_i & = & \frac{1 - b1 - b2}{1 + b1 + b2}(a_{i, causal} + a_{i, anticausal} - source_i)
    00069         \end{array}
    00070     \f]
    00071
    00072     The signal's value_type (SrcAccessor::value_type) must be a
    00073     linear space over <TT>double</TT>,
    00074     i.e. addition of source values, multiplication with <TT>double</TT>,
    00075     and <TT>NumericTraits</TT> must be defined.
    00076
    00077     <b> Declaration:</b>
    00078
    00079     <b>First order recursive filter:<b>
    00080
    00081     \code
    00082     namespace vigra {
    00083         template <class SrcIterator, class SrcAccessor,
    00084               class DestIterator, class DestAccessor>
    00085         void recursiveFilterLine(SrcIterator is, SrcIterator isend, SrcAccessor as,
    00086                      DestIterator id, DestAccessor ad,
    00087                      double b1, BorderTreatmentMode border)
    00088     }
    00089     \endcode
    00090
    00091     <b>Second order recursive filter:<b>
    00092
    00093     \code
    00094     namespace vigra {
    00095         template <class SrcIterator, class SrcAccessor,
    00096               class DestIterator, class DestAccessor>
    00097         void recursiveFilterLine(SrcIterator is, SrcIterator isend, SrcAccessor as,
    00098                      DestIterator id, DestAccessor ad,
    00099                      double b1, double b2)
    00100     }
    00101     \endcode
    00102
    00103     <b> Usage:</b>
    00104
    00105     <b>\#include</b> "<a href="recursiveconvolution_8hxx-source.html">vigra/recursiveconvolution.hxx</a>"<br>
    00106     Namespace: vigra
    00107
    00108
    00109     \code
    00110     vector<float> src, dest;
    00111     ...
    00112
    00113     vigra::DefaultAccessor<vector<float>::iterator, float> FAccessor;
    00114
    00115
    00116     vigra::recursiveFilterLine(src.begin(), src.end(), FAccessor(),
    00117                                dest.begin(), FAccessor(),
    00118                                0.5, BORDER_TREATMENT_REFLECT);
    00119     \endcode
    00120
    00121     <b> Required Interface:</b>
    00122
    00123     \code
    00124     RandomAccessIterator is, isend;
    00125     RandomAccessIterator id;
    00126
    00127     SrcAccessor src_accessor;
    00128     DestAccessor dest_accessor;
    00129
    00130     NumericTraits<SrcAccessor::value_type>::RealPromote s = src_accessor(is);
    00131     double d;
    00132
    00133     s = s + s;
    00134     s = d * s;
    00135
    00136     dest_accessor.set(
    00137         NumericTraits<DestAccessor::value_type>::fromRealPromote(s), id);
    00138
    00139     \endcode
    00140
    00141     <b> Preconditions:</b>
    00142
    00143     \code
    00144     -1 < b < 1
    00145     \endcode
    00146
    00147 */
    00148 template <class SrcIterator, class SrcAccessor,
    00149           class DestIterator, class DestAccessor>
    00150 void recursiveFilterLine(SrcIterator is, SrcIterator isend, SrcAccessor as,
    00151                          DestIterator id, DestAccessor ad, double b, BorderTreatmentMode border)
    00152 {
    00153     int w = isend - is;
    00154     SrcIterator istart = is;
    00155
    00156     int x;
    00157
    00158     vigra_precondition(-1.0 < b && b < 1.0,
    00159                  "recursiveFilterLine(): -1 < factor < 1 required.\n");
    00160
    00161     if(b == 0.0)
    00162     {
    00163         for(; is != isend; ++is, ++id)
    00164         {
    00165             ad.set(as(is), id);
    00166         }
    00167         return;
    00168     }
    00169
    00170     double eps = 0.00001;
    00171     int kernelw = std::min(w-1, (int)(VIGRA_CSTD::log(eps)/VIGRA_CSTD::log(VIGRA_CSTD::fabs(b))));
    00172
    00173     typedef typename
    00174         NumericTraits<typename SrcAccessor::value_type>::RealPromote TempType;
    00175     typedef NumericTraits<typename DestAccessor::value_type> DestTraits;
    00176
    00177     // store result of causal filtering
    00178     std::vector<TempType> vline(w);
    00179     typename std::vector<TempType>::iterator line = vline.begin();
    00180
    00181     double norm = (1.0 - b) / (1.0 + b);
    00182
    00183     TempType old;
    00184
    00185     if(border == BORDER_TREATMENT_REPEAT ||
    00186        border == BORDER_TREATMENT_AVOID)
    00187     {
    00188          old = (1.0 / (1.0 - b)) * as(is);
    00189     }
    00190     else if(border == BORDER_TREATMENT_REFLECT)
    00191     {
    00192         is += kernelw;
    00193         old = (1.0 / (1.0 - b)) * as(is);
    00194         for(x = 0; x < kernelw; ++x, --is)
    00195             old = as(is) + b * old;
    00196     }
    00197     else if(border == BORDER_TREATMENT_WRAP)
    00198     {
    00199         is = isend - kernelw;
    00200         old = (1.0 / (1.0 - b)) * as(is);
    00201         for(x = 0; x < kernelw; ++x, ++is)
    00202             old = as(is) + b * old;
    00203     }
    00204     else if(border == BORDER_TREATMENT_CLIP)
    00205     {
    00206         old = NumericTraits<TempType>::zero();
    00207     }
    00208     else
    00209         vigra_fail("recursiveFilterLine(): Unknown border treatment mode.\n");
    00210
    00211     // left side of filter
    00212     for(x=0, is = istart; x < w; ++x, ++is)
    00213     {
    00214         old = as(is) + b * old;
    00215         line[x] = old;
    00216     }
    00217
    00218     // right side of the filter
    00219     if(border == BORDER_TREATMENT_REPEAT ||
    00220        border == BORDER_TREATMENT_AVOID)
    00221     {
    00222         is = isend - 1;
    00223         old = (1.0 / (1.0 - b)) * as(is);
    00224     }
    00225     else if(border == BORDER_TREATMENT_REFLECT)
    00226     {
    00227         old = line[w-2];
    00228     }
    00229     else if(border == BORDER_TREATMENT_WRAP)
    00230     {
    00231       is = istart + kernelw - 1;
    00232       old = (1.0 / (1.0 - b)) * as(is);
    00233       for(x = 0; x < kernelw; ++x, --is)
    00234           old = as(is) + b * old;
    00235     }
    00236     else if(border == BORDER_TREATMENT_CLIP)
    00237     {
    00238         old = NumericTraits<TempType>::zero();
    00239     }
    00240
    00241     is = isend - 1;
    00242     id += w - 1;
    00243     if(border == BORDER_TREATMENT_CLIP)
    00244     {
    00245        // correction factors for b
    00246         double bright = b;
    00247         double bleft = VIGRA_CSTD::pow(b, w);
    00248
    00249         for(x=w-1; x>=0; --x, --is, --id)
    00250         {
    00251             TempType f = b * old;
    00252             old = as(is) + f;
    00253             double norm = (1.0 - b) / (1.0 + b - bleft - bright);
    00254             bleft /= b;
    00255             bright *= b;
    00256             ad.set(norm * (line[x] + f), id);
    00257         }
    00258     }
    00259     else if(border == BORDER_TREATMENT_AVOID)
    00260     {
    00261         for(x=w-1; x >= kernelw; --x, --is, --id)
    00262         {
    00263             TempType f = b * old;
    00264             old = as(is) + f;
    00265             if(x < w - kernelw)
    00266                 ad.set(DestTraits::fromRealPromote(norm * (line[x] + f)), id);
    00267         }
    00268     }
    00269     else
    00270     {
    00271         for(x=w-1; x>=0; --x, --is, --id)
    00272         {
    00273             TempType f = b * old;
    00274             old = as(is) + f;
    00275             ad.set(DestTraits::fromRealPromote(norm * (line[x] + f)), id);
    00276         }
    00277     }
    00278 }
    00279
    00280 /********************************************************/
    00281 /*                                                      */
    00282 /*            recursiveFilterLine (2nd order)           */
    00283 /*                                                      */
    00284 /********************************************************/
    00285
    00286 template <class SrcIterator, class SrcAccessor,
    00287           class DestIterator, class DestAccessor>
    00288 void recursiveFilterLine(SrcIterator is, SrcIterator isend, SrcAccessor as,
    00289                          DestIterator id, DestAccessor ad, double b1, double b2)
    00290 {
    00291     int w = isend - is;
    00292     SrcIterator istart = is;
    00293
    00294     int x;
    00295
    00296     typedef typename
    00297         NumericTraits<typename SrcAccessor::value_type>::RealPromote TempType;
    00298     typedef NumericTraits<typename DestAccessor::value_type> DestTraits;
    00299
    00300     // speichert den Ergebnis der linkseitigen Filterung.
    00301     std::vector<TempType> vline(w+1);
    00302     typename std::vector<TempType>::iterator line = vline.begin();
    00303
    00304     double norm  = 1.0 - b1 - b2;
    00305     double norm1 = (1.0 - b1 - b2) / (1.0 + b1 + b2);
    00306     double norm2 = norm * norm;
    00307
    00308
    00309     // init left side of filter
    00310     int kernelw = std::min(w-1, std::max(8, (int)(1.0 / norm + 0.5)));
    00311     is += (kernelw - 2);
    00312     line[kernelw] = as(is);
    00313     line[kernelw-1] = as(is);
    00314     for(x = kernelw - 2; x > 0; --x, --is)
    00315     {
    00316         line[x] = as(is) + b1 * line[x+1] + b2 * line[x+2];
    00317     }
    00318     line[0] = as(is) + b1 * line[1] + b2 * line[2];
    00319     ++is;
    00320     line[1] = as(is) + b1 * line[0] + b2 * line[1];
    00321     ++is;
    00322     for(x=2; x < w; ++x, ++is)
    00323     {
    00324         line[x] = as(is) + b1 * line[x-1] + b2 * line[x-2];
    00325     }
    00326     line[w] = line[w-1];
    00327
    00328     line[w-1] = norm1 * (line[w-1] + b1 * line[w-2] + b2 * line[w-3]);
    00329     line[w-2] = norm1 * (line[w-2] + b1 * line[w] + b2 * line[w-2]);
    00330     id += w-1;
    00331     ad.set(line[w-1], id);
    00332     --id;
    00333     ad.set(line[w-2], id);
    00334     --id;
    00335     for(x=w-3; x>=0; --x, --id, --is)
    00336     {
    00337         line[x] = norm2 * line[x] + b1 * line[x+1] + b2 * line[x+2];
    00338         ad.set(line[x], id);
    00339     }
    00340 }
    00341
    00342 /********************************************************/
    00343 /*                                                      */
    00344 /*                    recursiveSmoothLine               */
    00345 /*                                                      */
    00346 /********************************************************/
    00347
    00348 /** \brief Convolves the image with a 1-dimensional exponential filter.
    00349
    00350     This function calls \ref recursiveFilterLine() with <TT>b = exp(-1.0/scale)</TT>
    00351     and <TT>border = BORDER_TREATMENT_REPEAT</TT>. See
    00352     \ref recursiveFilterLine() for more documentation.
    00353
    00354     <b> Declaration:</b>
    00355
    00356     \code
    00357     namespace vigra {
    00358         template <class SrcIterator, class SrcAccessor,
    00359               class DestIterator, class DestAccessor>
    00360         void recursiveSmoothLine(SrcIterator is, SrcIterator isend, SrcAccessor as,
    00361                      DestIterator id, DestAccessor ad, double scale)
    00362     }
    00363     \endcode
    00364
    00365     <b> Usage:</b>
    00366
    00367     <b>\#include</b> "<a href="recursiveconvolution_8hxx-source.html">vigra/recursiveconvolution.hxx</a>"<br>
    00368     Namespace: vigra
    00369
    00370
    00371     \code
    00372     vector<float> src, dest;
    00373     ...
    00374
    00375     vigra::DefaultAccessor<vector<float>::iterator, float> FAccessor;
    00376
    00377
    00378     vigra::recursiveSmoothLine(src.begin(), src.end(), FAccessor(),
    00379                         dest.begin(), FAccessor(), 3.0);
    00380     \endcode
    00381
    00382     <b> Required Interface:</b>
    00383
    00384     \code
    00385     RandomAccessIterator is, isend;
    00386     RandomAccessIterator id;
    00387
    00388     SrcAccessor src_accessor;
    00389     DestAccessor dest_accessor;
    00390
    00391     NumericTraits<SrcAccessor::value_type>::RealPromote s = src_accessor(is);
    00392     double d;
    00393
    00394     s = s + s;
    00395     s = d * s;
    00396
    00397     dest_accessor.set(
    00398         NumericTraits<DestAccessor::value_type>::fromRealPromote(s), id);
    00399
    00400     \endcode
    00401
    00402     <b> Preconditions:</b>
    00403
    00404     \code
    00405     scale > 0
    00406     \endcode
    00407
    00408 */
    00409 template <class SrcIterator, class SrcAccessor,
    00410           class DestIterator, class DestAccessor>
    00411 inline
    00412 void recursiveSmoothLine(SrcIterator is, SrcIterator isend, SrcAccessor as,
    00413                          DestIterator id, DestAccessor ad, double scale)
    00414 {
    00415     vigra_precondition(scale >= 0,
    00416                  "recursiveSmoothLine(): scale must be >= 0.\n");
    00417
    00418     double b = (scale == 0.0) ?
    00419                     0.0 :
    00420                     VIGRA_CSTD::exp(-1.0/scale);
    00421
    00422     recursiveFilterLine(is, isend, as, id, ad, b, BORDER_TREATMENT_REPEAT);
    00423 }
    00424
    00425 /********************************************************/
    00426 /*                                                      */
    00427 /*             recursiveFirstDerivativeLine             */
    00428 /*                                                      */
    00429 /********************************************************/
    00430
    00431 /** \brief Performs a 1 dimensional recursive convolution of the source signal.
    00432
    00433     It uses the first derivative an exponential  <TT>d/dx exp(-abs(x)/scale)</TT> as
    00434     a kernel. The signal's value_type (SrcAccessor::value_type) must be a
    00435     linear space over <TT>double</TT>,
    00436     i.e. addition and subtraction of source values, multiplication with
    00437     <TT>double</TT>, and <TT>NumericTraits</TT> must be defined. Border
    00438     treatment is always <TT>BORDER_TREATMENT_REPEAT</TT>.
    00439
    00440     <b> Declaration:</b>
    00441
    00442     \code
    00443     namespace vigra {
    00444         template <class SrcIterator, class SrcAccessor,
    00445               class DestIterator, class DestAccessor>
    00446         void recursiveFirstDerivativeLine(SrcIterator is, SrcIterator isend, SrcAccessor as,
    00447                      DestIterator id, DestAccessor ad, double scale)
    00448     }
    00449     \endcode
    00450
    00451     <b> Usage:</b>
    00452
    00453     <b>\#include</b> "<a href="recursiveconvolution_8hxx-source.html">vigra/recursiveconvolution.hxx</a>"<br>
    00454     Namespace: vigra
    00455
    00456
    00457     \code
    00458     vector<float> src, dest;
    00459     ...
    00460
    00461     vigra::DefaultAccessor<vector<float>::iterator, float> FAccessor;
    00462
    00463
    00464     vigra::recursiveFirstDerivativeLine(src.begin(), src.end(), FAccessor(),
    00465                         dest.begin(), FAccessor(), 3.0);
    00466     \endcode
    00467
    00468     <b> Required Interface:</b>
    00469
    00470     \code
    00471     RandomAccessIterator is, isend;
    00472     RandomAccessIterator id;
    00473
    00474     SrcAccessor src_accessor;
    00475     DestAccessor dest_accessor;
    00476
    00477     NumericTraits<SrcAccessor::value_type>::RealPromote s = src_accessor(is);
    00478     double d;
    00479
    00480     s = s + s;
    00481     s = -s;
    00482     s = d * s;
    00483
    00484     dest_accessor.set(
    00485         NumericTraits<DestAccessor::value_type>::fromRealPromote(s), id);
    00486
    00487     \endcode
    00488
    00489     <b> Preconditions:</b>
    00490
    00491     \code
    00492     scale > 0
    00493     \endcode
    00494
    00495 */
    00496 template <class SrcIterator, class SrcAccessor,
    00497           class DestIterator, class DestAccessor>
    00498 void recursiveFirstDerivativeLine(SrcIterator is, SrcIterator isend, SrcAccessor as,
    00499                          DestIterator id, DestAccessor ad, double scale)
    00500 {
    00501     vigra_precondition(scale > 0,
    00502                  "recursiveFirstDerivativeLine(): scale must be > 0.\n");
    00503
    00504     int w = isend -is;
    00505
    00506     int x;
    00507
    00508     typedef typename
    00509         NumericTraits<typename SrcAccessor::value_type>::RealPromote
    00510     TempType;
    00511     typedef NumericTraits<typename DestAccessor::value_type> DestTraits;
    00512
    00513     std::vector<TempType> vline(w);
    00514     typename std::vector<TempType>::iterator line = vline.begin();
    00515
    00516     double b = VIGRA_CSTD::exp(-1.0/scale);
    00517     double norm = (1.0 - b) * (1.0 - b) / 2.0 / b;
    00518     TempType old = (1.0 / (1.0 - b)) * as(is);
    00519
    00520     // left side of filter
    00521     for(x=0; x<w; ++x, ++is)
    00522     {
    00523         old = as(is) + b * old;
    00524         line[x] = -old;
    00525     }
    00526
    00527     // right side of the filter
    00528     --is;
    00529     old = (1.0 / (1.0 - b)) * as(is);
    00530     id += w;
    00531     ++is;
    00532
    00533     for(x=w-1; x>=0; --x)
    00534     {
    00535         --is;
    00536         --id;
    00537
    00538         old = as(is) + b * old;
    00539
    00540         ad.set(DestTraits::fromRealPromote(norm * (line[x] + old)), id);
    00541     }
    00542 }
    00543
    00544 /********************************************************/
    00545 /*                                                      */
    00546 /*            recursiveSecondDerivativeLine             */
    00547 /*                                                      */
    00548 /********************************************************/
    00549
    00550 /** \brief Performs a 1 dimensional recursive convolution of the source signal.
    00551
    00552     It uses the second derivative an exponential  <TT>d2/dx2 exp(-abs(x)/scale)</TT> as
    00553     a kernel. The signal's value_type (SrcAccessor::value_type) must be a
    00554     linear space over <TT>double</TT>,
    00555     i.e. addition and subtraction of source values, multiplication with
    00556     <TT>double</TT>, and <TT>NumericTraits</TT> must be defined. Border
    00557     treatment is always <TT>BORDER_TREATMENT_REPEAT</TT>.
    00558
    00559     <b> Declaration:</b>
    00560
    00561     \code
    00562     namespace vigra {
    00563         template <class SrcIterator, class SrcAccessor,
    00564               class DestIterator, class DestAccessor>
    00565         void recursiveSecondDerivativeLine(SrcIterator is, SrcIterator isend, SrcAccessor as,
    00566                      DestIterator id, DestAccessor ad, double scale)
    00567     }
    00568     \endcode
    00569
    00570     <b> Usage:</b>
    00571
    00572     <b>\#include</b> "<a href="recursiveconvolution_8hxx-source.html">vigra/recursiveconvolution.hxx</a>"<br>
    00573     Namespace: vigra
    00574
    00575
    00576     \code
    00577     vector<float> src, dest;
    00578     ...
    00579
    00580     vigra::DefaultAccessor<vector<float>::iterator, float> FAccessor;
    00581
    00582
    00583     vigra::recursiveSecondDerivativeLine(src.begin(), src.end(), FAccessor(),
    00584                         dest.begin(), FAccessor(), 3.0);
    00585     \endcode
    00586
    00587     <b> Required Interface:</b>
    00588
    00589     \code
    00590     RandomAccessIterator is, isend;
    00591     RandomAccessIterator id;
    00592
    00593     SrcAccessor src_accessor;
    00594     DestAccessor dest_accessor;
    00595
    00596     NumericTraits<SrcAccessor::value_type>::RealPromote s = src_accessor(is);
    00597     double d;
    00598
    00599     s = s + s;
    00600     s = s - s;
    00601     s = d * s;
    00602
    00603     dest_accessor.set(
    00604         NumericTraits<DestAccessor::value_type>::fromRealPromote(s), id);
    00605
    00606     \endcode
    00607
    00608     <b> Preconditions:</b>
    00609
    00610     \code
    00611     scale > 0
    00612     \endcode
    00613
    00614 */
    00615 template <class SrcIterator, class SrcAccessor,
    00616           class DestIterator, class DestAccessor>
    00617 void recursiveSecondDerivativeLine(SrcIterator is, SrcIterator isend, SrcAccessor as,
    00618                          DestIterator id, DestAccessor ad, double scale)
    00619 {
    00620     vigra_precondition(scale > 0,
    00621                  "recursiveSecondDerivativeLine(): scale must be > 0.\n");
    00622
    00623     int w = isend -is;
    00624
    00625     int x;
    00626
    00627     typedef typename
    00628         NumericTraits<typename SrcAccessor::value_type>::RealPromote
    00629     TempType;
    00630     typedef NumericTraits<typename DestAccessor::value_type> DestTraits;
    00631
    00632     std::vector<TempType> vline(w);
    00633     typename std::vector<TempType>::iterator line = vline.begin();
    00634
    00635     double b = VIGRA_CSTD::exp(-1.0/scale);
    00636     double a = -2.0 / (1.0 - b);
    00637     double norm = (1.0 - b) * (1.0 - b) * (1.0 - b) / (1.0 + b);
    00638     TempType old = (1.0 / (1.0 - b)) * as(is);
    00639
    00640     // left side of filter
    00641     for(x=0; x<w; ++x, ++is)
    00642     {
    00643         line[x] = old;
    00644         old = as(is) + b * old;
    00645     }
    00646
    00647     // right side of the filter
    00648     --is;
    00649     old = (1.0 / (1.0 - b)) * as(is);
    00650     id += w;
    00651     ++is;
    00652
    00653     for(x=w-1; x>=0; --x)
    00654     {
    00655         --is;
    00656         --id;
    00657
    00658         TempType f = old + a * as(is);
    00659         old = as(is) + b * old;
    00660         ad.set(DestTraits::fromRealPromote(norm * (line[x] + f)), id);
    00661     }
    00662 }
    00663
    00664 /********************************************************/
    00665 /*                                                      */
    00666 /*                   recursiveFilterX                   */
    00667 /*                                                      */
    00668 /********************************************************/
    00669
    00670 /** \brief Performs 1 dimensional recursive filtering (1st and 2nd order) in x direction.
    00671
    00672     It calls \ref recursiveFilterLine() for every row of the
    00673     image. See \ref recursiveFilterLine() for more information about
    00674     required interfaces and vigra_preconditions.
    00675
    00676     <b> Declarations:</b>
    00677
    00678     pass arguments explicitly:
    00679     \code
    00680     namespace vigra {
    00681         // first order filter
    00682         template <class SrcImageIterator, class SrcAccessor,
    00683                   class DestImageIterator, class DestAccessor>
    00684         void recursiveFilterX(SrcImageIterator supperleft,
    00685                                SrcImageIterator slowerright, SrcAccessor as,
    00686                                DestImageIterator dupperleft, DestAccessor ad,
    00687                                double b, BorderTreatmentMode border);
    00688
    00689         // second order filter
    00690         template <class SrcImageIterator, class SrcAccessor,
    00691                   class DestImageIterator, class DestAccessor>
    00692         void recursiveFilterX(SrcImageIterator supperleft,
    00693                                SrcImageIterator slowerright, SrcAccessor as,
    00694                                DestImageIterator dupperleft, DestAccessor ad,
    00695                                double b1, double b2);
    00696     }
    00697     \endcode
    00698
    00699
    00700     use argument objects in conjunction with \ref ArgumentObjectFactories:
    00701     \code
    00702     namespace vigra {
    00703         // first order filter
    00704         template <class SrcImageIterator, class SrcAccessor,
    00705                   class DestImageIterator, class DestAccessor>
    00706         void recursiveFilterX(
    00707                     triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    00708                     pair<DestImageIterator, DestAccessor> dest,
    00709                     double b, BorderTreatmentMode border);
    00710
    00711         // second order filter
    00712         template <class SrcImageIterator, class SrcAccessor,
    00713                   class DestImageIterator, class DestAccessor>
    00714         void recursiveFilterX(
    00715                     triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    00716                     pair<DestImageIterator, DestAccessor> dest,
    00717                     double b1, double b2);
    00718             }
    00719     \endcode
    00720
    00721     <b> Usage:</b>
    00722
    00723     <b>\#include</b> "<a href="recursiveconvolution_8hxx-source.html">vigra/recursiveconvolution.hxx</a>"<br>
    00724     Namespace: vigra
    00725
    00726     \code
    00727     vigra::FImage src(w,h), dest(w,h);
    00728     ...
    00729
    00730     vigra::recursiveSmoothX(srcImageRange(src), destImage(dest),
    00731            0.5, BORDER_TREATMENT_REFLECT);
    00732
    00733     \endcode
    00734
    00735 */
    00736 template <class SrcImageIterator, class SrcAccessor,
    00737           class DestImageIterator, class DestAccessor>
    00738 void recursiveFilterX(SrcImageIterator supperleft,
    00739                        SrcImageIterator slowerright, SrcAccessor as,
    00740                        DestImageIterator dupperleft, DestAccessor ad,
    00741                        double b, BorderTreatmentMode border)
    00742 {
    00743     int w = slowerright.x - supperleft.x;
    00744     int h = slowerright.y - supperleft.y;
    00745
    00746     int y;
    00747
    00748     for(y=0; y<h; ++y, ++supperleft.y, ++dupperleft.y)
    00749     {
    00750         typename SrcImageIterator::row_iterator rs = supperleft.rowIterator();
    00751         typename DestImageIterator::row_iterator rd = dupperleft.rowIterator();
    00752
    00753         recursiveFilterLine(rs, rs+w, as,
    00754                              rd, ad,
    00755                              b, border);
    00756     }
    00757 }
    00758
    00759 template <class SrcImageIterator, class SrcAccessor,
    00760           class DestImageIterator, class DestAccessor>
    00761 inline void recursiveFilterX(
    00762             triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    00763             pair<DestImageIterator, DestAccessor> dest,
    00764             double b, BorderTreatmentMode border)
    00765 {
    00766     recursiveFilterX(src.first, src.second, src.third,
    00767                       dest.first, dest.second, b, border);
    00768 }
    00769
    00770 /********************************************************/
    00771 /*                                                      */
    00772 /*            recursiveFilterX (2nd order)              */
    00773 /*                                                      */
    00774 /********************************************************/
    00775
    00776 template <class SrcImageIterator, class SrcAccessor,
    00777           class DestImageIterator, class DestAccessor>
    00778 void recursiveFilterX(SrcImageIterator supperleft,
    00779                        SrcImageIterator slowerright, SrcAccessor as,
    00780                        DestImageIterator dupperleft, DestAccessor ad,
    00781                        double b1, double b2)
    00782 {
    00783     int w = slowerright.x - supperleft.x;
    00784     int h = slowerright.y - supperleft.y;
    00785
    00786     int y;
    00787
    00788     for(y=0; y<h; ++y, ++supperleft.y, ++dupperleft.y)
    00789     {
    00790         typename SrcImageIterator::row_iterator rs = supperleft.rowIterator();
    00791         typename DestImageIterator::row_iterator rd = dupperleft.rowIterator();
    00792
    00793         recursiveFilterLine(rs, rs+w, as,
    00794                              rd, ad,
    00795                              b1, b2);
    00796     }
    00797 }
    00798
    00799 template <class SrcImageIterator, class SrcAccessor,
    00800           class DestImageIterator, class DestAccessor>
    00801 inline void recursiveFilterX(
    00802             triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    00803             pair<DestImageIterator, DestAccessor> dest,
    00804                        double b1, double b2)
    00805 {
    00806     recursiveFilterX(src.first, src.second, src.third,
    00807                       dest.first, dest.second, b1, b2);
    00808 }
    00809
    00810 /********************************************************/
    00811 /*                                                      */
    00812 /*                    recursiveSmoothX                  */
    00813 /*                                                      */
    00814 /********************************************************/
    00815
    00816 /** \brief Performs 1 dimensional recursive smoothing in x direction.
    00817
    00818     It calls \ref recursiveSmoothLine() for every row of the
    00819     image. See \ref recursiveSmoothLine() for more information about
    00820     required interfaces and vigra_preconditions.
    00821
    00822     <b> Declarations:</b>
    00823
    00824     pass arguments explicitly:
    00825     \code
    00826     namespace vigra {
    00827         template <class SrcImageIterator, class SrcAccessor,
    00828               class DestImageIterator, class DestAccessor>
    00829         void recursiveSmoothX(SrcImageIterator supperleft,
    00830                   SrcImageIterator slowerright, SrcAccessor as,
    00831                   DestImageIterator dupperleft, DestAccessor ad,
    00832                   double scale)
    00833     }
    00834     \endcode
    00835
    00836
    00837     use argument objects in conjunction with \ref ArgumentObjectFactories:
    00838     \code
    00839     namespace vigra {
    00840         template <class SrcImageIterator, class SrcAccessor,
    00841               class DestImageIterator, class DestAccessor>
    00842         void recursiveSmoothX(
    00843             triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    00844             pair<DestImageIterator, DestAccessor> dest,
    00845             double scale)
    00846     }
    00847     \endcode
    00848
    00849     <b> Usage:</b>
    00850
    00851     <b>\#include</b> "<a href="recursiveconvolution_8hxx-source.html">vigra/recursiveconvolution.hxx</a>"<br>
    00852     Namespace: vigra
    00853
    00854     \code
    00855     vigra::FImage src(w,h), dest(w,h);
    00856     ...
    00857
    00858     vigra::recursiveSmoothX(srcImageRange(src), destImage(dest), 3.0);
    00859
    00860     \endcode
    00861
    00862 */
    00863 template <class SrcImageIterator, class SrcAccessor,
    00864           class DestImageIterator, class DestAccessor>
    00865 void recursiveSmoothX(SrcImageIterator supperleft,
    00866                       SrcImageIterator slowerright, SrcAccessor as,
    00867                       DestImageIterator dupperleft, DestAccessor ad,
    00868               double scale)
    00869 {
    00870     int w = slowerright.x - supperleft.x;
    00871     int h = slowerright.y - supperleft.y;
    00872
    00873     int y;
    00874
    00875     for(y=0; y<h; ++y, ++supperleft.y, ++dupperleft.y)
    00876     {
    00877         typename SrcImageIterator::row_iterator rs = supperleft.rowIterator();
    00878         typename DestImageIterator::row_iterator rd = dupperleft.rowIterator();
    00879
    00880         recursiveSmoothLine(rs, rs+w, as,
    00881                             rd, ad,
    00882                             scale);
    00883     }
    00884 }
    00885
    00886 template <class SrcImageIterator, class SrcAccessor,
    00887           class DestImageIterator, class DestAccessor>
    00888 inline void recursiveSmoothX(
    00889             triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    00890             pair<DestImageIterator, DestAccessor> dest,
    00891         double scale)
    00892 {
    00893     recursiveSmoothX(src.first, src.second, src.third,
    00894                      dest. first, dest.second, scale);
    00895 }
    00896
    00897 /********************************************************/
    00898 /*                                                      */
    00899 /*                     recursiveFilterY                 */
    00900 /*                                                      */
    00901 /********************************************************/
    00902
    00903 /** \brief Performs 1 dimensional recursive filtering (1st and 2nd order) in y direction.
    00904
    00905     It calls \ref recursiveFilterLine() for every column of the
    00906     image. See \ref recursiveFilterLine() for more information about
    00907     required interfaces and vigra_preconditions.
    00908
    00909     <b> Declarations:</b>
    00910
    00911     pass arguments explicitly:
    00912     \code
    00913     namespace vigra {
    00914         // first order filter
    00915         template <class SrcImageIterator, class SrcAccessor,
    00916                   class DestImageIterator, class DestAccessor>
    00917         void recursiveFilterY(SrcImageIterator supperleft,
    00918                                SrcImageIterator slowerright, SrcAccessor as,
    00919                                DestImageIterator dupperleft, DestAccessor ad,
    00920                                double b, BorderTreatmentMode border);
    00921
    00922         // second order filter
    00923         template <class SrcImageIterator, class SrcAccessor,
    00924                   class DestImageIterator, class DestAccessor>
    00925         void recursiveFilterY(SrcImageIterator supperleft,
    00926                                SrcImageIterator slowerright, SrcAccessor as,
    00927                                DestImageIterator dupperleft, DestAccessor ad,
    00928                                double b1, double b2);
    00929     }
    00930     \endcode
    00931
    00932
    00933     use argument objects in conjunction with \ref ArgumentObjectFactories:
    00934     \code
    00935     namespace vigra {
    00936         // first order filter
    00937         template <class SrcImageIterator, class SrcAccessor,
    00938                   class DestImageIterator, class DestAccessor>
    00939         void recursiveFilterY(
    00940                     triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    00941                     pair<DestImageIterator, DestAccessor> dest,
    00942                     double b, BorderTreatmentMode border);
    00943
    00944         // second order filter
    00945         template <class SrcImageIterator, class SrcAccessor,
    00946                   class DestImageIterator, class DestAccessor>
    00947         void recursiveFilterY(
    00948                     triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    00949                     pair<DestImageIterator, DestAccessor> dest,
    00950                     double b1, double b2);
    00951             }
    00952     \endcode
    00953
    00954     <b> Usage:</b>
    00955
    00956     <b>\#include</b> "<a href="recursiveconvolution_8hxx-source.html">vigra/recursiveconvolution.hxx</a>"<br>
    00957     Namespace: vigra
    00958
    00959     \code
    00960     vigra::FImage src(w,h), dest(w,h);
    00961     ...
    00962
    00963     vigra::recursiveFilterY(srcImageRange(src), destImage(dest), -0.6, -0.06);
    00964
    00965     \endcode
    00966
    00967 */
    00968 template <class SrcImageIterator, class SrcAccessor,
    00969           class DestImageIterator, class DestAccessor>
    00970 void recursiveFilterY(SrcImageIterator supperleft,
    00971                        SrcImageIterator slowerright, SrcAccessor as,
    00972                        DestImageIterator dupperleft, DestAccessor ad,
    00973                        double b, BorderTreatmentMode border)
    00974 {
    00975     int w = slowerright.x - supperleft.x;
    00976     int h = slowerright.y - supperleft.y;
    00977
    00978     int x;
    00979
    00980     for(x=0; x<w; ++x, ++supperleft.x, ++dupperleft.x)
    00981     {
    00982         typename SrcImageIterator::column_iterator cs = supperleft.columnIterator();
    00983         typename DestImageIterator::column_iterator cd = dupperleft.columnIterator();
    00984
    00985         recursiveFilterLine(cs, cs+h, as,
    00986                             cd, ad,
    00987                             b, border);
    00988     }
    00989 }
    00990
    00991 template <class SrcImageIterator, class SrcAccessor,
    00992           class DestImageIterator, class DestAccessor>
    00993 inline void recursiveFilterY(
    00994             triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    00995             pair<DestImageIterator, DestAccessor> dest,
    00996             double b, BorderTreatmentMode border)
    00997 {
    00998     recursiveFilterY(src.first, src.second, src.third,
    00999                       dest.first, dest.second, b, border);
    01000 }
    01001
    01002 /********************************************************/
    01003 /*                                                      */
    01004 /*            recursiveFilterY (2nd order)              */
    01005 /*                                                      */
    01006 /********************************************************/
    01007
    01008 template <class SrcImageIterator, class SrcAccessor,
    01009           class DestImageIterator, class DestAccessor>
    01010 void recursiveFilterY(SrcImageIterator supperleft,
    01011                        SrcImageIterator slowerright, SrcAccessor as,
    01012                        DestImageIterator dupperleft, DestAccessor ad,
    01013                        double b1, double b2)
    01014 {
    01015     int w = slowerright.x - supperleft.x;
    01016     int h = slowerright.y - supperleft.y;
    01017
    01018     int x;
    01019
    01020     for(x=0; x<w; ++x, ++supperleft.x, ++dupperleft.x)
    01021     {
    01022         typename SrcImageIterator::column_iterator cs = supperleft.columnIterator();
    01023         typename DestImageIterator::column_iterator cd = dupperleft.columnIterator();
    01024
    01025         recursiveFilterLine(cs, cs+h, as,
    01026                             cd, ad,
    01027                             b1, b2);
    01028     }
    01029 }
    01030
    01031 template <class SrcImageIterator, class SrcAccessor,
    01032           class DestImageIterator, class DestAccessor>
    01033 inline void recursiveFilterY(
    01034             triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    01035             pair<DestImageIterator, DestAccessor> dest,
    01036                        double b1, double b2)
    01037 {
    01038     recursiveFilterY(src.first, src.second, src.third,
    01039                       dest.first, dest.second, b1, b2);
    01040 }
    01041
    01042 /********************************************************/
    01043 /*                                                      */
    01044 /*                     recursiveSmoothY                 */
    01045 /*                                                      */
    01046 /********************************************************/
    01047
    01048 /** \brief Performs 1 dimensional recursive smoothing in y direction.
    01049
    01050     It calls \ref recursiveSmoothLine() for every column of the
    01051     image. See \ref recursiveSmoothLine() for more information about
    01052     required interfaces and vigra_preconditions.
    01053
    01054     <b> Declarations:</b>
    01055
    01056     pass arguments explicitly:
    01057     \code
    01058     namespace vigra {
    01059         template <class SrcImageIterator, class SrcAccessor,
    01060               class DestImageIterator, class DestAccessor>
    01061         void recursiveSmoothY(SrcImageIterator supperleft,
    01062                   SrcImageIterator slowerright, SrcAccessor as,
    01063                   DestImageIterator dupperleft, DestAccessor ad,
    01064                   double scale)
    01065     }
    01066     \endcode
    01067
    01068
    01069     use argument objects in conjunction with \ref ArgumentObjectFactories:
    01070     \code
    01071     namespace vigra {
    01072         template <class SrcImageIterator, class SrcAccessor,
    01073               class DestImageIterator, class DestAccessor>
    01074         void recursiveSmoothY(
    01075             triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    01076             pair<DestImageIterator, DestAccessor> dest,
    01077             double scale)
    01078     }
    01079     \endcode
    01080
    01081     <b> Usage:</b>
    01082
    01083     <b>\#include</b> "<a href="recursiveconvolution_8hxx-source.html">vigra/recursiveconvolution.hxx</a>"<br>
    01084     Namespace: vigra
    01085
    01086     \code
    01087     vigra::FImage src(w,h), dest(w,h);
    01088     ...
    01089
    01090     vigra::recursiveSmoothY(srcImageRange(src), destImage(dest), 3.0);
    01091
    01092     \endcode
    01093
    01094 */
    01095 template <class SrcImageIterator, class SrcAccessor,
    01096           class DestImageIterator, class DestAccessor>
    01097 void recursiveSmoothY(SrcImageIterator supperleft,
    01098                       SrcImageIterator slowerright, SrcAccessor as,
    01099                       DestImageIterator dupperleft, DestAccessor ad,
    01100               double scale)
    01101 {
    01102     int w = slowerright.x - supperleft.x;
    01103     int h = slowerright.y - supperleft.y;
    01104
    01105     int x;
    01106
    01107     for(x=0; x<w; ++x, ++supperleft.x, ++dupperleft.x)
    01108     {
    01109         typename SrcImageIterator::column_iterator cs = supperleft.columnIterator();
    01110         typename DestImageIterator::column_iterator cd = dupperleft.columnIterator();
    01111
    01112         recursiveSmoothLine(cs, cs+h, as,
    01113                             cd, ad,
    01114                             scale);
    01115     }
    01116 }
    01117
    01118 template <class SrcImageIterator, class SrcAccessor,
    01119           class DestImageIterator, class DestAccessor>
    01120 inline void recursiveSmoothY(
    01121             triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    01122             pair<DestImageIterator, DestAccessor> dest,
    01123             double scale)
    01124 {
    01125     recursiveSmoothY(src.first, src.second, src.third,
    01126                      dest. first, dest.second, scale);
    01127 }
    01128
    01129 /********************************************************/
    01130 /*                                                      */
    01131 /*              recursiveFirstDerivativeX               */
    01132 /*                                                      */
    01133 /********************************************************/
    01134
    01135 /** \brief Recursively calculates the 1 dimensional first derivative in x
    01136     direction.
    01137
    01138     It calls \ref recursiveFirstDerivativeLine() for every
    01139     row of the image. See \ref recursiveFirstDerivativeLine() for more
    01140     information about required interfaces and vigra_preconditions.
    01141
    01142     <b> Declarations:</b>
    01143
    01144     pass arguments explicitly:
    01145     \code
    01146     namespace vigra {
    01147         template <class SrcImageIterator, class SrcAccessor,
    01148               class DestImageIterator, class DestAccessor>
    01149         void recursiveFirstDerivativeX(SrcImageIterator supperleft,
    01150                   SrcImageIterator slowerright, SrcAccessor as,
    01151                   DestImageIterator dupperleft, DestAccessor ad,
    01152                   double scale)
    01153     }
    01154     \endcode
    01155
    01156
    01157     use argument objects in conjunction with \ref ArgumentObjectFactories:
    01158     \code
    01159     namespace vigra {
    01160         template <class SrcImageIterator, class SrcAccessor,
    01161               class DestImageIterator, class DestAccessor>
    01162         void recursiveFirstDerivativeX(
    01163             triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    01164             pair<DestImageIterator, DestAccessor> dest,
    01165             double scale)
    01166     }
    01167     \endcode
    01168
    01169     <b> Usage:</b>
    01170
    01171     <b>\#include</b> "<a href="recursiveconvolution_8hxx-source.html">vigra/recursiveconvolution.hxx</a>"<br>
    01172     Namespace: vigra
    01173
    01174     \code
    01175     vigra::FImage src(w,h), dest(w,h);
    01176     ...
    01177
    01178     vigra::recursiveFirstDerivativeX(srcImageRange(src), destImage(dest), 3.0);
    01179
    01180     \endcode
    01181
    01182 */
    01183 template <class SrcImageIterator, class SrcAccessor,
    01184           class DestImageIterator, class DestAccessor>
    01185 void recursiveFirstDerivativeX(SrcImageIterator supperleft,
    01186                       SrcImageIterator slowerright, SrcAccessor as,
    01187                       DestImageIterator dupperleft, DestAccessor ad,
    01188               double scale)
    01189 {
    01190     int w = slowerright.x - supperleft.x;
    01191     int h = slowerright.y - supperleft.y;
    01192
    01193     int y;
    01194
    01195     for(y=0; y<h; ++y, ++supperleft.y, ++dupperleft.y)
    01196     {
    01197         typename SrcImageIterator::row_iterator rs = supperleft.rowIterator();
    01198         typename DestImageIterator::row_iterator rd = dupperleft.rowIterator();
    01199
    01200         recursiveFirstDerivativeLine(rs, rs+w, as,
    01201                                      rd, ad,
    01202                                      scale);
    01203     }
    01204 }
    01205
    01206 template <class SrcImageIterator, class SrcAccessor,
    01207           class DestImageIterator, class DestAccessor>
    01208 inline void recursiveFirstDerivativeX(
    01209             triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    01210             pair<DestImageIterator, DestAccessor> dest,
    01211         double scale)
    01212 {
    01213     recursiveFirstDerivativeX(src.first, src.second, src.third,
    01214                           dest. first, dest.second, scale);
    01215 }
    01216
    01217 /********************************************************/
    01218 /*                                                      */
    01219 /*              recursiveFirstDerivativeY               */
    01220 /*                                                      */
    01221 /********************************************************/
    01222
    01223 /** \brief Recursively calculates the 1 dimensional first derivative in y
    01224     direction.
    01225
    01226     It calls \ref recursiveFirstDerivativeLine() for every
    01227     column of the image. See \ref recursiveFirstDerivativeLine() for more
    01228     information about required interfaces and vigra_preconditions.
    01229
    01230     <b> Declarations:</b>
    01231
    01232     pass arguments explicitly:
    01233     \code
    01234     namespace vigra {
    01235         template <class SrcImageIterator, class SrcAccessor,
    01236               class DestImageIterator, class DestAccessor>
    01237         void recursiveFirstDerivativeY(SrcImageIterator supperleft,
    01238                   SrcImageIterator slowerright, SrcAccessor as,
    01239                   DestImageIterator dupperleft, DestAccessor ad,
    01240                   double scale)
    01241     }
    01242     \endcode
    01243
    01244
    01245     use argument objects in conjunction with \ref ArgumentObjectFactories:
    01246     \code
    01247     namespace vigra {
    01248         template <class SrcImageIterator, class SrcAccessor,
    01249               class DestImageIterator, class DestAccessor>
    01250         void recursiveFirstDerivativeY(
    01251             triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    01252             pair<DestImageIterator, DestAccessor> dest,
    01253             double scale)
    01254     }
    01255     \endcode
    01256
    01257     <b> Usage:</b>
    01258
    01259     <b>\#include</b> "<a href="recursiveconvolution_8hxx-source.html">vigra/recursiveconvolution.hxx</a>"<br>
    01260     Namespace: vigra
    01261
    01262     \code
    01263     vigra::FImage src(w,h), dest(w,h);
    01264     ...
    01265
    01266     vigra::recursiveFirstDerivativeY(srcImageRange(src), destImage(dest), 3.0);
    01267
    01268     \endcode
    01269
    01270 */
    01271 template <class SrcImageIterator, class SrcAccessor,
    01272           class DestImageIterator, class DestAccessor>
    01273 void recursiveFirstDerivativeY(SrcImageIterator supperleft,
    01274                       SrcImageIterator slowerright, SrcAccessor as,
    01275                       DestImageIterator dupperleft, DestAccessor ad,
    01276               double scale)
    01277 {
    01278     int w = slowerright.x - supperleft.x;
    01279     int h = slowerright.y - supperleft.y;
    01280
    01281     int x;
    01282
    01283     for(x=0; x<w; ++x, ++supperleft.x, ++dupperleft.x)
    01284     {
    01285         typename SrcImageIterator::column_iterator cs = supperleft.columnIterator();
    01286         typename DestImageIterator::column_iterator cd = dupperleft.columnIterator();
    01287
    01288         recursiveFirstDerivativeLine(cs, cs+h, as,
    01289                                      cd, ad,
    01290                                      scale);
    01291     }
    01292 }
    01293
    01294 template <class SrcImageIterator, class SrcAccessor,
    01295           class DestImageIterator, class DestAccessor>
    01296 inline void recursiveFirstDerivativeY(
    01297             triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    01298             pair<DestImageIterator, DestAccessor> dest,
    01299         double scale)
    01300 {
    01301     recursiveFirstDerivativeY(src.first, src.second, src.third,
    01302                           dest. first, dest.second, scale);
    01303 }
    01304
    01305 /********************************************************/
    01306 /*                                                      */
    01307 /*             recursiveSecondDerivativeX               */
    01308 /*                                                      */
    01309 /********************************************************/
    01310
    01311 /** \brief Recursively calculates the 1 dimensional second derivative in x
    01312     direction.
    01313
    01314     It calls \ref recursiveSecondDerivativeLine() for every
    01315     row of the image. See \ref recursiveSecondDerivativeLine() for more
    01316     information about required interfaces and vigra_preconditions.
    01317
    01318     <b> Declarations:</b>
    01319
    01320     pass arguments explicitly:
    01321     \code
    01322     namespace vigra {
    01323         template <class SrcImageIterator, class SrcAccessor,
    01324               class DestImageIterator, class DestAccessor>
    01325         void recursiveSecondDerivativeX(SrcImageIterator supperleft,
    01326                   SrcImageIterator slowerright, SrcAccessor as,
    01327                   DestImageIterator dupperleft, DestAccessor ad,
    01328                   double scale)
    01329     }
    01330     \endcode
    01331
    01332
    01333     use argument objects in conjunction with \ref ArgumentObjectFactories:
    01334     \code
    01335     namespace vigra {
    01336         template <class SrcImageIterator, class SrcAccessor,
    01337               class DestImageIterator, class DestAccessor>
    01338         void recursiveSecondDerivativeX(
    01339             triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    01340             pair<DestImageIterator, DestAccessor> dest,
    01341             double scale)
    01342     }
    01343     \endcode
    01344
    01345     <b> Usage:</b>
    01346
    01347     <b>\#include</b> "<a href="recursiveconvolution_8hxx-source.html">vigra/recursiveconvolution.hxx</a>"<br>
    01348     Namespace: vigra
    01349
    01350     \code
    01351     vigra::FImage src(w,h), dest(w,h);
    01352     ...
    01353
    01354     vigra::recursiveSecondDerivativeX(srcImageRange(src), destImage(dest), 3.0);
    01355
    01356     \endcode
    01357
    01358 */
    01359 template <class SrcImageIterator, class SrcAccessor,
    01360           class DestImageIterator, class DestAccessor>
    01361 void recursiveSecondDerivativeX(SrcImageIterator supperleft,
    01362                       SrcImageIterator slowerright, SrcAccessor as,
    01363                       DestImageIterator dupperleft, DestAccessor ad,
    01364               double scale)
    01365 {
    01366     int w = slowerright.x - supperleft.x;
    01367     int h = slowerright.y - supperleft.y;
    01368
    01369     int y;
    01370
    01371     for(y=0; y<h; ++y, ++supperleft.y, ++dupperleft.y)
    01372     {
    01373         typename SrcImageIterator::row_iterator rs = supperleft.rowIterator();
    01374         typename DestImageIterator::row_iterator rd = dupperleft.rowIterator();
    01375
    01376         recursiveSecondDerivativeLine(rs, rs+w, as,
    01377                                       rd, ad,
    01378                                       scale);
    01379     }
    01380 }
    01381
    01382 template <class SrcImageIterator, class SrcAccessor,
    01383           class DestImageIterator, class DestAccessor>
    01384 inline void recursiveSecondDerivativeX(
    01385             triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    01386             pair<DestImageIterator, DestAccessor> dest,
    01387         double scale)
    01388 {
    01389     recursiveSecondDerivativeX(src.first, src.second, src.third,
    01390                           dest. first, dest.second, scale);
    01391 }
    01392
    01393 /********************************************************/
    01394 /*                                                      */
    01395 /*             recursiveSecondDerivativeY               */
    01396 /*                                                      */
    01397 /********************************************************/
    01398
    01399 /** \brief Recursively calculates the 1 dimensional second derivative in y
    01400     direction.
    01401
    01402     It calls \ref recursiveSecondDerivativeLine() for every
    01403     column of the image. See \ref recursiveSecondDerivativeLine() for more
    01404     information about required interfaces and vigra_preconditions.
    01405
    01406     <b> Declarations:</b>
    01407
    01408     pass arguments explicitly:
    01409     \code
    01410     namespace vigra {
    01411         template <class SrcImageIterator, class SrcAccessor,
    01412               class DestImageIterator, class DestAccessor>
    01413         void recursiveSecondDerivativeY(SrcImageIterator supperleft,
    01414                   SrcImageIterator slowerright, SrcAccessor as,
    01415                   DestImageIterator dupperleft, DestAccessor ad,
    01416                   double scale)
    01417     }
    01418     \endcode
    01419
    01420
    01421     use argument objects in conjunction with \ref ArgumentObjectFactories:
    01422     \code
    01423     namespace vigra {
    01424         template <class SrcImageIterator, class SrcAccessor,
    01425               class DestImageIterator, class DestAccessor>
    01426         void recursiveSecondDerivativeY(
    01427             triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    01428             pair<DestImageIterator, DestAccessor> dest,
    01429             double scale)
    01430     }
    01431     \endcode
    01432
    01433     <b> Usage:</b>
    01434
    01435     <b>\#include</b> "<a href="recursiveconvolution_8hxx-source.html">vigra/recursiveconvolution.hxx</a>"<br>
    01436     Namespace: vigra
    01437
    01438     \code
    01439     vigra::FImage src(w,h), dest(w,h);
    01440     ...
    01441
    01442     vigra::recursiveSecondDerivativeY(srcImageRange(src), destImage(dest), 3.0);
    01443
    01444     \endcode
    01445
    01446 */
    01447 template <class SrcImageIterator, class SrcAccessor,
    01448           class DestImageIterator, class DestAccessor>
    01449 void recursiveSecondDerivativeY(SrcImageIterator supperleft,
    01450                       SrcImageIterator slowerright, SrcAccessor as,
    01451                       DestImageIterator dupperleft, DestAccessor ad,
    01452               double scale)
    01453 {
    01454     int w = slowerright.x - supperleft.x;
    01455     int h = slowerright.y - supperleft.y;
    01456
    01457     int x;
    01458
    01459     for(x=0; x<w; ++x, ++supperleft.x, ++dupperleft.x)
    01460     {
    01461         typename SrcImageIterator::column_iterator cs = supperleft.columnIterator();
    01462         typename DestImageIterator::column_iterator cd = dupperleft.columnIterator();
    01463
    01464         recursiveSecondDerivativeLine(cs, cs+h, as,
    01465                                       cd, ad,
    01466                                       scale);
    01467     }
    01468 }
    01469
    01470 template <class SrcImageIterator, class SrcAccessor,
    01471           class DestImageIterator, class DestAccessor>
    01472 inline void recursiveSecondDerivativeY(
    01473             triple<SrcImageIterator, SrcImageIterator, SrcAccessor> src,
    01474             pair<DestImageIterator, DestAccessor> dest,
    01475         double scale)
    01476 {
    01477     recursiveSecondDerivativeY(src.first, src.second, src.third,
    01478                           dest. first, dest.second, scale);
    01479 }
    01480
    01481 //@}
    01482
    01483 } // namespace vigra
    01484
    01485 #endif // VIGRA_RECURSIVECONVOLUTION_HXX

© Ullrich Köthe (koethe@informatik.uni-hamburg.de) Cognitive Systems Group, University of Hamburg, Germany | html generated using doxygen and Python VIGRA 1.3.2 (27 Jan 2005)