[ 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 (3 Dec 2010)