![]() |
latest version v1.9 - last update 10 Apr 2010 |
![]() |
00001 /* 00002 * Copyright (C) 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 .......: ltiActiveShapeModel.h 00027 * authors ....: Benjamin Winkler, Holger Fillbrandt 00028 * organization: LTI, RWTH Aachen 00029 * creation ...: 1.3.2002 00030 * revisions ..: $Id: ltiActiveShapeModel.h,v 1.8 2006/02/07 18:28:08 ltilib Exp $ 00031 */ 00032 00033 #ifndef _LTI_ACTIVE_SHAPE_MODEL_H_ 00034 #define _LTI_ACTIVE_SHAPE_MODEL_H_ 00035 00036 00037 #include "ltiPointDistributionModel.h" 00038 #include "ltiGeometricTransform.h" 00039 #include "ltiFunctor.h" 00040 00041 namespace lti { 00042 /** 00043 * This is the base class for active shape models (ASM). ASMs are deformable 00044 * 2D-templates, that can align themselves to image features according 00045 * to defined search strategies (see derived classes). The deformation is 00046 * regularized (i.e. constrained) by an underlying PDM (pointDistributionModel). 00047 * 00048 * This class provides the methods for aligning PDM shapes (pointDistributionModel::shape) 00049 * and to correct invalid shapes to satisfy the restrictions of a given PDM. 00050 * Furthermore, methods to obtain information about the position of a shape are provided. 00051 * Shapes with weighted points (point reliabilities) are also supported. 00052 */ 00053 class activeShapeModel : public functor { 00054 public: 00055 /** 00056 * the parameters for the class activeShapeModel 00057 */ 00058 class parameters : public functor::parameters { 00059 public: 00060 /** 00061 * default constructor 00062 */ 00063 parameters(); 00064 00065 /** 00066 * copy constructor 00067 * @param other the parameters object to be copied 00068 */ 00069 parameters(const parameters& other); 00070 00071 /** 00072 * destructor 00073 */ 00074 ~parameters(); 00075 00076 /** 00077 * returns name of this type 00078 */ 00079 const char* getTypeName() const; 00080 00081 /** 00082 * copy the contents of a parameters object 00083 * @param other the parameters object to be copied 00084 * @return a reference to this parameters object 00085 */ 00086 parameters& copy(const parameters& other); 00087 00088 /** 00089 * copy the contents of a parameters object 00090 * @param other the parameters object to be copied 00091 * @return a reference to this parameters object 00092 */ 00093 parameters& operator=(const parameters& other); 00094 00095 00096 /** 00097 * returns a pointer to a clone of the parameters 00098 */ 00099 virtual functor::parameters* clone() const; 00100 00101 /** 00102 * write the parameters in the given ioHandler 00103 * @param handler the ioHandler to be used 00104 * @param complete if true (the default) the enclosing begin/end will 00105 * be also written, otherwise only the data block will be written. 00106 * @return true if write was successful 00107 */ 00108 virtual bool write(ioHandler& handler,const bool complete=true) const; 00109 00110 /** 00111 * read the parameters from the given ioHandler 00112 * @param handler the ioHandler to be used 00113 * @param complete if true (the default) the enclosing begin/end will 00114 * be also written, otherwise only the data block will be written. 00115 * @return true if write was successful 00116 */ 00117 virtual bool read(ioHandler& handler,const bool complete=true); 00118 00119 # ifdef _LTI_MSC_6 00120 /** 00121 * this function is required by MSVC only, as a workaround for a 00122 * very awful bug, which exists since MSVC V.4.0, and still by 00123 * V.6.0 with all bugfixes (so called "service packs") remains 00124 * there... This method is also public due to another bug, so please 00125 * NEVER EVER call this method directly: use read() instead 00126 */ 00127 bool readMS(ioHandler& handler,const bool complete=true); 00128 00129 /** 00130 * this function is required by MSVC only, as a workaround for a 00131 * very awful bug, which exists since MSVC V.4.0, and still by 00132 * V.6.0 with all bugfixes (so called "service packs") remains 00133 * there... This method is also public due to another bug, so please 00134 * NEVER EVER call this method directly: use write() instead 00135 */ 00136 bool writeMS(ioHandler& handler,const bool complete=true) const; 00137 # endif 00138 00139 // ------------------------------------------------ 00140 // the parameters 00141 // ------------------------------------------------ 00142 00143 /** 00144 * The PDM (pointDistributionModel), that regularizes the deformation of 00145 * an ASM. 00146 */ 00147 pointDistributionModel model; 00148 00149 /** 00150 * Defines the limit for valid shapes in eigenspace. 00151 * The dimensions, that exceede the limit given by 00152 * varianceCoefficient*eigenvalue , where eigenvalue is 00153 * the corresponding variance, are set to 0.0 . 00154 * 00155 * Default value is 3.0 00156 */ 00157 double varianceCoefficient; 00158 00159 /** 00160 * Weight points by point reliabilities before correcting the shape. 00161 * I.e. unreliable points are moved towards the mean shape. Thus if 00162 * true, then use 00163 * 00164 * <code> 00165 * w = (eigenVectorMatrix)^T * ((shape - meanShape) * reliabilities) 00166 * </code> 00167 * 00168 * instead of 00169 * 00170 * <code> 00171 * w = (eigenVectorMatrix)^T * (shape - meanShape) 00172 * </code> 00173 * 00174 * By default this is set to false. 00175 * Reliability values are then only considered for the geometric 00176 * transformations (shift, rotate, scale). 00177 */ 00178 bool reliabilityAsWeightingFactor; 00179 00180 }; 00181 00182 /** 00183 * default constructor 00184 */ 00185 activeShapeModel(); 00186 00187 /** 00188 * copy constructor 00189 * @param other the object to be copied 00190 */ 00191 activeShapeModel(const activeShapeModel& other); 00192 00193 /** 00194 * destructor 00195 */ 00196 virtual ~activeShapeModel(); 00197 00198 /** 00199 * returns the name of this type ("activeShapeModel") 00200 */ 00201 virtual const char* getTypeName() const; 00202 00203 /** 00204 * copy data of "other" functor. 00205 * @param other the functor to be copied 00206 * @return a reference to this functor object 00207 */ 00208 activeShapeModel& copy(const activeShapeModel& other); 00209 00210 /** 00211 * alias for copy member 00212 * @param other the functor to be copied 00213 * @return a reference to this functor object 00214 */ 00215 activeShapeModel& operator=(const activeShapeModel& other); 00216 00217 /** 00218 * returns a pointer to a clone of this functor. 00219 */ 00220 virtual functor* clone() const; 00221 00222 /** 00223 * returns used parameters 00224 */ 00225 const parameters& getParameters() const; 00226 00227 /** 00228 * @name Transformation 00229 * Methods for transforming a shape from shape space to eigenspace and 00230 * vice versa. 00231 * 00232 * Eigenspace (w) -> shape space (x): 00233 * x = eigenVectorMatrix * weightsVector + meanShape <br> 00234 * Shape space (x) -> eigenspace (w): 00235 * w = (eigenVectorMatrix)^T * (shape - meanShape) <br> 00236 */ 00237 //@{ 00238 00239 /** 00240 * convert a shape to a weights vector, i.e. project a shape into the pdm 00241 * eigenspace 00242 * 00243 * Formula: w = (eigenVectorMatrix)^T * (shape - meanShape) 00244 * 00245 * Note: the shape is assumed to be aligned to position, size and rotation 00246 * of meanShape! 00247 * 00248 * @param src shape with the source data. 00249 * @param dest vector where the result will be left. 00250 */ 00251 void convertShapeToWeightsVector(const pointDistributionModel::shape &src, 00252 vector<double> &dest) const; 00253 00254 /** 00255 * convert a reliability-weighted shape to a weights vector, 00256 * i.e. project a shape into the pdm eigenspace 00257 * Formula: 00258 * w = (eigenVectorMatrix)^T * ((shape - meanShape) * reliabilities) 00259 * Note: the shape is assumed to be aligned to position, size and rotation 00260 * of meanShape! 00261 * @param src shape with the source data. 00262 * @param dest vector where the result will be left. 00263 * @param pointReliability vector containing point reliabilities. 00264 */ 00265 void convertShapeToWeightsVector(const pointDistributionModel::shape &src, 00266 vector<double> &dest, 00267 const fvector &pointReliability) const; 00268 00269 /** 00270 * convert a weights vector into a shape (i.e. shape space) 00271 * Formula: x = eigenVectorMatrix * weightsVector + meanShape 00272 * @param src vector with the source data. 00273 * @param dest shape where the result will be left. 00274 */ 00275 void 00276 convertWeightsVectorToShape(const vector<double> &src, 00277 pointDistributionModel::shape &dest) const; 00278 //@} 00279 00280 /** 00281 * @name Comparison 00282 * Methods for comparing and aligning two shapes. 00283 */ 00284 //@{ 00285 00286 /** 00287 * align a given shape to another. 00288 * 00289 * note that the return geometricTransform::parameters describe the 00290 * transformation from the referenceShape to the unaligned shape! this 00291 * is done to align a given shape to a normalized shape and be able to 00292 * easily project this normalized shape (e.g. meanShape) on the original 00293 * shape. 00294 * 00295 * @param shape shape to be aligned. the transformed shape will also be 00296 * saved here. 00297 * @param referenceShape fixed shape to be aligned to 00298 * @return geometric parameters that are used to re-transform shape 00299 */ 00300 geometricTransform::parameters 00301 alignShape(pointDistributionModel::shape &shape, 00302 const pointDistributionModel::shape &referenceShape) const; 00303 00304 /** 00305 * align a given weighted shape to another. 00306 * 00307 * @param shape shape to be aligned. the transformed shape will also be 00308 * saved here. 00309 * @param referenceShape fixed shape to be aligned to 00310 * @param pointReliability vector containing reliability values between 00311 * 0 (unreliable) and 1 (reliable) for all points 00312 * @return geometric parameters that are used to re-transform shape 00313 */ 00314 geometricTransform::parameters 00315 alignShape(pointDistributionModel::shape &shape, 00316 const pointDistributionModel::shape &referenceShape, 00317 const fvector &pointReliability) const; 00318 00319 /** 00320 * calculate mean difference of two shapes, i.e. the sum of squared 00321 * distances of all corresponding points divided by the number of points 00322 */ 00323 float 00324 calculateShapeDifference(const pointDistributionModel::shape &firstShape, 00325 const pointDistributionModel::shape &secondShape 00326 ) const; 00327 00328 /** 00329 * calculate difference of two weighted shapes 00330 */ 00331 float 00332 calculateShapeDifference(const pointDistributionModel::shape &firstShape, 00333 const pointDistributionModel::shape &secondShape, 00334 const fvector &pointReliability) const; 00335 //@} 00336 00337 00338 /** 00339 * @name Properties 00340 * Methods for computing properties of one shape. 00341 */ 00342 //@{ 00343 00344 /** 00345 * calculate the center of a given shape. 00346 * all points of the shape are summed and the results divided by the 00347 * number of points. 00348 * @return center of the given shape 00349 */ 00350 tpoint<float> 00351 calculateShapeCenter(const pointDistributionModel::shape &shape) const; 00352 00353 /** 00354 * calculate the center of a given shape. 00355 * all points of the shape are multiplied with their reliability factor, 00356 * then summed, and the results divided by the sum of reliabilities. 00357 */ 00358 tpoint<float> 00359 calculateShapeCenter(const pointDistributionModel::shape &shape, 00360 const fvector &pointReliability) const; 00361 00362 /** 00363 * calculate the mean distance of a given point to the points of a shape 00364 * @return average distance 00365 */ 00366 float 00367 calculateShapeDistance(const pointDistributionModel::shape &shape, 00368 const tpoint<float> &thePoint = 00369 tpoint<float>(0.0f, 0.0f)) const; 00370 00371 /** 00372 * calculate the mean distance of a given point to the 00373 * reliability-weighted points of a shape 00374 */ 00375 float calculateShapeDistance(const pointDistributionModel::shape &shape, 00376 const fvector &pointReliability, 00377 const tpoint<float> &thePoint = 00378 tpoint<float>(0.0f, 0.0f)) const; 00379 00380 /** 00381 * calculate the relative orientation difference of two shapes, 00382 * with regard to a given rotation center 00383 * @return angle between referenceShape and shape 00384 */ 00385 double 00386 calculateShapeOrientation(const pointDistributionModel::shape &shape, 00387 const pointDistributionModel::shape &referenceShape, 00388 const tpoint<float> &theCenter = 00389 tpoint<float>(0.0f, 0.0f)) const; 00390 00391 /** 00392 * calculate the relative orientation difference of two shapes 00393 * with regard to a given rotation center and given point reliabilities 00394 */ 00395 double 00396 calculateShapeOrientation(const pointDistributionModel::shape &shape, 00397 const pointDistributionModel::shape &referenceShape, 00398 const fvector &pointReliability, 00399 const tpoint<float> &theCenter = 00400 tpoint<float>(0.0, 0.0)) const; 00401 //@} 00402 00403 protected: 00404 00405 /** 00406 * calculate reliability-weighted scaling factor 00407 */ 00408 float 00409 calculateRelativeShapeScale(const pointDistributionModel::shape &shape, 00410 const pointDistributionModel::shape &referenceShape, 00411 const fvector &pointReliability, 00412 const tpoint<float> &shapeCenter = 00413 tpoint<float>(0.0, 0.0), 00414 const tpoint<float> &referenceShapeCenter = 00415 tpoint<float>(0.0, 0.0)) const; 00416 00417 /** 00418 * convert shape to weights vector, correct if invalid and convert back to 00419 * shape space. 00420 * @param srcdest shape with the source data. The result will be left 00421 * here too. 00422 */ 00423 void trimShape(pointDistributionModel::shape& srcdest) const; 00424 00425 /** 00426 * convert reliability-weighted shape to weights vector, correct if 00427 * invalid and convert back to shape space. 00428 * @param srcdest shape with the source data. The result will be left 00429 * here too. 00430 * @param pointReliability the reliabilities of each point of the shape as 00431 * value between 0.0 and 1.0 00432 */ 00433 void trimShape(pointDistributionModel::shape& srcdest, 00434 const fvector &pointReliability) const; 00435 00436 /** 00437 * Correct weights vector according to varianceCoefficient. 00438 * 00439 * all vector entries that are not in between -c*v and c*v, where 00440 * c is the given varianceCoefficient and v is the variance of the 00441 * corresponding dimension (eigenvector), are set to 0.0 00442 * 00443 * @param srcdest vector<double> with the source data. The result 00444 * will be left here too. 00445 */ 00446 void trimWeightsVector(vector<double>& srcdest) const; 00447 00448 /* 00449 * calculate normal direction of a point between two line segments 00450 * n = normalized( normalized(v1) - normalized(v2) ); 00451 */ 00452 tpoint<float> calculateNormal(const tpoint<float> &seg1, 00453 const tpoint<float> &seg2) const; 00454 00455 /** 00456 * calculate angle between a point and the x-axis 00457 */ 00458 double calculateAngle(const tpoint<float> &thePoint) const; 00459 00460 /** 00461 * convert the shape [(x1,y1),...] to a vector [x1, y1, x2, y2, ...] 00462 */ 00463 vector<double> buildVector(const pointDistributionModel::shape &src) const; 00464 00465 /** 00466 * convert a vector [x1, y1, x2, y2, ...] into a shape [(x1,y1),...] 00467 */ 00468 pointDistributionModel::shape buildShape(const vector<double> &src) const; 00469 00470 /* 00471 * return normalized vector 00472 */ 00473 tpoint<float> getNormalizedVector(const tpoint<float> &vec) const; 00474 00475 /** 00476 * create normals for each point 00477 */ 00478 void createListOfNormals(const pointDistributionModel::shape &theShape, 00479 tpointList<float> &listOfNormals) const; 00480 00481 }; 00482 } 00483 00484 #endif