![]() |
latest version v1.9 - last update 10 Apr 2010 |
![]() |
00001 /* 00002 * Copyright (C) 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-Lib: Image Processing and Computer Vision Library 00026 * file .......: ltiArctanLUT.h 00027 * authors ....: Pablo Alvarado 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 01.06.2003 00030 * revisions ..: $Id: ltiArctanLUT.h,v 1.4 2006/02/08 12:11:42 ltilib Exp $ 00031 */ 00032 00033 #ifndef _LTI_ARCTAN_LUT_H_ 00034 #define _LTI_ARCTAN_LUT_H_ 00035 00036 #include "ltiObject.h" 00037 #include "ltiMath.h" 00038 #include "ltiAssert.h" 00039 00040 00041 namespace lti { 00042 /** 00043 * Following class provides a mono-state object that contains a 1MB Look-up 00044 * Table to accelerate the computation of the arc-tangens. 00045 * 00046 * The provided functionality is similar to std::atan2(y,x) which computes 00047 * arctan(y/x) returning also the right angle quadrant. 00048 * 00049 * This method is used in time critical operations. It is not appropriate 00050 * if you need exact computations of the arctan. For that you can use the 00051 * standard method std::atan2, which is of course much more time expensive. 00052 * 00053 * As a mono-state class, only one instance of the LUT will be created. 00054 * 00055 * To use it, just create an instance and use the operator() as if you were 00056 * using std::atan2: 00057 * 00058 * \code 00059 * lti::arctanLUT myatan2; 00060 * 00061 * float angle = myatan2(20,10); 00062 * \endcode 00063 * 00064 * The returned angle will be always possitive 0 <= angle < 2*Pi (in radians) 00065 */ 00066 class arctanLUT : public object { 00067 public: 00068 /** 00069 * Construct the class 00070 * Here, the LUT will be build just once (if not already done). 00071 * The first time you construct this class, it will take about 0.15 seconds 00072 * to build the LUT. 00073 */ 00074 arctanLUT(); 00075 00076 /** 00077 * Compute the arctan(dx/dy). 00078 * 00079 * It is a little bit slower than the other atan2() method, as it needs 00080 * to scale the input values into the range -255 and 255. If you need 00081 * a extremely efficient computation, try the other atan2() method. 00082 * 00083 * @param dy y component. 00084 * @param dx x component. 00085 * @return arctan(dy/dx) in radians (always possitive between 0 and 2*Pi) 00086 */ 00087 inline float operator() (const float dy,const float dx) const; 00088 00089 /** 00090 * Compute the arctan(dx/dy). 00091 * 00092 * It is a little bit slower than the other atan2() method, as it needs 00093 * to scale the input values into the range -255 and 255. If you need 00094 * a extremely efficient computation, try the other atan2() method. 00095 * 00096 * @param dy y component. 00097 * @param dx x component. 00098 * @return arctan(dy/dx) in radians (always possitive between 0 and 2*Pi) 00099 */ 00100 inline float operator() (const double& dy,const double& dx) const; 00101 00102 00103 /** 00104 * Compute the arctan(dx/dy). 00105 * 00106 * This is the fastest method, but the value range of the input variables 00107 * is restricted. 00108 * 00109 * @param dy y component must be between -255 and 255 00110 * @param dx x component must be between -255 and 255 00111 * @return arctan(dy/dx) in radians (always possitive between 0 and 2*Pi) 00112 */ 00113 inline float operator() (const int dy,const int dx) const; 00114 00115 protected: 00116 /** 00117 * construct a atan2 LUT. It will assume that the difference values 00118 * of the gradients will be always between -255 and 255. The 1MB Memory 00119 * required should not be a problem in modern PCs anymore!. 00120 */ 00121 static void constructArcTanLUT(); 00122 00123 /** 00124 * Type required to create the LUT as a const structure 00125 */ 00126 typedef const float* cfloatptr; 00127 00128 /** 00129 * the arctanLUT with floats. After calling constructArcTanLUT() the 00130 * valid index range for both dimensions will be between -255 and 255. 00131 * The arctanLUT[dy][dx] is equivalent to atan2(dy,dx) (but much faster). 00132 * The entries will always be between 0 and 2*Pi. 00133 */ 00134 static const cfloatptr* atanLUT; 00135 }; 00136 00137 // implementation of inline methods 00138 inline float arctanLUT::operator() (const double& dy,const double& dx) const { 00139 return this->operator()(static_cast<float>(dy),static_cast<float>(dx)); 00140 } 00141 00142 inline float arctanLUT::operator() (const float dy,const float dx) const { 00143 if (dy < 0.0f) { 00144 if (dx < 0.0f) { 00145 if (dx<dy) { 00146 return atanLUT[iround(-255.0f*dy/dx)][-255]; 00147 } else { 00148 return atanLUT[-255][iround(-255.0f*dx/dy)]; 00149 } 00150 } else { 00151 // dy < 0 and dx >= 0 00152 if (dx > -dy) { 00153 return atanLUT[iround(dy*255.0f/dx)][255]; 00154 } else { 00155 return atanLUT[-255][iround(-255.0f*dx/dy)]; 00156 } 00157 } 00158 } else { 00159 if (dx < 0.0f) { 00160 // dy >= 0 and dx < 0 00161 if (-dx > dy) { 00162 return atanLUT[iround(-dy*255.0f/dx)][-255]; 00163 } else { 00164 return atanLUT[255][iround(dx*255.0f/dy)]; 00165 } 00166 } else { 00167 // dy >= 0 and dx >= 0 00168 if (dx>dy) { 00169 return atanLUT[iround(dy*255.0f/dx)][255]; 00170 } else if (dx<dy) { 00171 return atanLUT[255][iround(dx*255.0f/dy)]; 00172 } else if (dx != 0.0f) { 00173 return atanLUT[255][255]; 00174 } 00175 } 00176 } 00177 return atanLUT[0][0]; 00178 } 00179 00180 inline float arctanLUT::operator() (const int dy,const int dx) const { 00181 // check in debug modus that range is ok 00182 assert((dy>-256) && (dy<256) && (dx>-256) && (dx<256)); 00183 00184 // just return the value 00185 return atanLUT[dy][dx]; 00186 }; 00187 00188 00189 } 00190 00191 #endif