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