00001 /*!@file SIFT/Keypoint.H Keypoint for SIFT obj recognition */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00005 // University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: James Bonaiuto <bonaiuto@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/SIFT/Keypoint.H $ 00035 // $Id: Keypoint.H 10462 2008-11-20 06:36:31Z rand $ 00036 // 00037 00038 #ifndef KEYPOINT_H_DEFINED 00039 #define KEYPOINT_H_DEFINED 00040 00041 #include "Component/ModelManager.H" 00042 #include "Raster/Raster.H" 00043 #include "Util/Types.H" 00044 #include "Util/Assert.H" 00045 #include "rutz/shared_ptr.h" 00046 #include <vector> 00047 #include <iosfwd> 00048 00049 // ######################################################################## 00050 //! The keypoint base class 00051 // ######################################################################## 00052 /*! The sift keypoint feature descriptor 00053 3D position (x, y, scale) 00054 Mean orientation, magnitude 00055 Feature vector */ 00056 class Keypoint 00057 { 00058 public: 00059 enum CHANNEL {ORI, COL}; 00060 // ###################################################################### 00061 /*! @name Constructors, destructor, copy, assigment */ 00062 //@{ 00063 00064 //! Uninitialized constructor; will net to call reset() later 00065 Keypoint(); 00066 00067 //! Constructor 00068 Keypoint(const std::vector<byte>& features, const float x, const float y, 00069 const float s, const float o, const float dogmag); 00070 00071 //! Constructor with Color 00072 Keypoint(const std::vector<byte>& features, 00073 const std::vector<byte>& colFeatures, 00074 const float x, const float y, 00075 const float s, const float o, const float dogmag, 00076 float oriWeight=1.0F, float colWeight=1.0F); 00077 00078 //! Copy-constructor 00079 Keypoint(const Keypoint& k); 00080 00081 //! Reset all internal values 00082 void reset(const std::vector<byte>& features, 00083 const float x, const float y, 00084 const float s, const float o, const float dogmag); 00085 00086 //! Destructor 00087 ~Keypoint(); 00088 00089 //! Assignment 00090 Keypoint& operator=(const Keypoint& k); 00091 00092 //@} 00093 00094 // ###################################################################### 00095 /*! @name Iterators and access functions 00096 The iterators iterate on our feature vector data only, while the 00097 other access functions can be used to access the other data. */ 00098 00099 //@{ 00100 00101 //! standard iterator 00102 typedef std::vector<byte>::iterator iterator; 00103 00104 //! const iterator 00105 typedef std::vector<byte>::const_iterator const_iterator; 00106 00107 //! Returns a read-only iterator to the beginning of the feature vec data 00108 inline const_iterator begin(CHANNEL channel=ORI) const; 00109 00110 //! Returns a read-only iterator to one-past-the-end of the feature vec data 00111 inline const_iterator end(CHANNEL channel=ORI) const; 00112 00113 //! Returns a read-write iterator to the beginning of the feature vec data 00114 inline iterator beginw(CHANNEL channel=ORI); 00115 00116 //! Returns a read-write iterator to one-past-the-end of the feature vec data 00117 inline iterator endw(CHANNEL channel=ORI); 00118 00119 //! x getter 00120 inline float getX() const; 00121 00122 //! y getter 00123 inline float getY() const; 00124 00125 //! scale getter 00126 inline float getS() const; 00127 00128 //! orientation getter 00129 inline float getO() const; 00130 00131 //! DoG magnitude getter 00132 inline float getM() const; 00133 00134 //! Return the length of this keypoint's feature vector 00135 inline uint getFVlength(CHANNEL channel=ORI) const; 00136 00137 //! Return the value of the feature vector at the given index 00138 inline byte getFVelement(const uint index, CHANNEL channel=ORI) const; 00139 00140 //! Return a copy of the orientation feature vector 00141 inline std::vector<byte> getOriFV() { return itsOriFV; }; 00142 00143 //! Return a copy of the color feature vector 00144 inline std::vector<byte> getColFV() { return itsColFV; }; 00145 //@} 00146 00147 // ###################################################################### 00148 /*! Comparisons and feature distance computation */ 00149 //@{ 00150 00151 //! Compute squared distance between two keypoint descriptors 00152 inline int distSquared(const rutz::shared_ptr<Keypoint>& k) const; 00153 00154 //! Return the maximum possible dist sq between two feature vectors 00155 /*! This is just a function of the size of our feature vector */ 00156 inline int maxDistSquared(CHANNEL channel=ORI) const; 00157 00158 //! Compares the magnitude of this keypoint to the given keypoint 00159 /*! This is useful, for example, to use std::sort() on an 00160 std::vector< rutz::shared_ptr<Keypoint> >. Just remember that the 00161 comparison is based on the magnitude of the DoG only, not on any 00162 other internal data of the Keypoint. */ 00163 inline bool operator<(const Keypoint& k) const; 00164 00165 00166 //@} 00167 00168 protected: 00169 float itsX; //!< our x coordinate 00170 float itsY; //!< our y coordinate 00171 float itsS; //!< our scale coordinate 00172 float itsO; //!< our orientation 00173 float itsM; //!< our DoG magnitude, for sorting 00174 std::vector<byte> itsOriFV; //!< our Ori feature vector 00175 std::vector<byte> itsColFV; //!< our color feature vector 00176 float itsOriWeight; //!< The weight for ori 00177 float itsColWeight; //!< The weight for col 00178 00179 00180 private: 00181 friend std::istream& operator>>(std::istream& is, Keypoint& k); 00182 friend std::ostream& operator<<(std::ostream& os, const Keypoint& k); 00183 }; 00184 00185 // ###################################################################### 00186 // Keypoint I/O: 00187 // ###################################################################### 00188 00189 //! Load a Keypoint from an istream 00190 std::istream& operator>>(std::istream& is, Keypoint& k); 00191 00192 //! Save a Keypoint to an ostream 00193 std::ostream& operator<<(std::ostream& os, const Keypoint& k); 00194 00195 // ###################################################################### 00196 // Inlined member functions 00197 // ###################################################################### 00198 inline Keypoint::const_iterator Keypoint::begin(CHANNEL channel) const 00199 { 00200 switch (channel){ 00201 case ORI: 00202 return itsOriFV.begin(); 00203 case COL: 00204 return itsColFV.begin(); 00205 default: 00206 return itsOriFV.begin(); //default 00207 } 00208 } 00209 00210 inline Keypoint::const_iterator Keypoint::end(CHANNEL channel) const 00211 { 00212 switch (channel){ 00213 case ORI: 00214 return itsOriFV.end(); 00215 case COL: 00216 return itsColFV.end(); 00217 default: 00218 return itsOriFV.end(); //default 00219 } 00220 } 00221 00222 //TODO: should these be beginw and endw? 00223 inline Keypoint::iterator Keypoint::beginw(CHANNEL channel) 00224 { 00225 switch (channel){ 00226 case ORI: 00227 return itsOriFV.begin(); 00228 case COL: 00229 return itsColFV.begin(); 00230 default: 00231 return itsOriFV.begin(); //default 00232 } 00233 } 00234 00235 inline Keypoint::iterator Keypoint::endw(CHANNEL channel) 00236 { 00237 switch (channel){ 00238 case ORI: 00239 return itsOriFV.end(); 00240 case COL: 00241 return itsColFV.end(); 00242 default: 00243 return itsOriFV.end(); //default 00244 } 00245 } 00246 00247 ///////////////////// Color FV access /////////////////////////// 00248 inline float Keypoint::getX() const 00249 { return itsX; } 00250 00251 inline float Keypoint::getY() const 00252 { return itsY; } 00253 00254 inline float Keypoint::getS() const 00255 { return itsS; } 00256 00257 inline float Keypoint::getO() const 00258 { return itsO; } 00259 00260 inline float Keypoint::getM() const 00261 { return itsM; } 00262 00263 inline uint Keypoint::getFVlength(CHANNEL channel) const 00264 { 00265 switch (channel){ 00266 case ORI: 00267 return itsOriFV.size(); 00268 case COL: 00269 return itsColFV.size(); 00270 default: 00271 return itsOriFV.size(); //default 00272 } 00273 } 00274 00275 inline byte Keypoint::getFVelement(const uint index,CHANNEL channel) const 00276 { 00277 switch (channel){ 00278 case ORI: 00279 ASSERT(index < itsOriFV.size()); 00280 return itsOriFV[index]; 00281 case COL: 00282 ASSERT(index < itsColFV.size()); 00283 return itsColFV[index]; 00284 default: 00285 ASSERT(index < itsOriFV.size()); 00286 return itsOriFV[index]; 00287 } 00288 } 00289 00290 inline int Keypoint::distSquared(const rutz::shared_ptr<Keypoint>& k) const 00291 { 00292 int oriDistsq = 0; 00293 int colDistsq = 0; 00294 00295 ASSERT(itsOriFV.size() == k->itsOriFV.size()); 00296 if (itsColFV.size() > 0) 00297 ASSERT(itsColFV.size() == k->itsColFV.size()); 00298 00299 Keypoint::const_iterator oriF1 = begin(ORI), oriF2 = k->begin(ORI), 00300 oriStop = end(ORI); 00301 00302 while(oriF1 != oriStop) 00303 { 00304 const int of1 = int(*oriF1++); 00305 const int of2 = int(*oriF2++); 00306 const int dif = of1 - of2; 00307 oriDistsq += dif * dif; 00308 } 00309 00310 if (itsColFV.size() > 0) { 00311 Keypoint::const_iterator colF1 = begin(COL), colF2 = k->begin(COL), 00312 colStop = end(COL); 00313 while(colF1 != colStop) 00314 { 00315 const int dif = int(*colF1++) - int(*colF2++); 00316 colDistsq += dif * dif; 00317 } 00318 } 00319 00320 return int(itsOriWeight*float(oriDistsq) + itsColWeight*float(colDistsq)); 00321 // return oriDistsq + colDistsq; 00322 } 00323 00324 inline int Keypoint::maxDistSquared(CHANNEL channel) const 00325 { 00326 switch (channel){ 00327 case ORI: 00328 return 255 * 255 * itsOriFV.size(); 00329 case COL: 00330 return 255 * 255 * itsColFV.size(); 00331 default: 00332 return 255 * 255 * itsOriFV.size(); 00333 } 00334 } 00335 00336 inline bool Keypoint::operator<(const Keypoint& k) const 00337 { return (itsM < k.itsM); } 00338 00339 #endif 00340 00341 // ###################################################################### 00342 /* So things look consistent in everyone's emacs... */ 00343 /* Local Variables: */ 00344 /* indent-tabs-mode: nil */ 00345 /* End: */