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

details vigra/recursiveconvolution.hxx VIGRA

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

© Ullrich Köthe (koethe@informatik.uni-hamburg.de)
Cognitive Systems Group, University of Hamburg, Germany

html generated using doxygen and Python
VIGRA 1.3.2 (27 Jan 2005)