[ 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.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)