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

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