00001 /** @file Psycho/GaborPatch.C represent the physical parameters of a gabor patch */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00005 // by the 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: Rob Peters <rjpeters at usc dot edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Psycho/GaborPatch.C $ 00035 // $Id: GaborPatch.C 9078 2007-12-11 21:11:45Z rjpeters $ 00036 // 00037 00038 // Code herein is derived from GroovX, also licensed under the GPL 00039 // Copyright (c) 2002-2004 California Institute of Technology 00040 // Copyright (c) 2004-2007 University of Southern California 00041 // [http://ilab.usc.edu/rjpeters/groovx/] 00042 00043 #ifndef PSYCHO_GABORPATCH_C_DEFINED 00044 #define PSYCHO_GABORPATCH_C_DEFINED 00045 00046 #include "Psycho/GaborPatch.H" 00047 #include "Image/geom.h" 00048 00049 #include <map> 00050 00051 namespace 00052 { 00053 typedef std::map<GaborSpec, GaborPatch*> MapType; 00054 MapType theMap; 00055 00056 const int NUM_THETA = 64; 00057 const int NUM_PHASE = 8; 00058 const double DELTA_THETA = M_PI / NUM_THETA; 00059 const double DELTA_PHASE = 2 * M_PI / NUM_PHASE; 00060 } 00061 00062 GaborSpec::GaborSpec(double s, double o, double t, double p) : 00063 theta(DELTA_THETA * (int(geom::rad_0_pi(t)/DELTA_THETA + 0.5) % NUM_THETA)), 00064 phi(DELTA_PHASE * (int(geom::rad_0_2pi(p)/DELTA_PHASE + 0.5) % NUM_PHASE)), 00065 sigma(s), 00066 omega(o) 00067 {} 00068 00069 bool GaborSpec::operator<(const GaborSpec& x) const 00070 { 00071 if (theta < x.theta) return true; 00072 else if (theta == x.theta) 00073 { 00074 if (phi < x.phi) return true; 00075 else if (phi == x.phi) 00076 { 00077 if (sigma < x.sigma) return true; 00078 else if (sigma == x.sigma) 00079 { 00080 return (omega < x.omega); 00081 } 00082 } 00083 } 00084 00085 return false; 00086 } 00087 00088 GaborPatch::GaborPatch(const GaborSpec& spec) 00089 : 00090 itsSpec ( spec ), 00091 itsSize ( int(8*spec.sigma + 0.5) ), 00092 itsCenter ( itsSize/2.0 + 0.5 ), 00093 itsCosTheta ( cos(spec.theta) ), 00094 itsSinTheta ( sin(spec.theta) ), 00095 itsSigmaSqr ( 2.0* spec.sigma * spec.sigma ), 00096 itsData ( itsSize, itsSize, ZEROS ) 00097 { 00098 Image<double>::iterator ptr = itsData.beginw(); 00099 00100 for (int y = 0; y < itsSize; ++y) 00101 for (int x = 0; x < itsSize; ++x) 00102 { 00103 const double fy = y - itsCenter; 00104 const double fx = x - itsCenter; 00105 00106 const double dx = itsCosTheta * fx - itsSinTheta * fy; 00107 const double dy = itsSinTheta * fx + itsCosTheta * fy; 00108 00109 const double dsqr = (dx*dx + dy*dy) / itsSigmaSqr; 00110 00111 const double sinus = cos(itsSpec.omega * dx + itsSpec.phi); 00112 00113 const double gauss = exp(-dsqr); 00114 *ptr++ = sinus * gauss; 00115 } 00116 } 00117 00118 GaborPatch::~GaborPatch() 00119 {} 00120 00121 const GaborPatch& GaborPatch::lookup(const GaborSpec& spec) 00122 { 00123 GaborPatch*& patch = theMap[spec]; 00124 00125 if (patch == 0) 00126 patch = new GaborPatch(spec); 00127 00128 return *patch; 00129 } 00130 00131 const GaborPatch& GaborPatch::lookup(double sigma, double omega, 00132 double theta, double phi) 00133 { 00134 GaborSpec spec(sigma, omega, theta, phi); 00135 00136 return lookup(spec); 00137 } 00138 00139 GaborPatchItem::GaborPatchItem() 00140 {} 00141 00142 GaborPatchItem::~GaborPatchItem() 00143 {} 00144 00145 Image<double> GaborPatchItem::getPatch() const 00146 { 00147 const GaborPatch& p = 00148 GaborPatch::lookup(itsSigma, 2*M_PI/itsPeriod, 00149 this->theta, this->phi); 00150 00151 return p.image(this->contrast); 00152 } 00153 00154 GaborPatchItemFactory::GaborPatchItemFactory(int thetaSeed, 00155 int phaseSeed, 00156 int contrastSeed, 00157 double period, double sigma) 00158 : 00159 itsThetaRand(thetaSeed), 00160 itsPhaseRand(phaseSeed), 00161 itsContrastRand(contrastSeed), 00162 itsThetaJitter(0.0), 00163 itsContrastJitter(0.0), 00164 itsPeriod(period), 00165 itsSigma(sigma) 00166 { 00167 } 00168 00169 GaborPatchItemFactory::~GaborPatchItemFactory() 00170 {} 00171 00172 rutz::shared_ptr<SearchItem> 00173 GaborPatchItemFactory::make(const geom::vec2d& pos) 00174 { 00175 rutz::shared_ptr<GaborPatchItem> el(new GaborPatchItem); 00176 00177 el->type = SearchItem::BACKGROUND; 00178 el->pos = pos; 00179 00180 el->phi = 2 * M_PI * itsPhaseRand.fdraw(); 00181 el->theta = 2 * M_PI * itsThetaRand.fdraw(); 00182 el->contrast = exp(-itsContrastJitter * itsContrastRand.fdraw()); 00183 00184 el->itsPeriod = this->itsPeriod; 00185 el->itsSigma = this->itsSigma; 00186 00187 return el; 00188 } 00189 00190 rutz::shared_ptr<GaborPatchItem> 00191 GaborPatchItemFactory::makeForeground(const geom::vec2d& pos, 00192 const double theta) 00193 { 00194 rutz::shared_ptr<GaborPatchItem> el(new GaborPatchItem); 00195 00196 el->type = SearchItem::FOREGROUND; 00197 el->pos = pos; 00198 00199 el->phi = 2 * M_PI * itsPhaseRand.fdraw(); 00200 const double rand_theta = 2*M_PI * itsThetaRand.fdraw(); 00201 el->theta = 00202 geom::rad_0_2pi(itsThetaJitter * (rand_theta - M_PI) + 00203 (theta + M_PI_2)); 00204 el->contrast = exp(-itsContrastJitter * itsContrastRand.fdraw()); 00205 00206 el->itsPeriod = this->itsPeriod; 00207 el->itsSigma = this->itsSigma; 00208 00209 return el; 00210 } 00211 00212 // ###################################################################### 00213 /* So things look consistent in everyone's emacs... */ 00214 /* Local Variables: */ 00215 /* mode: c++ */ 00216 /* indent-tabs-mode: nil */ 00217 /* End: */ 00218 00219 #endif // PSYCHO_GABORPATCH_C_DEFINED