last update 20 Sep 2009 |
00001 /* 00002 * Copyright (C) 2008 00003 * Pablo Alvarado 00004 * 00005 * This file is part of the Computer Vision and Robotics Library (CVR-Lib ) 00006 * 00007 * The CVR-Lib is free software; you can redistribute it and/or 00008 * modify it under the terms of the BSD License. 00009 * 00010 * All rights reserved. 00011 * 00012 * Redistribution and use in source and binary forms, with or without 00013 * modification, are permitted provided that the following conditions are met: 00014 * 00015 * 1. Redistributions of source code must retain the above copyright notice, 00016 * this list of conditions and the following disclaimer. 00017 * 00018 * 2. Redistributions in binary form must reproduce the above copyright notice, 00019 * this list of conditions and the following disclaimer in the documentation 00020 * and/or other materials provided with the distribution. 00021 * 00022 * 3. Neither the name of the authors nor the names of its contributors may be 00023 * used to endorse or promote products derived from this software without 00024 * specific prior written permission. 00025 * 00026 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00027 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00028 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00029 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00030 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00031 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00032 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00033 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00034 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00035 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00036 * POSSIBILITY OF SUCH DAMAGE. 00037 */ 00038 00039 /** 00040 * \file cvrAffineTransformation2D.h 00041 * Contains the class cvr::affineTransformation2D, 00042 * which is used to transform coordinate points in a planar 00043 * transformation with only rotation and translation. 00044 * 00045 * \author Pablo Alvarado 00046 * \date 15.01.2008 00047 * 00048 * revisions ..: $Id: cvrAffineTransformation2D.h,v $ 00049 */ 00050 00051 #ifndef _CVR_AFFINE_TRANSFORMATION2_D_H_ 00052 #define _CVR_AFFINE_TRANSFORMATION2_D_H_ 00053 00054 00055 #include "cvrLocation.h" 00056 #include "cvrVector.h" 00057 #include "cvrMatrix.h" 00058 #include "cvrFunctor.h" 00059 #include "cvrSinCos.h" 00060 #include "cvrLinearLeastSquares.h" 00061 #include <vector> 00062 #include <limits> 00063 00064 namespace cvr { 00065 00066 /** 00067 * Class affineTransformation2D 00068 * 00069 * The affine transformation for 2D spaces performs a planar 00070 * modification of points in which only rotation, translation, 00071 * (anisotropic) scaling and sheer are applied. 00072 * 00073 * With homogeneous coordinates, the affine transformation can be stated as 00074 * \f[ 00075 * \begin{bmatrix} 00076 * x'\\y'\\1 00077 * \end{bmatrix} 00078 * = 00079 * \begin{bmatrix} 00080 * a_{00} & a_{01} & t_x \\ 00081 * a_{10} & a_{11} & t_y \\ 00082 * 0 & 0 & 1 00083 * \end{bmatrix} 00084 * \begin{bmatrix} 00085 * x\\y\\1 00086 * \end{bmatrix} 00087 * \f] 00088 * 00089 * This class transforms points only, and therefore is not intended for 00090 * images, in which case you should use cvr::matrixTransform. You can 00091 * however obtain from this class the matrix used by 00092 * cvr::matrixTransform::parameters to generate the same results. 00093 * 00094 * Most apply methods are templates of a point type P, i.e. the type P is 00095 * usually a container that can be accessed with the operator[], like 00096 * the types cvr::point<T>, cvr::vector<T>. 00097 * 00098 * @see affineTransformation2D::parameters 00099 * @see euclideanTransformation2D 00100 * @see euclideanTransformation3D 00101 * @see affineTransformation2D 00102 * @see projectiveTransformation2D 00103 * 00104 * @ingroup gGeometricTrans 00105 */ 00106 class affineTransformation2D : public functor { 00107 public: 00108 /** 00109 * The parameters for the class affineTransformation2D 00110 */ 00111 class parameters : public functor::parameters { 00112 public: 00113 /** 00114 * Default constructor 00115 */ 00116 parameters(); 00117 00118 /** 00119 * Copy constructor 00120 * @param other the parameters object to be copied 00121 */ 00122 parameters(const parameters& other); 00123 00124 /** 00125 * Destructor 00126 */ 00127 ~parameters(); 00128 00129 /** 00130 * Copy the contents of a parameters object 00131 * @param other the parameters object to be copied 00132 * @return a reference to this parameters object 00133 */ 00134 parameters& copy(const parameters& other); 00135 00136 /** 00137 * Copy the contents of a parameters object 00138 * @param other the parameters object to be copied 00139 * @return a reference to this parameters object 00140 */ 00141 parameters& operator=(const parameters& other); 00142 00143 /** 00144 * Returns the complete name of the parameters class. 00145 */ 00146 virtual const std::string& name() const; 00147 00148 /** 00149 * Returns a pointer to a clone of the parameters. 00150 */ 00151 virtual parameters* clone() const; 00152 00153 /** 00154 * Returns a pointer to a new instance of the parameters. 00155 */ 00156 virtual parameters* newInstance() const; 00157 00158 /** 00159 * Write the parameters in the given ioHandler 00160 * @param handler the ioHandler to be used 00161 * @param complete if true (the default) the enclosing begin/end will 00162 * be also written, otherwise only the data block will be written. 00163 * @return true if write was successful 00164 */ 00165 virtual bool write(ioHandler& handler,const bool complete=true) const; 00166 00167 /** 00168 * Read the parameters from the given ioHandler 00169 * @param handler the ioHandler to be used 00170 * @param complete if true (the default) the enclosing begin/end will 00171 * be also written, otherwise only the data block will be written. 00172 * @return true if write was successful 00173 */ 00174 virtual bool read(ioHandler& handler,const bool complete=true); 00175 00176 // ------------------------------------------------ 00177 // the parameters 00178 // ------------------------------------------------ 00179 00180 /** 00181 * Magnitude of the translation in x and y directions 00182 * 00183 * Default value: 0 00184 */ 00185 fpoint translation; 00186 00187 /** 00188 * First element of the 2x2 submatrix 00189 * 00190 * Default value: 1 00191 */ 00192 float a00; 00193 00194 /** 00195 * Second element of the 2x2 submatrix 00196 * 00197 * Default value: 0 00198 */ 00199 float a01; 00200 00201 /** 00202 * Third element of the 2x2 submatrix 00203 * 00204 * Default value: 0 00205 */ 00206 float a10; 00207 00208 /** 00209 * Fourth element of the 2x2 submatrix 00210 * 00211 * Default value: 1 00212 */ 00213 float a11; 00214 00215 /** 00216 * Parameters used in the linearLeastSquares functor for 00217 * the estimation tasks. 00218 * 00219 * Default value: default 00220 */ 00221 linearLeastSquares::parameters llsParameters; 00222 }; 00223 00224 /** 00225 * Default constructor 00226 */ 00227 affineTransformation2D(); 00228 00229 /** 00230 * Construct a functor using the given parameters 00231 */ 00232 affineTransformation2D(const parameters& par); 00233 00234 /** 00235 * Copy constructor 00236 * @param other the object to be copied 00237 */ 00238 affineTransformation2D(const affineTransformation2D& other); 00239 00240 /** 00241 * Destructor 00242 */ 00243 virtual ~affineTransformation2D(); 00244 00245 /** 00246 * Transform the given point. 00247 * 00248 * @param srcdest point<T> with the source data. The result 00249 * will be left here too. 00250 * @return true if apply successful or false otherwise. 00251 */ 00252 template<class P> 00253 bool apply(P& srcdest) const; 00254 00255 /** 00256 * Transform the point \a src and write the transformation on the \a dest 00257 * point. 00258 * 00259 * @param src point<T> with the source data. 00260 * @param dest point<T> where the result will be left. 00261 * @return true if apply successful or false otherwise. 00262 */ 00263 template<class P> 00264 bool apply(const P& src, P& dest) const; 00265 00266 /** 00267 * Estimate a transformation that maps the first set of points into 00268 * the second set of points. 00269 * 00270 * The resulting estimation is left in the parameters. 00271 * 00272 * This method assumes that the corresponding point to setA[idx] is 00273 * stored in setB[idx]. 00274 * 00275 * Only the first \c dof()/2 correspondences will be used for the 00276 * estimation, and you need at least \c dof()/2 elements for the 00277 * transformation to be computed. 00278 */ 00279 template<class P> 00280 bool estimate(const std::vector<P>& setA, 00281 const std::vector<P>& setB); 00282 00283 00284 /** 00285 * Do a linear least squares error minimization for a transformation that 00286 * maps the first set of points into the second set of points. 00287 * 00288 * The resulting estimation is left in the parameters. 00289 * 00290 * This method assumes that the corresponding point to setA[idx] is 00291 * stored in setB[idx]. 00292 * 00293 * For the LLS to be computed, more than \c dof()/2 correspondences are 00294 * necessary for the estimation. 00295 */ 00296 template<class P> 00297 bool estimateLLS(const std::vector<P>& setA, 00298 const std::vector<P>& setB); 00299 00300 00301 /** 00302 * Do a linear least squares error minimization for a transformation that 00303 * maps the first set of points into the second set of points. 00304 * 00305 * The resulting estimation is left in the parameters. 00306 * 00307 * This method assumes that the corresponding point to setA[idx] is 00308 * stored in setB[idx]. 00309 * 00310 * For the LLS to be computed, more than \c dof()/2 correspondences are 00311 * necessary for the estimation. 00312 * 00313 * For the estimation, just the points with the indices specified in 00314 * \c selection are given. 00315 * 00316 * @return true if successful, false otherwise 00317 */ 00318 template<class P> 00319 bool estimateLLS(const ivector& selection, 00320 const std::vector<P>& setA, 00321 const std::vector<P>& setB); 00322 00323 /** 00324 * Degrees of freedom of the transformation. 00325 * 00326 * Usually this means the minimal number of parameters with which the 00327 * transforamtion matrix can be generated. 00328 */ 00329 int dof() const; 00330 00331 /** 00332 * Generate the transformation matrix that would be required by 00333 * cvr::matrixTransform to generate the same coordinate transformation. 00334 * The result is, so to speak, the matrix representation of the parameters. 00335 * 00336 * This method is provided to keep consistency with other matrix 00337 * transformation functors, since in this case, the conversion between the 00338 * parameters and the matrix is completely straightforward. 00339 * 00340 * @param mat matrix container of the result. 00341 */ 00342 void generateMatrix(fmatrix& mat) const; 00343 00344 /** 00345 * Decompose matrix. 00346 * 00347 * This method decomposes the computed matrix as a series of simpler 00348 * processes. 00349 * 00350 * The affine transformation matrix H is interpreted as the 3x3 matrix 00351 * 00352 * \f[ 00353 * H = \begin{bmatrix} A & t \\ 0^T & 1 \end{bmatrix} 00354 * \f] 00355 * 00356 * where the 2x2 submatrix A can be decomposed as a series of pure 00357 * rotations, and asymmetrical scalations, as follow: 00358 * 00359 * \f[ 00360 * A = R(\theta) R(-\phi) D R(\phi) 00361 * \f] 00362 * 00363 * with 00364 * 00365 * \f[ 00366 * D = \begin{bmatrix} \lambda_1 & 0 \\ 0 & \lambda_2 \end{bmatrix} 00367 * \f] 00368 */ 00369 void decompose(float& theta, 00370 float& phi, 00371 float& lambda1, 00372 float& lambda2, 00373 float& tx, 00374 float& ty) const; 00375 00376 /** 00377 * Generate the transformation matrix that would be required by 00378 * cvr::matrixTransform to generate the same coordinate transformation. 00379 * The result is, so to speak, the matrix representation of the parameters. 00380 */ 00381 fmatrix generateMatrix() const; 00382 00383 /** 00384 * Copy data of "other" functor. 00385 * @param other the functor to be copied 00386 * @return a reference to this functor object 00387 */ 00388 affineTransformation2D& copy(const affineTransformation2D& other); 00389 00390 /** 00391 * Alias for copy member 00392 * @param other the functor to be copied 00393 * @return a reference to this functor object 00394 */ 00395 affineTransformation2D& 00396 operator=(const affineTransformation2D& other); 00397 00398 /** 00399 * Returns the complete name of the functor class 00400 */ 00401 virtual const std::string& name() const; 00402 00403 /** 00404 * Returns a pointer to a clone of this functor. 00405 */ 00406 virtual affineTransformation2D* clone() const; 00407 00408 /** 00409 * Returns a pointer to a new instance of this functor. 00410 */ 00411 virtual affineTransformation2D* newInstance() const; 00412 00413 /** 00414 * Returns used parameters 00415 */ 00416 const parameters& getParameters() const; 00417 00418 /** 00419 * Update parameters 00420 */ 00421 bool updateParameters(); 00422 00423 protected: 00424 00425 /** 00426 * Returns used parameters 00427 */ 00428 parameters& getRWParameters(); 00429 00430 /** 00431 * Shadow of the translation point 00432 */ 00433 fpoint trans_; 00434 00435 /** 00436 * Shadow of matrix element 00437 */ 00438 float a00_; 00439 00440 /** 00441 * Shadow of matrix element 00442 */ 00443 float a01_; 00444 00445 /** 00446 * Shadow of matrix element 00447 */ 00448 float a10_; 00449 00450 /** 00451 * Shadow of matrix element 00452 */ 00453 float a11_; 00454 00455 /** 00456 * Singular value decomposition 00457 * 00458 * Convenience method to avoid the SVD to be present in the template 00459 * implementation 00460 */ 00461 linearLeastSquares lls_; 00462 }; 00463 } 00464 00465 #include "cvrAffineTransformation2D_template.h" 00466 00467 #endif 00468