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