00001 /*!@file Channels/Jet.H a simple jet (i.e., cortical hypercolumn) */ 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: Laurent Itti <itti@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Channels/Jet.H $ 00035 // $Id: Jet.H 6990 2006-08-11 18:13:51Z rjpeters $ 00036 // 00037 00038 #ifndef JET_H_DEFINED 00039 #define JET_H_DEFINED 00040 00041 #include "Util/Assert.H" 00042 #include "Util/Types.H" 00043 #include "Channels/VisualFeatures.H" 00044 #include "Util/Promotions.H" 00045 #include "Util/log.H" 00046 #include "rutz/shared_ptr.h" 00047 #include <cstdarg> 00048 #include <vector> 00049 00050 template <class T> class Image; 00051 00052 // ###################################################################### 00053 //! This class specifies the features, scales and indices represented in a Jet 00054 /*! A Jet object requires a valid JetSpec object at construction */ 00055 class JetSpec 00056 { 00057 public: 00058 /*! @name Constructors, destructor and operators */ 00059 //@{ 00060 00061 //! Empty constructor; starts with an empty specification 00062 JetSpec(); 00063 00064 //! Copy constructor 00065 JetSpec(const JetSpec& js); 00066 00067 //! Assignment operator 00068 JetSpec& operator=(const JetSpec& js); 00069 00070 //! Free all allocated memory and un-initialize 00071 void freeMem(); 00072 00073 //! Destructor 00074 ~JetSpec(); 00075 //@} 00076 00077 /*! @name Build methods */ 00078 //@{ 00079 //! Add a new feature; returns true on success 00080 bool addFeature(const VisualFeature f); 00081 00082 //! Add a new representation type for an existing feature; true on success 00083 bool addFeatureType(const VisualFeature f, const VisualFeatureType t); 00084 00085 //! Add a new index range for existing feature and type; true on success 00086 /*! Valid indices will be in [indexmin..indexmax] inclusive on both sides. */ 00087 bool addIndexRange(const VisualFeature f, const VisualFeatureType t, 00088 const int indexmin, const int indexmax); 00089 //@} 00090 00091 /*! @name Access methods */ 00092 //@{ 00093 //! Get the number of components in a jet with our specs 00094 inline int getJetSize() const; 00095 00096 //! Query whether we have some representation for given feature 00097 inline bool hasFeature(const VisualFeature f) const; 00098 00099 //! Query whether we have some representation for given feature/type 00100 inline bool hasFeatureType(const VisualFeature f, 00101 const VisualFeatureType t) const; 00102 00103 //! Get index of first Jet element for given feature & type 00104 /*! Also returns the total size allocated in the Jet for this feature 00105 and type */ 00106 inline int getIndexBase(const VisualFeature f, const VisualFeatureType t, 00107 int& siz) const; 00108 00109 //! Get number of index ranges 00110 inline int getNbIndexRanges(const VisualFeature f, 00111 const VisualFeatureType t) const; 00112 00113 //! Get an index range; true if range exists in JetSpec 00114 inline bool getIndexRange(const VisualFeature f, const VisualFeatureType t, 00115 const int idxnum, int& idxmin, int& idxmax) const; 00116 00117 //! Debugging printout to stdout 00118 void print() const; 00119 00120 //@} 00121 00122 /*! @name Jet data access methods */ 00123 //@{ 00124 //! Get index in Jet array data for given feature, type and set of indices 00125 /*! The ... arguments should be as many ints as we have have 00126 addIndexRange()'d when building the JetSpec, and their values 00127 should be within the ranges specified at the time of 00128 addIndexRange(). Returns -1 if feature or type unknown or if any 00129 of the indices is out of range. */ 00130 inline int getIndex(const VisualFeature f, 00131 const VisualFeatureType t, ...) const; 00132 00133 //! getIndex() with va_list parameters 00134 inline int getIndexA(const VisualFeature f, const VisualFeatureType t, 00135 va_list& a) const; 00136 00137 //! getIndex() with vector of parameters 00138 inline int getIndexV(const VisualFeature f, const VisualFeatureType t, 00139 const std::vector<int>& v) const; 00140 //@} 00141 00142 private: 00143 //! Chained list element that holds index range defs for given feature type 00144 struct JFT { 00145 VisualFeatureType ftype; //!< feature type 00146 int indexBase; //!< index in Jet of first data element 00147 int siz; //!< total number of elements 00148 int nbidx; //!< number of indices 00149 int *idxmin; //!< minimum index value 00150 int *idxmax; //!< max index val; valid range: idxmin<=i<idxmax 00151 JFT *next; //!< pointer to next feature type for that feature 00152 }; 00153 00154 //! chained list element that holds JTF definitions for given feature 00155 struct JF { 00156 VisualFeature feature; //!< feature 00157 JFT *jft; //!< pointer to list of feature types 00158 JF *next; //!< pointer to next feature in this specification 00159 }; 00160 00161 JF *spec; //!< Specification as tree of JF's holding JFT's 00162 00163 //! accelerated access to individula feature/type defs 00164 JFT *dataIdx[NBVISUALFEATURES][NBVISUALFEATURETYPES]; 00165 int jetSize; //!< size of a Jet using our specs 00166 00167 //! update our accelerated access array in dataIdx 00168 void updateDataIdx(); 00169 }; 00170 00171 00172 // ###################################################################### 00173 //! This class specifies a Jet, i.e., array of feature values for one location 00174 /*! The features represented in the Jet are defined by a JetSpec 00175 object that must be passed at construction of the Jet. Jet extends 00176 Image and inherits all of its functionality. The JetSpec is passed as 00177 a rutz::shared_ptr, so that the original can run out of scope and be 00178 destroyed (and the actual data will be freed upon destruction of the 00179 last Jet built from that JetSpec). */ 00180 00181 template <class T> 00182 class Jet : public Image<T> { 00183 public: 00184 /*! @name Constructors, initialization and destructor */ 00185 //@{ 00186 //! Constructor; must provide a fully-configured JetSpec 00187 Jet(const rutz::shared_ptr<JetSpec> js); 00188 00189 //! Uninitialized constructor (for arrays of Jets) 00190 Jet(); 00191 00192 //! Initialization of an uninitialized Jet 00193 void init(const rutz::shared_ptr<JetSpec> js); 00194 00195 //! Load from an Image, presenving our JetSpec 00196 /*! The Jet must have been initialized previously and its size must 00197 match that of the Image. This is potentially dangerous, and mostly 00198 provided so that we can inherit all of the Image free functions 00199 that return images (e.g., those of Image_MathOps.H). This is a 00200 cheap operation thanks to the copy-on-write/ref-counting */ 00201 inline Jet<T>& operator=(const Image<T>& img); 00202 00203 //! Load from an image, preserving our JetSpec and doing a clamped convert 00204 /*! The Jet must have been initialized previously and its size must 00205 match that of the Image. This is potentially dangerous, and mostly 00206 provided so that we can inherit all of the Image free functions 00207 that return images (e.g., those of Image_MathOps.H). This is an 00208 expensive operation in which we convert each pixel in turn. */ 00209 template <class TT> inline Jet<T>& operator=(const Image<TT>& img); 00210 00211 //! Destructor 00212 ~Jet(); 00213 //@} 00214 00215 /*! @name Access functions */ 00216 //@{ 00217 //! Get a value, for given feature, type and indices 00218 inline T getVal(const VisualFeature f, const VisualFeatureType t, ...) const; 00219 00220 //! Get a value, for given feature, type and vector of indices 00221 inline T getValV(const VisualFeature f, const VisualFeatureType t, 00222 const std::vector<int>& v) const; 00223 00224 //! Get a value by absolute index in the Jet array. Use with caution! 00225 inline T getVal(const int idx) const; 00226 00227 //! Set a value, for given feature, type and indices 00228 inline void setVal(const T& val, const VisualFeature f, 00229 const VisualFeatureType t, ...); 00230 00231 //! Set a value, for given feature, type and vector of indices 00232 inline void setValV(const T& val, const VisualFeature f, 00233 const VisualFeatureType t, const std::vector<int>& v); 00234 00235 //! Set a value by absolute index in the Jet array. Use with caution! 00236 inline void setVal(const int idx, const T& val); 00237 00238 //! Retrieve the JetSpec in case your original has run out of scope 00239 inline rutz::shared_ptr<JetSpec> getSpec() const; 00240 //@} 00241 00242 /*! @name Convenience JetSpec Access Methods */ 00243 //@{ 00244 //! Query whether we have some representation for given feature 00245 inline bool hasFeature(const VisualFeature f) const; 00246 00247 //! Query whether we have some representation for given feature/type 00248 inline bool hasFeatureType(const VisualFeature f, 00249 const VisualFeatureType t) const; 00250 00251 //! Get index of first Jet element for given feature & type 00252 /*! Also returns total size allocated in the Jet for this feature/type */ 00253 inline int getIndexBase(const VisualFeature f, 00254 const VisualFeatureType t, int& siz) const; 00255 00256 //! Get number of index ranges 00257 inline int getNbIndexRanges(const VisualFeature f, 00258 const VisualFeatureType t) const; 00259 00260 //! Get an index range; true if range exists in JetSpec 00261 inline bool getIndexRange(const VisualFeature f, const VisualFeatureType t, 00262 const int idxnum, int& idxmin, int& idxmax) const; 00263 //@} 00264 00265 private: 00266 rutz::shared_ptr<JetSpec> spec; 00267 }; 00268 00269 // ###################################################################### 00270 //! Compute distance between two Jets like Rao et al., Vis Res, 2002 00271 double raodistance(const Jet<float>& j1, const Jet<float>& j2, 00272 const int idxmin, const int idxmax); 00273 00274 // ###################################################################### 00275 template <class Stream, class T> 00276 inline Stream& operator<<(Stream& s, const Jet<T> &j) 00277 { 00278 int siz = j.getSize(); 00279 for (int i = 0; i < siz; i ++) s<<j.Image<T>::getVal(i)<<' '; 00280 return s; 00281 } 00282 00283 // ###################################################################### 00284 template <class Stream, class T> 00285 inline Stream& operator>>(Stream& s, Jet<T> &j) 00286 { 00287 int siz = j.getSize(); float x; 00288 for (int i = 0; i < siz; i ++) { s>>x; j.Image<T>::setVal(i, x); } 00289 return s; 00290 } 00291 00292 // ###################################################################### 00293 // ###################################################################### 00294 // ########## INLINED METHODS for JetSpec: 00295 // ###################################################################### 00296 // ###################################################################### 00297 00298 // ###################################################################### 00299 inline int JetSpec::getJetSize() const 00300 { return jetSize; } 00301 00302 // ###################################################################### 00303 inline bool JetSpec::hasFeature(const VisualFeature f) const 00304 { 00305 JF *jfp = spec; 00306 while(jfp) if (jfp->feature == f) return true; else jfp = jfp->next; 00307 return false; 00308 } 00309 00310 // ###################################################################### 00311 inline bool JetSpec::hasFeatureType(const VisualFeature f, 00312 const VisualFeatureType t) const 00313 { return (dataIdx[f][t] != NULL); } 00314 00315 // ###################################################################### 00316 inline int JetSpec::getIndexBase(const VisualFeature f, 00317 const VisualFeatureType t, int& siz) const 00318 { 00319 ASSERT(dataIdx[f][t]); 00320 siz = dataIdx[f][t]->siz; 00321 return dataIdx[f][t]->indexBase; 00322 } 00323 00324 // ###################################################################### 00325 inline int JetSpec::getNbIndexRanges(const VisualFeature f, 00326 const VisualFeatureType t) const 00327 { 00328 ASSERT(dataIdx[f][t]); 00329 return dataIdx[f][t]->nbidx; 00330 } 00331 00332 // ###################################################################### 00333 inline bool JetSpec::getIndexRange(const VisualFeature f, 00334 const VisualFeatureType t, 00335 const int idxnum, int& idxmin, 00336 int& idxmax) const 00337 { 00338 if (dataIdx[f][t] == NULL || idxnum < 0 || idxnum >= dataIdx[f][t]->nbidx) 00339 return false; 00340 idxmin = dataIdx[f][t]->idxmin[idxnum]; 00341 idxmax = dataIdx[f][t]->idxmax[idxnum]; 00342 return true; 00343 } 00344 00345 // ###################################################################### 00346 inline int JetSpec::getIndex(const VisualFeature f, const VisualFeatureType t, 00347 ...) const 00348 { 00349 va_list a; va_start(a, t); int idx = getIndexA(f, t, a); va_end(a); 00350 return idx; 00351 } 00352 00353 // ###################################################################### 00354 inline int JetSpec::getIndexA(const VisualFeature f, 00355 const VisualFeatureType t, va_list& a) const 00356 { 00357 // do a rapid fetch of data for given feature & type: 00358 JFT *jftp = dataIdx[f][t]; 00359 if (jftp == NULL) { 00360 LERROR("Unknown feature/type: %s/%s", featureName(f), featureTypeName(t)); 00361 return -1; 00362 } 00363 00364 // FIXME: how can we check that the number of va_args matches the 00365 // number of indices? 00366 00367 // add offset according to parameters passed by caller: 00368 int index = 0; 00369 for (int i = 0; i < jftp->nbidx; i ++) { 00370 int arg = va_arg(a, int); 00371 if (arg < jftp->idxmin[i] || arg > jftp->idxmax[i]) 00372 { LERROR("Index %d value %d out of range [%d..%d]", i, arg, 00373 jftp->idxmin[i], jftp->idxmax[i]); return -1; } 00374 index = index * (jftp->idxmax[i] - jftp->idxmin[i] + 1) + 00375 (arg - jftp->idxmin[i]); 00376 } 00377 return index + jftp->indexBase; 00378 } 00379 00380 // ###################################################################### 00381 inline int JetSpec::getIndexV(const VisualFeature f, const VisualFeatureType t, 00382 const std::vector<int>& v) const 00383 { 00384 // do a rapid fetch of data for given feature & type: 00385 JFT *jftp = dataIdx[f][t]; 00386 if (jftp == NULL) { 00387 LERROR("Unknown feature/type: %s/%s", featureName(f), featureTypeName(t)); 00388 return -1; 00389 } 00390 00391 // check that caller passed right number of indices: 00392 if (int(v.size()) != jftp->nbidx) { 00393 LERROR("Passed %"ZU" indices but %s/%s has %d", v.size(), 00394 featureName(f), featureTypeName(t), jftp->nbidx); 00395 return -1; 00396 } 00397 00398 //std::cout<<featureName(f)<<'/'<<featureTypeName(t)<<"[ "; 00399 //for (int i = 0; i < v.size(); i ++) std::cout<<v[i]<<' '; 00400 00401 // add offset according to parameters passed by caller: 00402 int index = 0; 00403 for (int i = 0; i < jftp->nbidx; i ++) { 00404 int arg = v[i]; 00405 if (arg < jftp->idxmin[i] || arg > jftp->idxmax[i]) 00406 { LERROR("Index %d value %d out of range [%d..%d]", i, arg, 00407 jftp->idxmin[i], jftp->idxmax[i]); return -1; } 00408 index = index * (jftp->idxmax[i] - jftp->idxmin[i] + 1) + 00409 (arg - jftp->idxmin[i]); 00410 } 00411 00412 //std::cout<<"] = "<<index + jftp->indexBase<<std::endl; 00413 00414 return index + jftp->indexBase; 00415 } 00416 00417 00418 // ###################################################################### 00419 // ###################################################################### 00420 // ########## INLINED METHODS for Jet: 00421 // ###################################################################### 00422 // ###################################################################### 00423 00424 // ###################################################################### 00425 template <class T> inline 00426 Jet<T>& Jet<T>::operator=(const Image<T>& img) 00427 { 00428 ASSERT(isSameSize(img)); 00429 Image<T> A_copy(img); 00430 this->swap(A_copy); 00431 return *this; 00432 } 00433 00434 // ###################################################################### 00435 template <class T> template <class TT> inline 00436 Jet<T>& Jet<T>::operator=(const Image<TT>& img) 00437 { 00438 ASSERT(isSameSize(img)); 00439 Image<T>::operator=(img); return *this; 00440 } 00441 00442 // ###################################################################### 00443 template <class T> inline 00444 T Jet<T>::getVal(const VisualFeature f, const VisualFeatureType t, ...) const 00445 { 00446 00447 va_list a; va_start(a, t); int idx = spec->getIndexA(f, t, a); va_end(a); 00448 return Image<T>::getVal(idx); 00449 } 00450 00451 // ###################################################################### 00452 template <class T> inline 00453 T Jet<T>::getValV(const VisualFeature f, const VisualFeatureType t, 00454 const std::vector<int>& v) const 00455 { 00456 int idx = spec->getIndexV(f, t, v); 00457 return Image<T>::getVal(idx); 00458 } 00459 00460 // ###################################################################### 00461 template <class T> inline 00462 T Jet<T>::getVal(const int idx) const 00463 { return this->begin()[idx]; } 00464 00465 // ###################################################################### 00466 template <class T> inline 00467 void Jet<T>::setVal(const T& val, const VisualFeature f, 00468 const VisualFeatureType t, ...) 00469 { 00470 va_list a; va_start(a, t); 00471 setVal(spec->getIndexA(f, t, a), val); 00472 va_end(a); 00473 } 00474 00475 // ###################################################################### 00476 template <class T> inline 00477 void Jet<T>::setValV(const T& val, const VisualFeature f, 00478 const VisualFeatureType t, const std::vector<int>& v) 00479 { 00480 setVal(spec->getIndexV(f, t, v), val); 00481 } 00482 00483 // ###################################################################### 00484 template <class T> inline 00485 void Jet<T>::setVal(const int idx, const T& val) 00486 { this->beginw()[idx] = val; } 00487 00488 // ###################################################################### 00489 template <class T> inline 00490 rutz::shared_ptr<JetSpec> Jet<T>::getSpec() const 00491 { return spec; } 00492 00493 // ###################################################################### 00494 template <class T> inline 00495 bool Jet<T>::hasFeature(const VisualFeature f) const 00496 { return spec->hasFeature(f); } 00497 00498 // ###################################################################### 00499 template <class T> inline 00500 bool Jet<T>::hasFeatureType(const VisualFeature f, 00501 const VisualFeatureType t) const 00502 { return spec->hasFeatureType(f, t); } 00503 00504 // ###################################################################### 00505 template <class T> inline 00506 int Jet<T>::getIndexBase(const VisualFeature f, const VisualFeatureType t, 00507 int& siz) const 00508 { return spec->getIndexBase(f, t, siz); } 00509 00510 00511 // ###################################################################### 00512 template <class T> inline 00513 int Jet<T>::getNbIndexRanges(const VisualFeature f, 00514 const VisualFeatureType t) const 00515 { return spec->getNbIndexRanges(f, t); } 00516 00517 00518 // ###################################################################### 00519 template <class T> inline 00520 bool Jet<T>::getIndexRange(const VisualFeature f, const VisualFeatureType t, 00521 const int idxnum, int& idxmin, int& idxmax) const 00522 { return spec->getIndexRange(f, t, idxnum, idxmin, idxmax); } 00523 00524 #endif 00525 00526 // ###################################################################### 00527 /* So things look consistent in everyone's emacs... */ 00528 /* Local Variables: */ 00529 /* indent-tabs-mode: nil */ 00530 /* End: */