latest version v1.9 - last update 10 Apr 2010 |
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