latest version v1.9 - last update 10 Apr 2010 |
00001 /* 00002 * Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 00003 * Lehrstuhl fuer Technische Informatik, RWTH-Aachen, Germany 00004 * 00005 * This file is part of the LTI-Computer Vision Library (LTI-Lib) 00006 * 00007 * The LTI-Lib is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public License (LGPL) 00009 * as published by the Free Software Foundation; either version 2.1 of 00010 * the License, or (at your option) any later version. 00011 * 00012 * The LTI-Lib is distributed in the hope that it will be 00013 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 00014 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with the LTI-Lib; see the file LICENSE. If 00019 * not, write to the Free Software Foundation, Inc., 59 Temple Place - 00020 * Suite 330, Boston, MA 02111-1307, USA. 00021 */ 00022 00023 00024 /*---------------------------------------------------------------- 00025 * project ....: LTI Digital Image/Signal Processing Library 00026 * file .......: ltiGenericInterpolator.h 00027 * authors ....: Pablo Alvarado 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 12.6.2001 00030 * revisions ..: $Id: ltiGenericInterpolator.h,v 1.8 2006/02/08 11:10:53 ltilib Exp $ 00031 */ 00032 00033 #ifndef _LTI_GENERIC_INTERPOLATOR_H_ 00034 #define _LTI_GENERIC_INTERPOLATOR_H_ 00035 00036 #include "ltiImage.h" 00037 #include "ltiVector.h" 00038 #include "ltiScalarValuedInterpolation.h" 00039 00040 namespace lti { 00041 00042 /** 00043 * This functor use a generic interpolation concept based on look-up-tables 00044 * for the interpolation kernels. 00045 * 00046 * The LUT allow to considerably accelerate the computation times, but a 00047 * little bit precision is lost due to the unavoidable quantization present 00048 * in the LUT. 00049 * 00050 * The type T of the template is the type of the elements of the vector 00051 * or matrix used. 00052 */ 00053 template <class T> 00054 class genericInterpolator : public scalarValuedInterpolation<T> { 00055 public: 00056 /** 00057 * The parameters for the class genericInterpolator 00058 */ 00059 class parameters : public scalarValuedInterpolation<T>::parameters { 00060 public: 00061 /** 00062 * Types for interpolation kernels. 00063 */ 00064 enum eInterpolationKernelType { 00065 BilinearKernel, /**< Bilinear interpolation kernel. 00066 * The neighborhood size is always 2x2. 00067 * This implementation 00068 * is slower than the optimized version in the functor 00069 * lti::bilinearInterpolation, but is provided for 00070 * completeness. 00071 */ 00072 BicubicKernel, /**< Bicubic interpolation. 00073 * The neighborhood size is always 4x4. 00074 * The kernel provided here is after Sonka et.al. 00075 * pp. 67 00076 * 00077 * \f[ h(x)=\begin{cases} 00078 * 1-2|x|^2+|x|^3 & \text{for $0\leq|x|\leq 1$} \\ 00079 * 4-8|x|+5|x|^2-|x|^3 & \text{for $1\leq|x|\leq 2$}\\ 00080 * 0 & \text{otherwise} 00081 * \end{cases} \f] 00082 */ 00083 GenericKernel /**< Generic interpolation. 00084 * The generic interpolation uses the kernelLUT given 00085 * in the parameters. 00086 */ 00087 }; 00088 00089 /** 00090 * default constructor 00091 */ 00092 parameters() : scalarValuedInterpolation<T>::parameters() { 00093 kernelType = eInterpolationKernelType(BicubicKernel); 00094 numSamplesPerInterval = int(128); 00095 this->boundaryType = Constant; 00096 kernelLUT.clear(); 00097 }; 00098 00099 /** 00100 * Constructor to set explicitelly the desired boundaryType 00101 */ 00102 parameters(const eBoundaryType btype) 00103 : scalarValuedInterpolation<T>::parameters(btype) { 00104 kernelType = eInterpolationKernelType(BicubicKernel); 00105 numSamplesPerInterval = int(256); 00106 this->boundaryType = Constant; 00107 kernelLUT.clear(); 00108 }; 00109 00110 /** 00111 * copy constructor 00112 * @param other the parameters object to be copied 00113 */ 00114 parameters(const parameters& other) 00115 : scalarValuedInterpolation<T>::parameters() { 00116 copy(other); 00117 } 00118 00119 /** 00120 * destructor 00121 */ 00122 ~parameters() { 00123 kernelLUT.clear(); 00124 }; 00125 00126 /** 00127 * returns name of this type 00128 */ 00129 const char* getTypeName() const { 00130 return "genericInterpolator::parameters"; 00131 }; 00132 00133 /** 00134 * copy the contents of a parameters object 00135 * @param other the parameters object to be copied 00136 * @return a reference to this parameters object 00137 */ 00138 parameters& copy(const parameters& other) { 00139 # ifndef _LTI_MSC_6 00140 // MS Visual C++ 6 is not able to compile this... 00141 scalarValuedInterpolation<T>::parameters::copy(other); 00142 # else 00143 // ...so we have to use this workaround. 00144 // Conditional on that, copy may not be virtual. 00145 scalarValuedInterpolation<T>::parameters& 00146 (scalarValuedInterpolation<T>::parameters::* p_copy) 00147 (const scalarValuedInterpolation<T>::parameters&) = 00148 scalarValuedInterpolation<T>::parameters::copy; 00149 (this->*p_copy)(other); 00150 # endif 00151 00152 kernelType = other.kernelType; 00153 numSamplesPerInterval = other.numSamplesPerInterval; 00154 kernelLUT.copy(other.kernelLUT); 00155 return *this; 00156 }; 00157 00158 /** 00159 * copy the contents of a parameters object 00160 * @param other the parameters object to be copied 00161 * @return a reference to this parameters object 00162 */ 00163 parameters& operator=(const parameters& other) { 00164 return copy(other); 00165 }; 00166 00167 /** 00168 * returns a pointer to a clone of the parameters 00169 */ 00170 virtual functor::parameters* clone() const { 00171 return new parameters(*this); 00172 }; 00173 00174 # ifndef _LTI_MSC_6 00175 /** 00176 * write the parameters in the given ioHandler 00177 * @param handler the ioHandler to be used 00178 * @param complete if true (the default) the enclosing begin/end will 00179 * be also written, otherwise only the data block will be written. 00180 * @return true if write was successful 00181 */ 00182 virtual bool write(ioHandler& handler,const bool complete=true) const 00183 # else 00184 /** 00185 * this function is required by MSVC only, as a workaround for a 00186 * very awful bug, which exists since MSVC V.4.0, and still by 00187 * V.6.0 with all bugfixes (so called "service packs") remains 00188 * there... This method is also public due to another bug, so please 00189 * NEVER EVER call this method directly: use write() instead 00190 */ 00191 bool writeMS(ioHandler& handler,const bool complete=true) const 00192 # endif 00193 { 00194 bool b = true; 00195 if (complete) { 00196 b = handler.writeBegin(); 00197 } 00198 00199 if (b) { 00200 switch (kernelType) { 00201 case BilinearKernel: 00202 lti::write(handler,"kernelType","BilinearKernel"); 00203 break; 00204 case BicubicKernel: 00205 lti::write(handler,"kernelType","BicubicKernel"); 00206 break; 00207 case GenericKernel: 00208 lti::write(handler,"kernelType","GenericKernel"); 00209 break; 00210 default: 00211 lti::write(handler,"kernelType","Unknown"); 00212 b=false; 00213 } 00214 00215 lti::write(handler,"numSamplesPerInterval",numSamplesPerInterval); 00216 lti::write(handler,"kernelLUT",kernelLUT); 00217 } 00218 00219 # ifndef _LTI_MSC_6 00220 // This is the standard C++ code, which MS Visual C++ 6 is not able to 00221 // compile... 00222 b = b && scalarValuedInterpolation<T>::parameters::write(handler, 00223 false); 00224 # else 00225 bool (scalarValuedInterpolation<T>::parameters::* 00226 p_writeMS)(ioHandler&, 00227 const bool) const = 00228 scalarValuedInterpolation<T>::parameters::writeMS; 00229 b = b && (this->*p_writeMS)(handler,false); 00230 # endif 00231 00232 if (complete) { 00233 b = b && handler.writeEnd(); 00234 } 00235 00236 return b; 00237 } 00238 00239 # ifdef _LTI_MSC_6 00240 /** 00241 * write the parameters in the given ioHandler 00242 * @param handler the ioHandler to be used 00243 * @param complete if true (the default) the enclosing begin/end will 00244 * be also written, otherwise only the data block will be written. 00245 * @return true if write was successful 00246 */ 00247 bool write(ioHandler& handler, 00248 const bool complete=true) const { 00249 // ...we need this workaround to cope with another really 00250 // awful MSVC bug. 00251 return writeMS(handler,complete); 00252 } 00253 # endif 00254 00255 00256 # ifndef _LTI_MSC_6 00257 /** 00258 * read the parameters from the given ioHandler 00259 * @param handler the ioHandler to be used 00260 * @param complete if true (the default) the enclosing begin/end will 00261 * be also written, otherwise only the data block will be written. 00262 * @return true if write was successful 00263 */ 00264 virtual bool read(ioHandler& handler,const bool complete=true) 00265 # else 00266 /** 00267 * this function is required by MSVC only, as a workaround for a 00268 * very awful bug, which exists since MSVC V.4.0, and still by 00269 * V.6.0 with all bugfixes (so called "service packs") remains 00270 * there... This method is also public due to another bug, so please 00271 * NEVER EVER call this method directly: use read() instead 00272 */ 00273 bool readMS(ioHandler& handler,const bool complete=true) 00274 # endif 00275 { 00276 bool b = true; 00277 if (complete) { 00278 b = handler.readBegin(); 00279 } 00280 00281 if (b) { 00282 std::string str; 00283 00284 lti::read(handler,"kernelType",str); 00285 if (str.find("ilinear") != std::string::npos) { 00286 kernelType = BilinearKernel; 00287 } else if (str.find("icubic") != std::string::npos) { 00288 kernelType = BicubicKernel; 00289 } else if (str.find("eneric") != std::string::npos) { 00290 kernelType = GenericKernel; 00291 } else { 00292 handler.setStatusString("Unknown interpolator kernel type"); 00293 b=false; 00294 } 00295 00296 lti::read(handler,"numSamplesPerInterval",numSamplesPerInterval); 00297 lti::read(handler,"kernelLUT",kernelLUT); 00298 } 00299 00300 # ifndef _LTI_MSC_6 00301 // This is the standard C++ code, which MS Visual C++ 6 is not 00302 // able to compile... 00303 b = b && scalarValuedInterpolation<T>::parameters::read(handler,false); 00304 # else 00305 bool (scalarValuedInterpolation<T>::parameters::* p_readMS)(ioHandler&, 00306 const bool) = 00307 scalarValuedInterpolation<T>::parameters::readMS; 00308 b = b && (this->*p_readMS)(handler,false); 00309 # endif 00310 00311 if (complete) { 00312 b = b && handler.readEnd(); 00313 } 00314 00315 return b; 00316 } 00317 00318 # ifdef _LTI_MSC_6 00319 /** 00320 * read the parameters from the given ioHandler 00321 * @param handler the ioHandler to be used 00322 * @param complete if true (the default) the enclosing begin/end will 00323 * be also written, otherwise only the data block will be written. 00324 * @return true if write was successful 00325 */ 00326 bool read(ioHandler& handler,const bool complete=true) { 00327 // ...we need this workaround to cope with another really awful MSVC 00328 // bug. 00329 return readMS(handler,complete); 00330 } 00331 # endif 00332 00333 // ------------------------------------------------ 00334 // the parameters 00335 // ------------------------------------------------ 00336 00337 /** 00338 * Interpolation type to be used. 00339 * 00340 * Default: Bicubic 00341 */ 00342 eInterpolationKernelType kernelType; 00343 00344 /** 00345 * Number of samples in the interpolation table for a unit interval. 00346 * 00347 * The total number of elements in the LUT will be this value multiplied 00348 * by the number of unit intervals of the interpolation kernel. 00349 * 00350 * Default value: 256 00351 */ 00352 int numSamplesPerInterval; 00353 00354 /** 00355 * Generic interpolation kernel. 00356 * 00357 * If the kernelType is GenericKernel then this kernel LUT will be used. 00358 * To be a valid kernel, this vector must have a size \a n times 00359 * numSamplesPerInterval, with \a n even. If the validity of the 00360 * kernel LUT cannot be confirmed, a Bilinear Kernel will be used 00361 * instead, but setParameters will return false. 00362 * 00363 * Default value: empty kernel 00364 */ 00365 fvector kernelLUT; 00366 }; 00367 00368 /** 00369 * default constructor 00370 */ 00371 genericInterpolator(); 00372 00373 /** 00374 * Construct an interpolator with the given parameters 00375 */ 00376 genericInterpolator(const parameters& params); 00377 00378 /** 00379 * Construct an interpolator with the given boundary type 00380 */ 00381 genericInterpolator(const eBoundaryType boundaryType); 00382 00383 /** 00384 * copy constructor 00385 * @param other the object to be copied 00386 */ 00387 genericInterpolator(const genericInterpolator<T>& other); 00388 00389 /** 00390 * destructor 00391 */ 00392 virtual ~genericInterpolator(); 00393 00394 /** 00395 * returns the name of this type ("genericInterpolator") 00396 */ 00397 virtual const char* getTypeName() const; 00398 00399 /** 00400 * Returns the interpolated value of the vector at the real valued 00401 * position x. 00402 * @param src vector<T> with the source data. 00403 * @param x the real valued position to be interpolated. 00404 * @return the interpolated value of the vector. 00405 */ 00406 T apply(const vector<T>& src,const float& x) const; 00407 00408 /** 00409 * Returns the interpolated value of the vector specified with 00410 * use() at the real valued position x. 00411 * @param x the real valued position to be interpolated. 00412 * @return the interpolated value of the vector. */ 00413 T apply(const float& x) const; 00414 00415 /** 00416 * Returns the interpolated value of the matrix at the real valued 00417 * position (row,col). 00418 * 00419 * @param src matrix<T> with the source data. 00420 * @param row which row 00421 * @param col which column 00422 * @return the interpolated value of the matrix. 00423 */ 00424 T apply(const matrix<T>& src, 00425 const float& row, 00426 const float& col) const; 00427 00428 /** 00429 * Returns the interpolated value of the matrix at the real valued 00430 * position p. 00431 * 00432 * @param src matrix<T> with the source data. 00433 * @param p the real valued position to be interpolated. 00434 * @return the interpolated value of the matrix. 00435 */ 00436 T apply(const matrix<T>& src,const tpoint<float>& p) const; 00437 00438 /** 00439 * Returns the interpolated value of the matrix specified with 00440 * use() at the real valued position (row,col). 00441 * 00442 * @param row which row 00443 * @param col which column 00444 * @return the interpolated value of the matrix. */ 00445 T apply(const float& row, const float& col) const; 00446 00447 /** 00448 * Returns the interpolated value of the matrix specified with 00449 * use() at the real valued position p. 00450 * 00451 * @param p the real valued position to be interpolated. 00452 * @return the interpolated value of the matrix. 00453 */ 00454 T apply(const tpoint<float>& p) const; 00455 00456 /** 00457 * Returns the interpolated value of the matrix at the real valued 00458 * position (row,col). This method is not virtual and can be used 00459 * if this interpolation type is used as template parameter in time 00460 * critical situations 00461 * 00462 * @param src matrix<T> with the source data. 00463 * @param row which row 00464 * @param col which column 00465 * @return the interpolated value of the matrix. 00466 */ 00467 T interpolate(const matrix<T>& src, 00468 const float row, 00469 const float col) const; 00470 00471 /** 00472 * Returns the interpolated value of the matrix specified with 00473 * use() at the real valued position (row,col). This method is 00474 * not virtual and can be used if this interpolation type is used 00475 * as template parameter in time critical situations 00476 * 00477 * @param row which row 00478 * @param col which column 00479 * @return the interpolated value of the matrix. 00480 */ 00481 inline T interpolate(const float row, 00482 const float col) const { 00483 return interpolate(*this->theMatrix,row,col); 00484 }; 00485 00486 /** 00487 * Returns the interpolated value of the matrix at the real valued 00488 * position (row,col). 00489 * 00490 * This method does not check if the given coordinates and the rest of 00491 * used points in the src matrix lie within the valid range. This is 00492 * left to you. Please consider that for the generic interpolation 00493 * not only the point(trunc(col),trunc(row)) is used, but a nxn 00494 * neighborhood centered such that (col,row) is nearest to the center. 00495 * 00496 * This method is not virtual and can be used in time critical situations, 00497 * where you prefer to take the boundary control by yourself. 00498 * 00499 * @param src matrix<T> with the source data. 00500 * @param row which row 00501 * @param col which column 00502 * @return the interpolated value of the matrix. 00503 */ 00504 inline T interpolateUnchk(const matrix<T>& src, 00505 const float row, 00506 const float col); 00507 00508 /** 00509 * Returns the interpolated value of the matrix specified with 00510 * use() at the real valued position (row,col). This method is 00511 * not virtual and can be used if this interpolation type is used 00512 * as template parameter in time critical situations 00513 * 00514 * @param row which row 00515 * @param col which column 00516 * @return the interpolated value of the matrix. 00517 */ 00518 inline T interpolateUnchk(const float row, 00519 const float col); 00520 00521 /** 00522 * copy data of "other" functor. 00523 * @param other the functor to be copied 00524 * @return a reference to this functor object 00525 */ 00526 genericInterpolator& copy(const genericInterpolator& other); 00527 00528 /** 00529 * returns a pointer to a clone of this functor. 00530 */ 00531 virtual functor* clone() const; 00532 00533 /** 00534 * returns used parameters 00535 */ 00536 const parameters& getParameters() const; 00537 00538 /** 00539 * returns used parameters 00540 */ 00541 virtual bool updateParameters(); 00542 00543 /** 00544 * Return a read only reference to the last computed LUT. 00545 * 00546 * This method is mainly used for debugging purposes. 00547 */ 00548 inline const vector<float>& getLUT() const; 00549 00550 /** 00551 * Compute the generic interpolated value for the given coefficients 00552 * and values. 00553 * 00554 * This method is provided for convenience only. Use at your own 00555 * risk. 00556 * 00557 * @param fx fractional term between 0.0f (inclusive) and 1.0f (exclusive) 00558 * @param data pointer to an array with the support samples. It has at 00559 * least \a n elements, with \a n the number of unit intervals 00560 * in the interpolation kernel. 00561 * Their position will be assumed to be from 00562 * -(n/2-1) to n/2, so that the 00563 * interval 0..1 lies exaclty in the middle. 00564 * 00565 * @return interpolated value between the three values 00566 */ 00567 inline T compute(const float fx,const T* data) const; 00568 00569 /** 00570 * Compute the generic interpolated value for the given coefficients 00571 * and values. 00572 * 00573 * This method is provided for convenience only. Use at your own 00574 * risk. 00575 * 00576 * @param fy fractional term between 0.0 and 1.0 00577 * @param fx fractional term between 0.0 and 1.0 00578 * @param data pointer to an array of arrays with the support samples. 00579 * 00580 * @return interpolated value between the four corners 00581 */ 00582 inline T compute(const float fy, 00583 const float fx, 00584 const T** data) const; 00585 00586 protected: 00587 /** 00588 * The interpolation kernel is traversed in revers order than 00589 * the data. To save the first computation time, we store the 00590 * sample index for the first element of the last interval 00591 */ 00592 int lastIntervalFirstSample; 00593 00594 /** 00595 * Number of intervals really used. 00596 * 00597 * The value given in the parameters might be ignored depending on the 00598 * chosen kernel type. 00599 */ 00600 int numberOfIntervals; 00601 00602 /** 00603 * This is the number that need to be substracted to a position point 00604 * to get the first valid support sample. 00605 * It is usually numberOfIntervals/2 - 1; 00606 */ 00607 int firstSampleOffset; 00608 00609 /** 00610 * Interval size taken from the parameters numSamplesPerInterval; 00611 */ 00612 int intervalSize; 00613 00614 /** 00615 * @name Buffers 00616 */ 00617 /** 00618 * For the two dimensional interpolation, this vector will administrate 00619 * the memory array required. 00620 */ 00621 vector<T> column; 00622 00623 /** 00624 * This pointer will always point to the first element of column 00625 */ 00626 T* firstElemColumn; 00627 00628 /** 00629 * This is a small window that can be used to save temporarily the 00630 * sample supporting points 00631 */ 00632 mutable matrix<T> buffer; 00633 00634 /** 00635 * This pointer to arrays is initialized to have the proper size, but 00636 * you have to set the second pointers by yourself 00637 */ 00638 mutable const T** rows; 00639 00640 /** 00641 * This is initialized to point a the buffer's rows. 00642 */ 00643 const T** bufferRows; 00644 00645 //@} 00646 00647 /** 00648 * @name Kernel initialization routines 00649 */ 00650 //@{ 00651 /** 00652 * Interpolation kernel. 00653 * 00654 * This is initialized by the initLUT 00655 */ 00656 vector<float> interpolationKernel; 00657 00658 /** 00659 * Initialize the interpolation kernel LUT based on the parameters 00660 * settings. 00661 * 00662 * The LUT has only positive entries, but represents the interval from 00663 * -halfSize+1 to halfSize. No use of the symmetrical properties of the 00664 * kernel are exploited to improve efficiency, since less comparisons are 00665 * required. 00666 */ 00667 bool initLUT(); 00668 00669 /** 00670 * Initialization of the bilinear kernel. 00671 * Two unit intervals wlll be initialized. 00672 */ 00673 bool initBilinearLUT(); 00674 00675 /** 00676 * Initialization of the bicubic kernel. 00677 * Four unit intervals wlll be initialized. 00678 * The kernel provided here is after Sonka et.al. page 67: 00679 * \code 00680 * / 00681 * | 1-2|x|^2 + |x|^3 for 0<=x<=1 00682 * h(x) = < 4-8|x|^2 + 5|x|^2 - |x|^3 for 1<x<=2 00683 * | 0 otherwise 00684 * \ 00685 * \endcode 00686 */ 00687 bool initBicubicLUT(); 00688 00689 /** 00690 * Generic kernel initialization. 00691 * 00692 * This method checks that the kernelLUT in the parameters is a valid 00693 * kernel and sets all required attributes. 00694 */ 00695 bool initGenericLUT(); 00696 00697 //@} 00698 }; 00699 } 00700 00701 #include "ltiGenericInterpolator_inline.h" 00702 00703 #endif