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