GistEstimatorSurfPMK.C

Go to the documentation of this file.
00001 /*!
00002    \file Neuro/GistEstimatorSurfPMK.C
00003 
00004    This file defines the member functions, static members, etc. of the
00005    GistEstimatorSurfPMK class. Further details are in the header file.
00006 */
00007 
00008 // //////////////////////////////////////////////////////////////////// //
00009 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00010 // by the University of Southern California (USC) and the iLab at USC.  //
00011 // See http://iLab.usc.edu for information about this project.          //
00012 // //////////////////////////////////////////////////////////////////// //
00013 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00014 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00015 // in Visual Environments, and Applications'' by Christof Koch and      //
00016 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00017 // pending; application number 09/912,225 filed July 23, 2001; see      //
00018 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00019 // //////////////////////////////////////////////////////////////////// //
00020 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00023 // redistribute it and/or modify it under the terms of the GNU General  //
00024 // Public License as published by the Free Software Foundation; either  //
00025 // version 2 of the License, or (at your option) any later version.     //
00026 //                                                                      //
00027 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00028 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00029 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00030 // PURPOSE.  See the GNU General Public License for more details.       //
00031 //                                                                      //
00032 // You should have received a copy of the GNU General Public License    //
00033 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00034 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00035 // Boston, MA 02111-1307 USA.                                           //
00036 // //////////////////////////////////////////////////////////////////// //
00037 //
00038 // Primary maintainer for this file: Manu Viswanathan <mviswana at usc dot edu>
00039 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Neuro/GistEstimatorSurfPMK.C $
00040 // $Id: GistEstimatorSurfPMK.C 13065 2010-03-28 00:01:00Z itti $
00041 //
00042 
00043 //--------------------------- LIBRARY CHECK -----------------------------
00044 
00045 #if !defined(INVT_HAVE_LIBSURF) || !defined(HAVE_OPENCV)
00046 
00047 // Gist specific headers
00048 #include "Neuro/GistEstimatorSurfPMK.H"
00049 
00050 // INVT utils
00051 #include "Util/log.H"
00052 
00053 // Dummy class definition
00054 GistEstimatorSurfPMK::
00055 GistEstimatorSurfPMK(OptionManager& mgr,
00056                      const std::string& descrName, const std::string& tagName)
00057   : GistEstimatorAdapter(mgr, descrName, tagName)
00058 {
00059    LFATAL("Sorry, GistEstimatorSurfPMK requires OpenSURF and OpenCV") ;
00060 }
00061 
00062 GistEstimatorSurfPMK::~GistEstimatorSurfPMK(){}
00063 
00064 #else // the regular SURF-PMK gist estimator in all its hideous glory
00065 
00066 //------------------------------ HEADERS --------------------------------
00067 
00068 #include "Image/OpenCVUtil.H"  // must be first to avoid conflicting defs of int64, uint64
00069 
00070 // Gist specific headers
00071 #include "Neuro/GistEstimatorSurfPMK.H"
00072 
00073 // Other INVT headers
00074 #include "Neuro/VisualCortex.H"
00075 #include "Neuro/NeuroSimEvents.H"
00076 
00077 #include "Simulation/SimEventQueue.H"
00078 
00079 #include "Image/Kernels.H"
00080 #include "Image/Convolutions.H"
00081 #include "Image/MathOps.H"
00082 #include "Image/ShapeOps.H"
00083 #include "Image/CutPaste.H"
00084 #include "Image/Point2D.H"
00085 #include "Image/Dims.H"
00086 
00087 #include "Util/Timer.H"
00088 
00089 #include "nub/ref.h"
00090 #include "rutz/shared_ptr.h"
00091 
00092 // Standard C++ headers
00093 #include <sstream>
00094 #include <numeric>
00095 #include <algorithm>
00096 #include <functional>
00097 #include <map>
00098 #include <list>
00099 #include <stdexcept>
00100 #include <utility>
00101 #include <limits>
00102 #include <ctime>
00103 
00104 //------------------------------ DEFINES --------------------------------
00105 
00106 // Error message for exceptions when vocabulary is required but not
00107 // specified.
00108 #define GE_SPMK_ERR_NO_VOCABULARY \
00109    "GistEstimatorSurfPMK requires vocabulary of " \
00110    "prototypical SURF descriptors"
00111 
00112 //----------------------------- TYPEDEFS --------------------------------
00113 
00114 // Some useful shortcuts
00115 typedef GistEstimatorSurfPMK    SurfPMK ;
00116 typedef SurfPMK::Vocabulary     Vocabulary ;
00117 typedef SurfPMK::SurfDescriptor SurfDescriptor ;
00118 typedef SurfPMK::SurfKeypoints  SurfKeypoints ;
00119 
00120 // Other frequently used types
00121 typedef float PixelType ;
00122 typedef Image<PixelType> ImageType ;
00123 typedef Image<double>    GistVectorType ;
00124 
00125 //-------------- STATIC DATA MEMBERS AND OTHER CONSTANTS ----------------
00126 
00127 const int GistEstimatorSurfPMK::GIST_VECTOR_SIZE = 200 ; // FIXME!
00128 
00129 //-------------------------- INITIALIZATION -----------------------------
00130 
00131 GistEstimatorSurfPMK::
00132 GistEstimatorSurfPMK(OptionManager& mgr,
00133                      const std::string& descrName,
00134                      const std::string& tagName)
00135    : GistEstimator(mgr, descrName, tagName),
00136      SIMCALLBACK_INIT(SimEventRetinaImage),
00137      itsTrainingHook(0)
00138 {}
00139 
00140 // Quick helper to extract the r-th row of an Image
00141 static inline ImageType get_row(int r, const ImageType& I)
00142 {
00143    return crop(I, Point2D<int>(0, r), Dims(I.getWidth(), 1)) ;
00144 }
00145 
00146 // The vocabulary is a list of SURF descriptors. But for convenience,
00147 // clients can pass it in as an image. The image must have 128 columns
00148 // (for the 128 values that make up a SURF descriptor) and will usually
00149 // have 200 rows (the size of the vocabulary). Thus, the dimensions of
00150 // the input image used to represent the SURF descriptor vocabulary in
00151 // client space will be 128x200.
00152 //
00153 // The following method simply converts this image into the list of SURF
00154 // descriptors used to represent the vocabulary internally by this class.
00155 void GistEstimatorSurfPMK::setVocabulary(const ImageType& V)
00156 {
00157    itsVocabulary.clear() ;
00158 
00159    const int H = V.getHeight() ;
00160    for (int i = 0; i < H; ++i)
00161       //itsVocabulary.push_back(SurfDescriptor(get_row(i, V))) ;
00162       itsVocabulary.push_back(SurfDescriptor()) ; // FIXME!
00163 }
00164 
00165 //----------------------------- CLEAN-UP --------------------------------
00166 
00167 GistEstimatorSurfPMK::~GistEstimatorSurfPMK(){}
00168 
00169 //------------------ GIST FEATURE VECTOR COMPUTATION --------------------
00170 
00171 // Forward declarations
00172 static SurfKeypoints apply_surf_on_image(ImageType I) ;
00173 
00174 // The processing method divides the current frame of the series of input
00175 // images into 16x16 pixel patches and computes the SURF descriptors for
00176 // each of these patches. Then, it either passes this grid of
00177 // descriptors back to its client (in training mode) or computes the
00178 // required gist vector using the supplied vocabulary of prototypical
00179 // descriptors (in normal operational mode).
00180 //
00181 // COMPLEXITY ANALYSIS: O(?) [? time]
00182 // ---------------------------------------
00183 // During normal operation (i.e., non-training mode), this function
00184 // calls apply_surf_on_patches() and flattened_multi_level_histogram().
00185 // The time complexity latter is O(n). That of the former is not yet
00186 // known as it depends on how the SURF black box will work.
00187 //
00188 // The other operations in this function are all constant time or at
00189 // worst O(n), where n is the number of pixels in the input image.
00190 // Therefore, as it stands now, the overall complexity of this function
00191 // will be determined by that of the SURF black box; if that is O(n),
00192 // then so is this; if that is O(n^2), so is this; so on and so forth.
00193 void GistEstimatorSurfPMK::
00194 onSimEventRetinaImage(SimEventQueue& q, rutz::shared_ptr<SimEventRetinaImage>& e)
00195 {
00196    Timer T ;
00197    ImageType current_frame = e->frame().grayFloat() ;
00198    SurfKeypoints surf_descriptors = apply_surf_on_image(current_frame) ;
00199    LINFO("MVN: %g seconds to compute SURF grid", T.getSecs()) ;
00200    if (itsTrainingHook)
00201      itsTrainingHook(surf_descriptors) ;
00202    else
00203      {
00204        if (itsVocabulary.empty())
00205          throw std::runtime_error(GE_SPMK_ERR_NO_VOCABULARY) ;
00206 
00207        T.reset() ;
00208        //itsGistVector =
00209        //flattened_multi_level_histogram(surf_descriptors, itsVocabulary) ;
00210        LINFO("MVN: %g seconds to compute %dx%d gist vector", T.getSecs(),
00211              itsGistVector.getHeight(), itsGistVector.getWidth()) ;
00212      }
00213 
00214    rutz::shared_ptr<SimEventGistOutput>
00215      gist_output_event(new SimEventGistOutput(this, itsGistVector)) ;
00216    q.post(gist_output_event) ;
00217 }
00218 
00219 //---------------------- INPUT IMAGE FILTERATION ------------------------
00220 
00221 // A quick helper to convert INVT images to IPL images and properly
00222 // release the IPL images when we're done with them. This is essentially
00223 // a convenience class whose constructor does the conversion and whose
00224 // destructor takes care of releasing the IPL data structures so that
00225 // client functions don't have to worry about these details.
00226 namespace {
00227 
00228 class IplImg {
00229    IplImage* img ;
00230 public:
00231    IplImg(Image<float>&) ;
00232    ~IplImg() ;
00233    operator IplImage*() const {return img ;} // cast operator
00234 } ;
00235 
00236 // Constructor to create float images
00237 IplImg::IplImg(Image<float>& I)
00238    : img(cvCreateImageHeader(cvSize(I.getWidth(), I.getHeight()),
00239                              IPL_DEPTH_32F, 1))
00240 {
00241    if (! img)
00242       throw std::runtime_error("IplImage init error") ;
00243    img->imageData = reinterpret_cast<char*>(I.getArrayPtr()) ;
00244 }
00245 
00246 // Release the OpenCV resources created by constructor
00247 IplImg::~IplImg()
00248 {
00249    cvReleaseImageHeader(& img) ;
00250 }
00251 
00252 } // end of local namespace encapsulating above helper
00253 
00254 /*
00255 
00256    COMPLEXITY ANALYSIS: O(?) [linear time]
00257    ---------------------------------------
00258 */
00259 static SurfKeypoints apply_surf_on_image(ImageType I)
00260 {
00261    return opensurf::doSurf(IplImg(I)) ;
00262 }
00263 
00264 //---------------------- HISTOGRAM COMPUTATIONS -------------------------
00265 
00266 namespace {
00267 
00268 } // end of local namespace encapsulating histogram computations section
00269 
00270 //---------------------- MISCELLANEOUS FUNCTIONS ------------------------
00271 
00272 // Stream I/O for SURF descriptors
00273 std::ostream& operator<<(std::ostream& os, const SurfDescriptor& d)
00274 {
00275    for (int i = 0; i < GistEstimatorSurfPMK::SURF_DESCRIPTOR_SIZE; ++i)
00276       os << d.descriptor[i] << ' ' ;
00277    return os ;
00278 }
00279 
00280 //-----------------------------------------------------------------------
00281 
00282 #endif // #if !defined(INVT_HAVE_LIBSURF) || !defined(HAVE_OPENCV)
00283 
00284 /* So things look consistent in everyone's emacs... */
00285 /* Local Variables: */
00286 /* indent-tabs-mode: nil */
00287 /* End: */
Generated on Sun May 8 08:41:03 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3