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

ltiGeometricFeatures.h

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 .......: ltiGeometricFeatures.h
00027  * authors ....: Ulle Canzler
00028  * organization: LTI, RWTH Aachen
00029  * creation ...: 11.1.2001
00030  * revisions ..: $Id: ltiGeometricFeatures.h,v 1.12 2006/02/08 11:11:32 ltilib Exp $
00031  */
00032 
00033 #ifndef _LTI_GEOMETRIC_FEATURES_H_
00034 #define _LTI_GEOMETRIC_FEATURES_H_
00035 
00036 #include "ltiTypes.h"
00037 #include "ltiContour.h"
00038 #include "ltiMath.h"
00039 #include <map>
00040 
00041 // include parent class:
00042 #include "ltiGlobalFeatureExtractor.h"
00043 
00044 namespace lti {
00045   /**
00046    * Computes features, which describe some geometric properties of a 2D shape.
00047    * Results can be obtained as vector or map.
00048    *
00049    * The shape %object may be passed as areaPoints or
00050    * borderPoints. The Features are grouped. Group 0 will always be
00051    * calculated, the other groups only if indicated by the
00052    * corresponding %parameter.  The following features are
00053    * available:<br>
00054    *
00055    * (T,R,S,F indicate invariance against Translation, Rotation,
00056    * Scaling, Flipping)
00057    *
00058    * (The quoted "..." names are the key-names for accessing the
00059    * result map and at the same time the const-aliases for indices of
00060    * the result %vector.)
00061    *
00062    * Feature Group 0 (COG means "center of gravity").
00063    *
00064    * - feat[0] = "areasize"    = (T,F) number of enclosed pixels (area).
00065    * - feat[1] = "bordersize"  = (T,F) number of border pixels.
00066    * - feat[2] = "xcog"        = x-component of COG.
00067    * - feat[3] = "ycog"        = y-component of COG.
00068    * - feat[4] = "xmin"        = smallest x coordinate.
00069    * - feat[5] = "xmax"        = largest x coordinate.
00070    * - feat[6] = "ymin"        = smallest y coordinate.
00071    * - feat[7] = "ymax"        = largest y coordinate.
00072    * - feat[26]= "compactness" = (T,R,S,F)
00073    *    compactness=(4PI*area/(bordersize)^2), ranges from 0 to 1.
00074    *
00075    * Feature Group 1 (see Sonka, Hlavac, Boyle: Image Processing,
00076    * Analysis, and Machine Vision).
00077    *
00078    * - feat[8] = "m02"         = (T) central moment m02.
00079    * - feat[9] = "m03"         = (T) central moment m03.
00080    * - feat[10]= "m11"         = (T) central moment m11.
00081    * - feat[11]= "m12"         = (T) central moment m12.
00082    * - feat[12]= "m20"         = (T) central moment m20.
00083    * - feat[13]= "m21"         = (T) central moment m21.
00084    * - feat[14]= "m30"         = (T) central moment m30.
00085    *
00086    * - feat[22]= "j1"          = (T,R,F) inertia parallel to main axis.
00087    * - feat[23]= "j2"          = (T,R,F) inertia orthogonal to main axis.
00088    * - feat[24]= "orientation" = (T,S) orientation of main
00089    *             axis. range: -90 to 90 degrees.
00090    * - feat[25]= "eccentricity"= (T,R,S,F) eccentricity, ranges from 0
00091    *             (=circle) to 1 (=line).
00092    *
00093    * Feature Group 2. These are the first 7 moment invariants as
00094    * described in "Visual Pattern Recognition by Moment Invariants" by
00095    * Ming-Kuei Hu (IRE Transactions on Information Theory,
00096    * 1962). Since values can be very small, they have additionally
00097    * been scaled by the function sign(x)*log(abs(x))
00098    * - feat[15]= "hu1"         = (T,R,S,F) moment invariant 1.
00099    * - feat[16]= "hu2"         = (T,R,S,F) moment invariant 2.
00100    * - feat[17]= "hu3"         = (T,R,S,F) moment invariant 3.
00101    * - feat[18]= "hu4"         = (T,R,S,F) moment invariant 4.
00102    * - feat[19]= "hu5"         = (T,R,S,F) moment invariant 5.
00103    * - feat[20]= "hu6"         = (T,R,S,F) moment invariant 6.
00104    * - feat[21]= "hu7"         = (T,R,S) moment invariant 7.
00105    *
00106    * Feature Group 3. (note that "compactness" is now computed in feature
00107    * group 0 and j1, j2, orientation, eccentricity are now computed in
00108    * feature group 1 at no extra cost)
00109    *
00110    * Empty now, but keept for compatibility with group 4
00111    *
00112    * Feature Group 4. All the following distances are relative to the COG.
00113    * Calculation of these features is always performed using
00114    * BoundaryDefinition == CentralBoundary.
00115    *
00116    * - feat[27]= "rmin"        = (T,R,F) minimum distance to border.
00117    * - feat[28]= "rmax"        = (T,R,F) maximum  distance to border.
00118    * - feat[29]= "rmean"       = (T,R,F) mean distance to border.
00119    * - feat[30]= "dleft"       = (T,R -90°to+90°) leftmost distance to
00120    *                             main axis.
00121    * - feat[31]= "dright"      = (T,R -90°to+90°) rightmost distance to main
00122    *                             axis.
00123    * - feat[32]= "dfront"      = (T,R -90°to+90°) frontmost distance to COG,
00124    *                             along main axis.
00125    * - feat[33]= "drear" = (T,R -90°to+90°) rearmost distance to COG, along
00126    *                       main axis.
00127    */
00128   class geometricFeatures : public globalFeatureExtractor {
00129   public:
00130     /**
00131      * Labels for feature indices
00132      */
00133     enum {
00134       areasize    = 0,  /**< areasize   */   
00135       bordersize  = 1,  /**< bordersize */ 
00136       xcog        = 2,  /**< xcog */       
00137       ycog        = 3,  /**< ycog */
00138       xmin        = 4,  /**< xmin */
00139       xmax        = 5,  /**< xmax */
00140       ymin        = 6,  /**< ymin */
00141       ymax        = 7,  /**< ymax */
00142       m02         = 8,  /**< m02 */
00143       m03         = 9,  /**< m03 */
00144       m11         = 10, /**< m11 */
00145       m12         = 11, /**< m12 */
00146       m20         = 12, /**< m20 */
00147       m21         = 13, /**< m21 */
00148       m30         = 14, /**< m30 */
00149       hu1         = 15, /**< hu1 */
00150       hu2         = 16, /**< hu2 */
00151       hu3         = 17, /**< hu3 */
00152       hu4         = 18, /**< hu4 */
00153       hu5         = 19, /**< hu5 */
00154       hu6         = 20, /**< hu6 */
00155       hu7         = 21, /**< hu7 */
00156       j1          = 22, /**< j1  */
00157       j2          = 23, /**< j2  */
00158       orientation = 24, /**< orientation  */
00159       eccentricity= 25, /**< eccentricity */
00160       compactness = 26, /**< compactness  */
00161       rmin        = 27, /**< rmin   */
00162       rmax        = 28, /**< rmax   */
00163       rmean       = 29, /**< rmean  */
00164       dleft       = 30, /**< dleft  */
00165       dright      = 31, /**< dright */
00166       dfront      = 32, /**< dfront */
00167       drear       = 33, /**< drear  */ 
00168       numberOfFeatures = 34 /**< numberOfFeatures */ 
00169     };
00170 
00171     /**
00172      * the parameters for the class geometricFeatures
00173      */
00174     class parameters : public globalFeatureExtractor::parameters {
00175     public:
00176 
00177       /**
00178        * default constructor
00179        */
00180       parameters();
00181 
00182       /**
00183        * copy constructor
00184        * @param other the parameters object to be copied
00185        */
00186       parameters(const parameters& other);
00187 
00188       /**
00189        * destructor
00190        */
00191       ~parameters();
00192 
00193       /**
00194        * returns name of this type
00195        */
00196       const char* getTypeName() const;
00197 
00198       /**
00199        * copy the contents of a parameters object
00200        * @param other the parameters object to be copied
00201        * @return a reference to this parameters object
00202        */
00203       parameters& copy(const parameters& other);
00204 
00205       /**
00206        * returns a pointer to a clone of the parameters
00207        */
00208       virtual functor::parameters* clone() const;
00209 
00210 
00211       /**
00212        * write the parameters in the given ioHandler
00213        * @param handler the ioHandler to be used
00214        * @param complete if true (the default) the enclosing begin/end will
00215        *        be also written, otherwise only the data block will be written.
00216        * @return true if write was successful
00217        */
00218       virtual bool write(ioHandler& handler,
00219                          const bool complete=true) const;
00220 
00221       /**
00222        * read the parameters from the given ioHandler
00223        * @param handler the ioHandler to be used
00224        * @param complete if true (the default) the enclosing begin/end will
00225        *        be also written, otherwise only the data block will be written.
00226        * @return true if write was successful
00227        */
00228       virtual bool read(ioHandler& handler,const bool complete=true);
00229 
00230 #     ifdef _LTI_MSC_6
00231       /**
00232        * this function is required by MSVC only, as a workaround for a
00233        * very awful bug, which exists since MSVC V.4.0, and still by
00234        * V.6.0 with all bugfixes (so called "service packs") remains
00235        * there...  This method is public due to another bug!, so please
00236        * NEVER EVER call this method directly
00237        */
00238       bool readMS(ioHandler& handler,const bool complete=true);
00239 
00240       /**
00241        * this function is required by MSVC only, as a workaround for a
00242        * very awful bug, which exists since MSVC V.4.0, and still by
00243        * V.6.0 with all bugfixes (so called "service packs") remains
00244        * there...  This method is public due to another bug!, so please
00245        * NEVER EVER call this method directly
00246        */
00247       bool writeMS(ioHandler& handler,const bool complete=true) const;
00248 #     endif
00249 
00250       /**
00251        * Toggle calculation of feature group 1.
00252        *
00253        * Default is true
00254        */
00255        bool calcFeatureGroup1;
00256       /**
00257        * Toggle calculation of feature group 2.
00258        *
00259        * Default is true
00260        */
00261        bool calcFeatureGroup2;
00262       /**
00263        * Toggle calculation of feature group 3.
00264        *
00265        * Default is true
00266        */
00267        bool calcFeatureGroup3;
00268       /**
00269        * Toggle calculation of feature group 4.
00270        *
00271        * Default is true
00272        */
00273        bool calcFeatureGroup4;
00274 
00275        /**
00276         * Boundary definition.
00277         *
00278         * The boundary definition to be used (default: CentralBoundary).
00279         */
00280        enum eBoundaryDefinition {
00281          /**
00282           * The central boundary is the line drawn from the center of
00283           * each borderPoint to the center of the following
00284           * borderPoint, and from the last one's center to the first
00285           * one's (with sub-pixel accuracy, meaning that the length is
00286           * the same as it were in continuous space).
00287           *
00288           * A single pixel has a central boundary length of 0 and an
00289           * area of 0.  A tiny rectangle with upper left corner at
00290           * (0,0) and bottom right corner at (1,1) has an outer
00291           * boundary length of 4 and an area of 1.
00292           *
00293           * Note: We define that objects with an area of 0 have the
00294           * same COG as by the OuterBoundary definition.
00295           *
00296           * \b Disadvantages: Very large objects may lead to
00297           * numerical problems in feature group 2 (and thus above).
00298           *
00299           * Formulas taken from: Carsten Steger: On the Calculation of
00300           * Arbitrary Moments of Polygons; Technical Report
00301           * FGBV-96-05, Forschungsgruppe Bildverstehen (FG BV),
00302           * Informatik IX, Technische Universität München, October
00303           * 1996
00304           *
00305           * http://www9.informatik.tu-muenchen.de/people/steger/publications.html
00306           */
00307          CentralBoundary,
00308          /**
00309           * The outer boundary delimits the borderPoints completely,
00310           * ie a single pixel has an outer boundary length of 4 and an
00311           * area of 1.  A tiny rectangle with upper left corner at
00312           * (0,0) and bottom right corner at (1,1) has an outer
00313           * boundary length of 8 and an area of 4. I.e. the boundary
00314           * is considered to be part of the object (completely).
00315           *
00316           * \b Disadvantages: By this definition, a square and a
00317           * circle with equal side length resp. diameter have the same
00318           * boundary length if the square is parallel to the
00319           * coordinate axes. This contradicts intuition and renders
00320           * features like compactness rather meaningless. Also, an
00321           * object's boundary length is very susceptible to rotation.
00322           */
00323          OuterBoundary,
00324          /**
00325           * "Approximation" uses CentralBoundary for the calculation
00326           * of feature group 4 and the bordersize, and OuterBoundary
00327           * for all others.
00328           *
00329           * <b>Disadvantages</b>: This definition is mathematically
00330           * inconsistent, e.g.  especially very small objects may have
00331           * a compactness greater than 1.
00332           */
00333          Approximation
00334        };
00335 
00336        /**
00337         * Type of boundary definition to use.
00338         *
00339         * Default value: CentralBoundary
00340         */
00341        eBoundaryDefinition boundaryDefinition;
00342     };
00343 
00344     /**
00345      * default constructor
00346      */
00347     geometricFeatures();
00348 
00349     /**
00350      * Create functor with the given parameters
00351      */
00352     geometricFeatures(const parameters& par);
00353 
00354     /**
00355      * copy constructor
00356      * @param other the object to be copied
00357      */
00358     geometricFeatures(const geometricFeatures& other);
00359 
00360     /**
00361      * destructor
00362      */
00363     virtual ~geometricFeatures();
00364 
00365     /**
00366      * returns the name of this type ("geometricFeatures")
00367      */
00368     virtual const char* getTypeName() const;
00369 
00370     /**
00371      * Compute features for the object described by the given areaPoints.
00372      * The boundaryDefinition set in the parameters will be considered.
00373      *
00374      * You can access a feature by its enum-name
00375      * (e.g. features[eFeatures::areasize]).
00376      * Please refer to Class Documentation for enum-names.
00377      *
00378      * @param ap list of areaPoints
00379      * @param features the Features as vector of doubles
00380      * @return true if successful, false otherwise.
00381      */
00382     bool apply(const lti::areaPoints& ap,dvector& features) const;
00383 
00384     /**
00385      * Compute features for the object described by the given borderPoints.
00386      * This methos always uses the boundaryDefinition "CentralBoundary" for
00387      * reasons of computational efficiency.
00388      *
00389      * You can access a feature by its enum-name
00390      * (e.g. features[eFeatures::areasize]).
00391      * Please refer to Class Documentation for enum-names.
00392      *
00393      * @param borderPointList list of borderPoints
00394      * @param features the Features as vector of doubles
00395      * @return true if successful, false otherwise.
00396      */
00397     bool apply(const lti::borderPoints& borderPointList,
00398                dvector& features) const;
00399 
00400     /**
00401      * Considers io Points for feature computation.
00402      *
00403      * The boundaryDefinition set in the parameters is currently not
00404      * considered; an approximation is returned instead.
00405      *
00406      * You can access a feature by its enum-name
00407      * (e.g. features[eFeatures::areasize]).  Please refer to Class
00408      * Documentation for enum-names.
00409      *
00410      * @param ioPointList list of ioPoints
00411      * @param features the Features as vector of doubles
00412      * @return true if successful, false otherwise.
00413      */
00414     bool apply(const lti::ioPoints& ioPointList,
00415                dvector& features) const;
00416 
00417     /**
00418      * Considers all area Points for feature computation.
00419      *
00420      * Warning! Working with a map is less efficient than with a
00421      * vector, but easier to use.
00422      *
00423      * You can access a feature by its key-name (e.g. features["areasize"]).
00424      * Please refer to Class Documentation for key-names.
00425      *
00426      * @param ap list of areaPoints
00427      * @param features a map with the extracted features
00428      * @return true if successful, false otherwise.
00429      */
00430     bool apply(const lti::areaPoints& ap,
00431                std::map<std::string,double>& features) const;
00432 
00433     /**
00434      * Considers border Points for feature computation.
00435      * Warning! Working with a map is less efficient than with a vector,
00436      * but easier to use.
00437      * You can access a feature by its key-name (e.g. features["areasize"]).
00438      * Please refer to Class Documentation for key-names.
00439      * @param borderPointList list of borderPoints
00440      * @param features a map with the extracted features
00441      * @return true if successful, false otherwise.
00442      */
00443     bool apply(const lti::borderPoints& borderPointList,
00444                std::map<std::string,double>& features) const;
00445 
00446     /**
00447      * Considers io Points for feature computation.
00448      * Warning! Working with a map is less efficient than with a vector,
00449      * but easier to use.
00450      * You can access a feature by its key-name (e.g. features["areasize"]).
00451      * Please refer to Class Documentation for key-names.
00452      * @param ioPointList list of ioPoints
00453      * @param features a map with the extracted features
00454      * @return true if successful, false otherwise.
00455      */
00456     bool apply(const lti::ioPoints& ioPointList,
00457                std::map<std::string,double>& features) const;
00458 
00459     /**
00460      * copy data of "other" functor.
00461      * @param other the functor to be copied
00462      * @return a reference to this functor object
00463      */
00464     geometricFeatures& copy(const geometricFeatures& other);
00465 
00466     /**
00467      * Alias for copy operator.
00468      * @param other the functor to be copied
00469      * @return a reference to this functor object
00470      */
00471     geometricFeatures& operator=(const geometricFeatures& other);
00472 
00473     /**
00474      * returns a pointer to a clone of this functor.
00475      */
00476     virtual functor* clone() const;
00477 
00478     /**
00479      * returns used parameters
00480      */
00481     const parameters& getParameters() const;
00482 
00483     /**
00484      * Compute the length of the given border according to the
00485      * given boundary definition.
00486      */
00487     float getLength(const borderPoints& bp,
00488       const parameters::eBoundaryDefinition& boundaryDefinition) const;
00489 
00490   private:
00491     /**
00492      * This is an internal help function.
00493      * sign(x)*log(abs(x)) for scanning the channel reg. Objects
00494      * @param x value
00495      * @return sign(x)*log(abs(x))
00496      */
00497     inline double logn( double x ) const;
00498 
00499     /**
00500      * This is an internal help function for scanning the channel reg. Objects
00501      * @param numerator nominator
00502      * @param denominator denominator
00503      * @return fraction, in case of deviding by zero -> zero will be returned !
00504      */
00505     inline double divide( double numerator, double denominator ) const;
00506 
00507     /**
00508      * This is an internal function for mapping features to a dvector
00509      * @param theMap
00510      * @param theVector
00511      * @return true if successfull
00512      */
00513     bool mapFeatures(dvector& theVector, 
00514                      std::map<std::string,double>& theMap) const;
00515 
00516     /**
00517      * Compute the COG of a massless borderPoints object (according
00518      * to OuterBoundary definition) 
00519      */
00520     void computeMasslessCOG(const borderPoints& bp, 
00521                             double& xCog,
00522                             double& yCog) const;
00523 
00524 public: // used by lti::borderPoints to compute their own length
00525 
00526     /**
00527      * helper array for chain codes, stores direction (e.g. North)
00528      * depending on x/y step. x/y step may be -1/0/1. Add 1 -> 0/1/2.
00529      * Use as index, e.g. direction[xStep+1][yStep+1] to obtain direction.
00530      * direction[1][1] means neither x nor y step -> Invalid.
00531      */
00532     static const int direction[3][3];
00533 
00534     /**
00535      * Helper array that stores the length of the outer boundary contributed
00536      * by two steps in the directions that serve as index. E.g. one step N,
00537      * then one step NW -> outerBoundaryLength[NW][N]. Invalid step sequences
00538      * are marked with a value of -1.
00539      *
00540      * For a definition of the outer boundary, see eBoundaryDefinition.
00541      */
00542     static const int outerBoundaryLength[8][8];
00543 
00544     /**
00545      * Helper array to compute the length of the central boundary. When
00546      * iterating through the borderPoints, a step can be defined as the
00547      * difference from the current point to the last point. Decomposing this
00548      * step into x and y step and incrementing each by 1, we have a tuple
00549      * (0-2,0-2) with (1,1) meaning no step (which is invalid). Using these
00550      * steps as indices to this array, the step's contribution to the central
00551      * boundary length is returned.
00552      *
00553      * For a definition of the central boundary, see eBoundaryDefinition.
00554      */
00555     static const double centralBoundaryLength[3][3];
00556   };
00557 }
00558 
00559 #endif

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