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

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