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