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

vigra/recursiveconvolution.hxx VIGRA

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

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.8.0 (20 Sep 2011)