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