LTI-Lib latest version v1.9 - last update 10 Apr 2010

ltiActiveShapeModel.h

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

Generated on Sat Apr 10 15:25:06 2010 for LTI-Lib by Doxygen 1.6.1