VIGRA - VIGRA: vigra/recursiveconvolution.hxx Source File

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