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

vigra/recursiveconvolution-old.hxx |

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

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany | html generated using doxygen and Python vigra 1.7.1 (9 Jul 2010)