Main MRPT website > C++ reference
MRPT logo
CFeature.h
Go to the documentation of this file.
00001 /* +---------------------------------------------------------------------------+
00002    |          The Mobile Robot Programming Toolkit (MRPT) C++ library          |
00003    |                                                                           |
00004    |                       http://www.mrpt.org/                                |
00005    |                                                                           |
00006    |   Copyright (C) 2005-2011  University of Malaga                           |
00007    |                                                                           |
00008    |    This software was written by the Machine Perception and Intelligent    |
00009    |      Robotics Lab, University of Malaga (Spain).                          |
00010    |    Contact: Jose-Luis Blanco  <jlblanco@ctima.uma.es>                     |
00011    |                                                                           |
00012    |  This file is part of the MRPT project.                                   |
00013    |                                                                           |
00014    |     MRPT is free software: you can redistribute it and/or modify          |
00015    |     it under the terms of the GNU General Public License as published by  |
00016    |     the Free Software Foundation, either version 3 of the License, or     |
00017    |     (at your option) any later version.                                   |
00018    |                                                                           |
00019    |   MRPT is distributed in the hope that it will be useful,                 |
00020    |     but WITHOUT ANY WARRANTY; without even the implied warranty of        |
00021    |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         |
00022    |     GNU General Public License for more details.                          |
00023    |                                                                           |
00024    |     You should have received a copy of the GNU General Public License     |
00025    |     along with MRPT.  If not, see <http://www.gnu.org/licenses/>.         |
00026    |                                                                           |
00027    +---------------------------------------------------------------------------+ */
00028 #ifndef CFeature_H
00029 #define CFeature_H
00030 
00031 #include <mrpt/utils/CImage.h>
00032 #include <mrpt/utils/stl_extensions.h>
00033 #include <mrpt/math/CMatrix.h>
00034 #include <mrpt/math/ops_matrices.h>
00035 #include <mrpt/math/KDTreeCapable.h>
00036 
00037 #include <mrpt/vision/types.h>
00038 #include <mrpt/vision/link_pragmas.h>
00039 
00040 namespace mrpt
00041 {
00042         namespace vision
00043         {
00044                 using namespace mrpt::utils;
00045                 using namespace mrpt::math;
00046                 using namespace std;
00047 
00048                 class CFeatureList;
00049                 class CMatchedFeatureList;
00050 
00051                 enum TListIdx
00052                 {
00053                     firstList = 0,
00054                     secondList,
00055                     bothLists
00056                 };
00057 
00058                 /** \defgroup mrptvision_features Feature detection, tracking, descriptors and matching 
00059                   * \ingroup mrpt_vision_grp
00060                   */
00061 
00062                 /** \addtogroup  mrptvision_features
00063                     @{ */
00064 
00065 
00066                 /****************************************************
00067                                                 Class CFEATURE
00068                 *****************************************************/
00069                 DEFINE_SERIALIZABLE_PRE_CUSTOM_BASE_LINKAGE( CFeature, mrpt::utils::CSerializable, VISION_IMPEXP )
00070 
00071                 /** A generic 2D feature from an image, extracted with \a CFeatureExtraction
00072                   * Each feature may have one or more descriptors (see \a descriptors), in addition to an image patch.
00073                   * The (Euclidean) distance between descriptors in a pair of features can be computed with  descriptorDistanceTo,
00074                   *  while the similarity of the patches is given by patchCorrelationTo.
00075                   *
00076                   *  \sa CFeatureList, TSimpleFeature, TSimpleFeatureList
00077                   */
00078                 class VISION_IMPEXP CFeature : public mrpt::utils::CSerializable
00079                 {
00080                         friend class CFeatureList;
00081                         friend class CMatchedFeatureList;
00082 
00083                         DEFINE_SERIALIZABLE( CFeature )
00084 
00085                 public:
00086                         float                           x,y;                    //!< Coordinates in the image
00087                         TFeatureID                      ID;                             //!< ID of the feature
00088                         CImage                          patch;                  //!< A patch of the image surrounding the feature
00089                         uint16_t                        patchSize;              //!< Size of the patch (patchSize x patchSize) (it must be an odd number)
00090                         TFeatureType            type;                   //!< Type of the feature: featNotDefined, featSIFT, featKLT,    featHarris, featSURF, featBeacon
00091                         TFeatureTrackStatus     track_status;   //!< Status of the feature tracking process (old name: KLT_status)
00092                         float                           response;               //!< A measure of the "goodness" of the feature (old name: KLT_val)
00093                         float                           orientation;    //!< Main orientation of the feature
00094                         float                           scale;                  //!< Feature scale into the scale space
00095                         uint8_t                         user_flags;             //!< A field for any other flags needed by the user (this has not a predefined meaning)
00096                         uint16_t            nTimesSeen;     //!< Number of frames it has been seen in a sequence of images.
00097                         uint16_t            nTimesNotSeen;  //!< Number of frames it has not been seen in a sequence of images.
00098                         uint16_t            nTimesLastSeen; //!< Number of frames since it was seen for the last time.
00099 
00100             double                          depth;              //!< The estimated depth in 3D of this feature wrt the camera in the current frame
00101             double                          initialDepth;       //!< The estimated depth in 3D of this feature wrt the camera that took its image
00102             TPoint3D                        p3D;                //!< The estimated 3D point of this feature wrt its camera
00103             deque<double>                   multiScales;        //!< A set of scales where the multi-resolution descriptor has been computed
00104             deque<vector<double> >          multiOrientations;  //!< A vector of main orientations (there is a vector of orientations for each scale)
00105             deque<vector<vector<int32_t> > >    multiHashCoeffs;    //!< A set of vectors containing the coefficients for a HASH table of descriptors
00106                         bool isPointFeature() const;                            //!< Return false only for Blob detectors (SIFT, SURF)
00107 
00108                         /** All the possible descriptors this feature may have */
00109                         struct VISION_IMPEXP TDescriptors
00110                         {
00111                                 TDescriptors();  // Initialization
00112 
00113                                 std::vector<uint8_t>            SIFT;                           //!< Feature descriptor
00114                                 std::vector<float>                          SURF;                               //!< Feature descriptor
00115                                 std::vector<float>                          SpinImg;                    //!< The 2D histogram as a single row
00116                                 uint16_t                                            SpinImg_range_rows;     //!< The number of rows (corresponding to range bins in the 2D histogram) of the original matrix from which SpinImg was extracted as a vector.
00117                                 mrpt::math::CMatrix                         PolarImg;                   //!< A polar image centered at the interest point
00118                                 mrpt::math::CMatrix                         LogPolarImg;                //!< A log-polar image centered at the interest point
00119                                 bool                                                polarImgsNoRotation;    //!< If set to true (manually, default=false) the call to "descriptorDistanceTo" will not consider all the rotations between polar image descriptors (PolarImg, LogPolarImg)
00120                                 deque<vector<vector<int32_t> > >    multiSIFTDescriptors;   //!< A set of SIFT-like descriptors for each orientation and scale of the multiResolution feature (there is a vector of descriptors for each scale)
00121 
00122                                 bool hasDescriptorSIFT() const { return !SIFT.empty(); };                       //!< Whether this feature has this kind of descriptor
00123                                 bool hasDescriptorSURF() const { return !SURF.empty(); }                        //!< Whether this feature has this kind of descriptor
00124                                 bool hasDescriptorSpinImg() const { return !SpinImg.empty(); };                 //!< Whether this feature has this kind of descriptor
00125                                 bool hasDescriptorPolarImg() const { return PolarImg.rows()!=0; } ;             //!< Whether this feature has this kind of descriptor
00126                                 bool hasDescriptorLogPolarImg() const { return LogPolarImg.rows()!=0; } ;       //!< Whether this feature has this kind of descriptor
00127                                 bool hasDescriptorMultiSIFT() const {
00128                     return (multiSIFTDescriptors.size() > 0 && multiSIFTDescriptors[0].size() > 0); //!< Whether this feature has this kind of descriptor
00129                 }
00130                         }
00131                         descriptors;
00132 
00133                         /** Return the first found descriptor, as a matrix.
00134                           * \return false on error, i.e. there is no valid descriptor.
00135                           */
00136                         bool getFirstDescriptorAsMatrix(mrpt::math::CMatrixFloat &desc) const;
00137 
00138                         /** Computes the normalized cross-correlation between the patches of this and another feature (normalized in the range [0,1], such as 0=best, 1=worst).
00139                           *  \note If this or the other features does not have patches or they are of different sizes, an exception will be raised.
00140                           * \sa descriptorDistanceTo
00141                           */
00142                         float patchCorrelationTo( const CFeature &oFeature) const;
00143 
00144                         /** Computes the Euclidean Distance between this feature's and other feature's descriptors, using the given descriptor or the first present one.
00145                           *  \note If descriptorToUse is not descAny and that descriptor is not present in one of the features, an exception will be raised.
00146                           * \sa patchCorrelationTo
00147                           */
00148                         float descriptorDistanceTo( const CFeature &oFeature,  TDescriptorType descriptorToUse = descAny, bool normalize_distances = true ) const;
00149 
00150                         /** Computes the Euclidean Distance between "this" and the "other" descriptors */
00151                         float descriptorSIFTDistanceTo( const CFeature &oFeature, bool normalize_distances = true ) const;
00152 
00153                         /** Computes the Euclidean Distance between "this" and the "other" descriptors */
00154                         float descriptorSURFDistanceTo( const CFeature &oFeature, bool normalize_distances = true  ) const;
00155 
00156                         /** Computes the Euclidean Distance between "this" and the "other" descriptors */
00157                         float descriptorSpinImgDistanceTo( const CFeature &oFeature, bool normalize_distances = true ) const;
00158 
00159                         /** Returns the minimum Euclidean Distance between "this" and the "other" polar image descriptor, for the best shift in orientation.
00160                           * \param oFeature The other feature to compare with.
00161                           * \param minDistAngle The placeholder for the angle at which the smallest distance is found.
00162                           * \return The distance for the best orientation (minimum distance).
00163                           */
00164                         float descriptorPolarImgDistanceTo(
00165                                 const CFeature &oFeature,
00166                                 float &minDistAngle,
00167                                 bool normalize_distances = true ) const;
00168 
00169                         /** Returns the minimum Euclidean Distance between "this" and the "other" log-polar image descriptor, for the best shift in orientation.
00170                           * \param oFeature The other feature to compare with.
00171                           * \param minDistAngle The placeholder for the angle at which the smallest distance is found.
00172                           * \return The distance for the best orientation (minimum distance).
00173                           */
00174                         float descriptorLogPolarImgDistanceTo(
00175                                 const CFeature &oFeature,
00176                                 float &minDistAngle,
00177                                 bool normalize_distances = true ) const;
00178 
00179                         /** Save the feature to a text file in this format:
00180               *    "%% Dump of mrpt::vision::CFeatureList. Each line format is:\n"
00181               *    "%% ID TYPE X Y ORIENTATION SCALE TRACK_STATUS RESPONSE HAS_SIFT [SIFT] HAS_SURF [SURF] HAS_MULTI [MULTI]_i"
00182               *    "%% |---------------------- feature ------------------| |---------------------- descriptors ------------------------|"
00183               *    "%% with:\n"
00184               *    "%%  TYPE  : The used detector: 0:KLT, 1: Harris, 2: BCD, 3: SIFT, 4: SURF, 5: Beacon, 6: FAST\n"
00185               *    "%%  HAS_* : 1 if a descriptor of that type is associated to the feature."
00186               *    "%%  SIFT  : Present if HAS_SIFT=1: N DESC_0 ... DESC_N-1"
00187               *    "%%  SURF  : Present if HAS_SURF=1: N DESC_0 ... DESC_N-1"
00188               *    "%%  MULTI : Present if HAS_MULTI=1: SCALE ORI N DESC_0 ... DESC_N-1"
00189               *    "%%-------------------------------------------------------------------------------------------\n");
00190                         */
00191             void saveToTextFile( const std::string &filename, bool APPEND = false );
00192 
00193                         /** Get the type of the feature
00194                         */
00195                         TFeatureType get_type() const { return type; }
00196 
00197                         /** Dump feature information into a text stream */
00198                         void dumpToTextStream( mrpt::utils::CStream &out) const;
00199 
00200                         void dumpToConsole() const;
00201 
00202                         /** Constructor
00203                         */
00204                         CFeature();
00205 
00206                         /** Virtual destructor */
00207                         virtual ~CFeature() {}
00208 
00209 
00210                 protected:
00211 
00212                         /** Internal function used by "descriptorLogPolarImgDistanceTo" and "descriptorPolarImgDistanceTo"
00213                           */
00214                         static float internal_distanceBetweenPolarImages(
00215                                 const mrpt::math::CMatrix &desc1,
00216                                 const mrpt::math::CMatrix &desc2,
00217                                 float &minDistAngle,
00218                                 bool normalize_distances,
00219                                 bool dont_shift_angle );
00220 
00221                 }; // end of class
00222 
00223 
00224                 /****************************************************
00225                                                 Class CFEATURELIST
00226                 *****************************************************/
00227                 /** A list of visual features, to be used as output by detectors, as input/output by trackers, etc.
00228                   */
00229                 class VISION_IMPEXP CFeatureList : public mrpt::math::KDTreeCapable<CFeatureList>
00230                 {
00231                 protected:
00232                         typedef std::vector<CFeaturePtr> TInternalFeatList;
00233 
00234                         TInternalFeatList  m_feats; //!< The actual container with the list of features
00235 
00236                 public:
00237                         /** The type of the first feature in the list */
00238                         inline TFeatureType get_type() const { return empty() ? featNotDefined : (*begin())->get_type(); }
00239 
00240                         /** Save feature list to a text file */
00241                         void saveToTextFile( const std::string &fileName, bool APPEND = false );
00242 
00243                         /** Save feature list to a text file */
00244                         void loadFromTextFile( const std::string &fileName );
00245 
00246                         /** Copies the content of another CFeatureList inside this one. The inner features are also copied. */
00247                         void copyListFrom( const CFeatureList &otherList );
00248 
00249                         /** Get the maximum ID into the list */
00250                         TFeatureID getMaxID() const;
00251 
00252                         /** Get a reference to a Feature from its ID */
00253                         CFeaturePtr getByID( const TFeatureID &ID ) const;
00254                         CFeaturePtr getByID( const TFeatureID &ID, int &out_idx ) const;
00255 
00256             /** Get a vector of references to a subset of features from their IDs */
00257             void getByMultiIDs( const vector<TFeatureID> &IDs, vector<CFeaturePtr> &out, vector<int> &outIndex ) const;
00258 
00259                         /** Get a reference to the nearest feature to the a given 2D point (version returning distance to closest feature in "max_dist")
00260                         *   \param x [IN] The query point x-coordinate
00261                         *   \param y [IN] The query point y-coordinate
00262                         *   \param max_dist [IN/OUT] At input: The maximum distance to search for. At output: The actual distance to the feature.
00263                         *  \return A reference to the found feature, or a NULL smart pointer if none found.
00264                         *  \note See also all the available KD-tree search methods, listed in mrpt::math::KDTreeCapable
00265                         */
00266                         CFeaturePtr nearest( const float x, const float y, double &max_dist ) const;
00267 
00268                         /** Constructor */
00269                         CFeatureList();
00270 
00271                         /** Virtual destructor */
00272                         virtual ~CFeatureList();
00273 
00274                         /** Call this when the list of features has been modified so the KD-tree is marked as outdated. */
00275                         inline void mark_kdtree_as_outdated() const { kdtree_mark_as_outdated(); }
00276 
00277                         /** @name Method and datatypes to emulate a STL container
00278                             @{ */
00279                         typedef TInternalFeatList::iterator iterator;
00280                         typedef TInternalFeatList::const_iterator const_iterator;
00281 
00282                         typedef TInternalFeatList::reverse_iterator reverse_iterator;
00283                         typedef TInternalFeatList::const_reverse_iterator const_reverse_iterator;
00284 
00285                         inline iterator begin() { return m_feats.begin(); }
00286                         inline iterator end() { return m_feats.end(); }
00287                         inline const_iterator begin() const { return m_feats.begin(); }
00288                         inline const_iterator end() const { return m_feats.end(); }
00289 
00290                         inline reverse_iterator rbegin() { return m_feats.rbegin(); }
00291                         inline reverse_iterator rend() { return m_feats.rend(); }
00292                         inline const_reverse_iterator rbegin() const { return m_feats.rbegin(); }
00293                         inline const_reverse_iterator rend() const { return m_feats.rend(); }
00294 
00295                         inline iterator erase(const iterator it)  { mark_kdtree_as_outdated(); return m_feats.erase(it); }
00296 
00297                         inline bool empty() const  { return m_feats.empty(); }
00298                         inline size_t size() const { return m_feats.size(); }
00299 
00300                         inline void clear() { m_feats.clear(); mark_kdtree_as_outdated(); }
00301                         inline void resize(size_t N) { m_feats.resize(N); mark_kdtree_as_outdated(); }
00302 
00303                         inline void push_back(const CFeaturePtr &f) { mark_kdtree_as_outdated();  m_feats.push_back(f); }
00304 
00305                         inline CFeaturePtr & operator [](const unsigned int index) { return m_feats[index]; }
00306                         inline const CFeaturePtr & operator [](const unsigned int index) const  { return m_feats[index]; }
00307 
00308                         /** @} */
00309 
00310 
00311                         /** @name Methods that MUST be implemented by children classes of KDTreeCapable
00312                                 @{ */
00313 
00314                         /// Must return the number of data points 
00315                         inline size_t kdtree_get_point_count() const {  return this->size(); }
00316 
00317                         /// Returns the dim'th component of the idx'th point in the class:
00318                         inline float kdtree_get_pt(const size_t idx, int dim) const { 
00319                                 ASSERTDEB_(dim==0 || dim==1)
00320                                 if (dim==0) return m_feats[idx]->x;
00321                                 else return m_feats[idx]->y;
00322                         }
00323 
00324                         /// Returns the distance between the vector "p1[0:size-1]" and the data point with index "idx_p2" stored in the class:
00325                         inline float kdtree_distance(const float *p1, const size_t idx_p2,size_t size) const
00326                         {
00327                                 ASSERTDEB_(size==2)
00328 
00329                                 const float d0 = p1[0] - m_feats[idx_p2]->x; 
00330                                 const float d1 = p1[1] - m_feats[idx_p2]->y; 
00331                                 return d0*d0+d1*d1;
00332                         }
00333 
00334                         // Optional bounding-box computation: return false to default to a standard bbox computation loop. 
00335                         //   Return true if the BBOX was already computed by the class and returned in "bb" so it can be avoided to redo it again.
00336                         //   Look at bb.size() to find out the expected dimensionality (e.g. 2 or 3 for point clouds)
00337                         template <typename BBOX>
00338                         bool kdtree_get_bbox(BBOX &bb) const  { return false; }
00339 
00340                         /** @} */
00341 
00342 
00343                         /** @name getFeature*() methods for template-based access to feature list
00344                             @{ */
00345                         inline float getFeatureX(size_t i) const { return m_feats[i]->x; }
00346                         inline float getFeatureY(size_t i) const { return m_feats[i]->y; }
00347                         inline TFeatureID getFeatureID(size_t i) const { return m_feats[i]->ID; }
00348                         inline float getFeatureResponse(size_t i) const { return m_feats[i]->response; }
00349                         inline bool isPointFeature(size_t i) const { return m_feats[i]->isPointFeature(); }
00350                         inline float getScale(size_t i) const { return m_feats[i]->scale; }
00351                         inline TFeatureTrackStatus getTrackStatus(size_t i) { return m_feats[i]->track_status; }
00352 
00353                         inline void setFeatureX(size_t i,float x) { m_feats[i]->x=x; }
00354                         inline void setFeatureXf(size_t i,float x) { m_feats[i]->x=x; }
00355                         inline void setFeatureY(size_t i,float y) { m_feats[i]->y=y; }
00356                         inline void setFeatureYf(size_t i,float y) { m_feats[i]->y=y; }
00357 
00358                         inline void setFeatureID(size_t i,TFeatureID id) { m_feats[i]->ID=id; }
00359                         inline void setFeatureResponse(size_t i,float r) { m_feats[i]->response=r; }
00360                         inline void setScale(size_t i,float s) { m_feats[i]->scale=s; }
00361                         inline void setTrackStatus(size_t i,TFeatureTrackStatus s) { m_feats[i]->track_status=s; }
00362 
00363                         inline void mark_as_outdated() const { kdtree_mark_as_outdated(); }
00364 
00365                         /** @} */
00366 
00367 
00368                 }; // end of class
00369 
00370                 /****************************************************
00371                                         Class CMATCHEDFEATURELIST
00372                 *****************************************************/
00373                 /** A list of features
00374                 */
00375                 class VISION_IMPEXP CMatchedFeatureList : public std::deque< std::pair<CFeaturePtr,CFeaturePtr> >
00376                 {
00377                 public:
00378                         /** The type of the first feature in the list */
00379                         inline TFeatureType get_type() const { return empty() ? featNotDefined : (begin()->first)->get_type(); }
00380 
00381                         /** Save list of matched features to a text file */
00382                         void saveToTextFile(const std::string &fileName);
00383 
00384             /** Returns the matching features as two separate CFeatureLists */
00385                         void getBothFeatureLists( CFeatureList &list1, CFeatureList &list2 );
00386 
00387                         /** Returns a smart pointer to the feature with the provided ID or a empty one if not found */
00388                         CFeaturePtr getByID( const TFeatureID & ID, const TListIdx &idx );
00389 
00390                         /** Returns the maximum ID of the features in the list. If the max ID has been already set up, this method just returns it.
00391                             Otherwise, this method finds, stores and returns it.*/
00392                         void getMaxID( const TListIdx &idx, TFeatureID & firstListID, TFeatureID & secondListID );
00393 
00394                         /** Updates the value of the maximum ID of the features in the matched list, i.e. it explicitly searches for the max ID and updates the member variables. */
00395                         void updateMaxID( const TListIdx &idx );
00396 
00397             /** Explicitly set the max IDs values to certain values */
00398             inline void setLeftMaxID( const TFeatureID &leftID ){ m_leftMaxID = leftID; }
00399             inline void setRightMaxID( const TFeatureID &rightID ){ m_rightMaxID = rightID; }
00400                         inline void setMaxIDs( const TFeatureID &leftID, const TFeatureID &rightID )
00401             {
00402                 setLeftMaxID(leftID);
00403                 setRightMaxID(rightID);
00404             };
00405 
00406                         /** Constructor */
00407                         CMatchedFeatureList();
00408 
00409                         /** Virtual destructor */
00410                         virtual ~CMatchedFeatureList();
00411         protected:
00412             TFeatureID m_leftMaxID, m_rightMaxID;
00413                 }; // end of class
00414 
00415 
00416                 /** @} */ // End of add to module: mrptvision_features
00417 
00418         } // end of namespace
00419 
00420 
00421         namespace utils
00422         {
00423                 using namespace ::mrpt::vision;
00424                 // Specialization must occur in the same namespace
00425                 MRPT_DECLARE_TTYPENAME_PTR(CFeature)
00426         }
00427 } // end of namespace
00428 
00429 #endif
00430 



Page generated by Doxygen 1.7.5 for MRPT 0.9.5 SVN: at Thu Oct 13 21:25:36 UTC 2011