00001 /*!@file SceneUnderstanding/Regions.C */ 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: Lior Elazary <elazary@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/plugins/SceneUnderstanding/Regions.C $ 00035 // $Id: Regions.C 13765 2010-08-06 18:56:17Z lior $ 00036 // 00037 00038 #ifndef Regions_C_DEFINED 00039 #define Regions_C_DEFINED 00040 00041 #include "Image/DrawOps.H" 00042 #include "Image/MathOps.H" 00043 //#include "Image/OpenCVUtil.H" 00044 #include "Image/Kernels.H" 00045 #include "Image/FilterOps.H" 00046 #include "Image/Convolutions.H" 00047 #include "Image/fancynorm.H" 00048 #include "Image/Point3D.H" 00049 #include "Simulation/SimEventQueue.H" 00050 #include "plugins/SceneUnderstanding/Regions.H" 00051 #include "Neuro/EnvVisualCortex.H" 00052 #include "GUI/DebugWin.H" 00053 #include "Util/MathFunctions.H" 00054 #include <math.h> 00055 #include <fcntl.h> 00056 #include <limits> 00057 #include <string> 00058 00059 const ModelOptionCateg MOC_Regions = { 00060 MOC_SORTPRI_3, "Regions-Related Options" }; 00061 00062 // Used by: SimulationViewerEyeMvt 00063 const ModelOptionDef OPT_RegionsShowDebug = 00064 { MODOPT_ARG(bool), "RegionsShowDebug", &MOC_Regions, OPTEXP_CORE, 00065 "Show debug img", 00066 "regions-debug", '\0', "<true|false>", "false" }; 00067 00068 00069 // ###################################################################### 00070 Regions::Regions(OptionManager& mgr, const std::string& descrName, 00071 const std::string& tagName) : 00072 SimModule(mgr, descrName, tagName), 00073 SIMCALLBACK_INIT(SimEventLGNOutput), 00074 SIMCALLBACK_INIT(SimEventSMapOutput), 00075 SIMCALLBACK_INIT(SimEventSaveOutput), 00076 SIMCALLBACK_INIT(SimEventUserInput), 00077 SIMCALLBACK_INIT(SimEventRegionsPrior), 00078 itsShowDebug(&OPT_RegionsShowDebug, this) 00079 00080 { 00081 00082 itsTempColor = 104; 00083 00084 00085 itsRegionsState.clear(); 00086 } 00087 00088 // ###################################################################### 00089 Regions::~Regions() 00090 { 00091 00092 } 00093 00094 // ###################################################################### 00095 void Regions::onSimEventLGNOutput(SimEventQueue& q, 00096 rutz::shared_ptr<SimEventLGNOutput>& e) 00097 { 00098 itsRegionsCellsInput = e->getCells(); 00099 inplaceNormalize(itsRegionsCellsInput[0], 0.0F, 255.0F); 00100 evolve(); 00101 00102 q.post(rutz::make_shared(new SimEventRegionsOutput(this, itsRegionsState))); 00103 00104 } 00105 00106 // ###################################################################### 00107 void Regions::onSimEventRegionsPrior(SimEventQueue& q, 00108 rutz::shared_ptr<SimEventRegionsPrior>& e) 00109 { 00110 itsRegionsPrior = e->getRegions(); 00111 evolve(); 00112 } 00113 00114 00115 // ###################################################################### 00116 void Regions::onSimEventSMapOutput(SimEventQueue& q, 00117 rutz::shared_ptr<SimEventSMapOutput>& e) 00118 { 00119 itsSMapInput = e->getCells(); 00120 00121 //for(uint i=0; i<1; i++) 00122 //Add the background 00123 Image<float> tmp(itsRegionsCellsInput[0].getDims(), ZEROS); 00124 if (itsSMapInput.size() > 0) 00125 { 00126 SMap::SMapState sms = itsSMapInput[0]; 00127 00128 itsBackgroundRegion.mu = sms.mu; 00129 itsBackgroundRegion.sigma = sms.sigma; 00130 00131 for(uint pix=0; pix<sms.region.size(); pix++) 00132 { 00133 //only take pixels that are close to the mean 00134 //if ( gauss<double>((double)itsRegionsCellsInput[0].getVal(sms.region[pix]), 00135 // itsBackgroundRegion.mu, itsBackgroundRegion.sigma) > 1.0e-20) 00136 { 00137 itsBackgroundRegion.region.push_back(sms.region[pix]); 00138 tmp.setVal(sms.region[pix], 255); 00139 } 00140 } 00141 00142 calcRegionLikelihood(itsBackgroundRegion); 00143 } 00144 00145 ////Find the edge of the background 00146 //Image<float> mag, ori; 00147 //gradientSobel(tmp, mag, ori); 00148 00149 //std::vector<Point2D<int> > boundry; 00150 //for(int y=0; y<tmp.getHeight(); y++) 00151 // for(int x=0; x<tmp.getWidth(); x++) 00152 // if (mag.getVal(x,y) > 0) 00153 // boundry.push_back(Point2D<int>(x,y)); 00154 00155 00156 //if (itsSMapInput.size() > 1) 00157 //{ 00158 // for(uint i=1; i<itsSMapInput.size(); i++) 00159 // { 00160 // SMap::SMapState sms = itsSMapInput[i]; 00161 00162 // RegionState rs; 00163 // rs.mu = sms.mu; 00164 // rs.sigma = sms.sigma; 00165 00166 // for(uint pix=0; pix<sms.region.size(); pix++) 00167 // { 00168 // double backgroundProb = gauss<double>((double)itsRegionsCellsInput[0].getVal(sms.region[pix]), itsRegionsState[0].mu, itsRegionsState[0].sigma); 00169 // //double foregroundProb = gauss<double>((double)itsRegionsCellsInput[0].getVal(sms.region[pix]), rs.mu, rs.sigma); 00170 00171 // //check if this pixel will be better off beloging to the background 00172 // if ((backgroundProb > 1.0e-2) ) 00173 // { 00174 // //check the distance from this pixel to the rest; 00175 // double minDist = 100; 00176 // for(uint j=0; j<boundry.size(); j++) 00177 // { 00178 // double dist = sms.region[pix].distance(boundry[j]); 00179 // if (dist < minDist) 00180 // minDist = dist; 00181 // } 00182 00183 // if (minDist < 3) 00184 // { 00185 // itsRegionsState[0].region.push_back(sms.region[pix]); 00186 // boundry.push_back(sms.region[pix]); 00187 // } 00188 // else 00189 // rs.region.push_back(sms.region[pix]); 00190 00191 // } 00192 // else 00193 // rs.region.push_back(sms.region[pix]); 00194 00195 // } 00196 00197 // calcRegionLikelihood(rs); 00198 00199 // itsRegionsState.push_back(rs); 00200 // } 00201 //} 00202 00203 00204 00205 } 00206 00207 // ###################################################################### 00208 void Regions::onSimEventSaveOutput(SimEventQueue& q, rutz::shared_ptr<SimEventSaveOutput>& e) 00209 { 00210 if (itsShowDebug.getVal()) 00211 { 00212 // get the OFS to save to, assuming sinfo is of type 00213 // SimModuleSaveInfo (will throw a fatal exception otherwise): 00214 nub::ref<FrameOstream> ofs = 00215 dynamic_cast<const SimModuleSaveInfo&>(e->sinfo()).ofs; 00216 Layout<PixRGB<byte> > disp = getDebugImage(); 00217 ofs->writeRgbLayout(disp, "Regions", FrameInfo("Regions", SRC_POS)); 00218 } 00219 } 00220 00221 00222 // ###################################################################### 00223 void Regions::onSimEventUserInput(SimEventQueue& q, rutz::shared_ptr<SimEventUserInput>& e) 00224 { 00225 00226 //if (e->getWinName() == "Regions") 00227 { 00228 LINFO("Got event %s %ix%i key=%i", 00229 e->getWinName(), 00230 e->getMouseClick().i, 00231 e->getMouseClick().j, 00232 e->getKey()); 00233 00234 switch(e->getKey()) 00235 { 00236 case 54: //c for clear 00237 itsUserPolygon.clear(); 00238 break; 00239 case 36: //enter for closing polygon 00240 break; 00241 case 98: //up key 00242 itsTempColor += 1; 00243 break; 00244 case 104: //down key 00245 itsTempColor -= 1; 00246 break; 00247 } 00248 if (e->getMouseClick().isValid()) 00249 { 00250 itsUserPolygon.push_back(e->getMouseClick()); 00251 LINFO("Color is %f", itsRegionsCellsInput[0].getVal(e->getMouseClick())); 00252 } 00253 evolve(); 00254 00255 } 00256 00257 } 00258 00259 00260 00261 void Regions::calcRegionLikelihood(RegionState& rs) 00262 { 00263 00264 double minProb = 1.0e-5; 00265 00266 rs.prob = log(minProb)*512*512; //set the initial prob to very low 00267 00268 if (itsRegionsCellsInput.size() > 0) 00269 { 00270 for(uint i=0; i<rs.region.size(); i++) 00271 rs.prob += log(gauss<double>((double)itsRegionsCellsInput[0].getVal(rs.region[i]), rs.mu, rs.sigma)); 00272 00273 //Correct for more data 00274 rs.prob -= log(minProb) * rs.region.size(); 00275 } 00276 00277 } 00278 00279 00280 double Regions::calcRegionLikelihood(Image<float>& mu) 00281 { 00282 00283 double prob = 0; 00284 Image<float> in = itsRegionsCellsInput[0]; 00285 00286 for(uint i=0; i<mu.size(); i++) 00287 { 00288 prob += log(gauss<double>((double)in[i], (double)mu[i], 5)); 00289 } 00290 00291 return prob; 00292 } 00293 00294 00295 // ###################################################################### 00296 void Regions::evolve() 00297 { 00298 00299 00300 //for(uint py=0; py<240; py++) 00301 // for(uint px=0;px<320; px++) 00302 // { 00303 // RegionState newRs = itsRegionsState[0]; 00304 // //Pick a point at random and add it to the region 00305 // // int px = randomUpToIncluding(320-1); 00306 // // int py = randomUpToIncluding(240-1); 00307 // LINFO("New pix %ix%i", px, py); 00308 // newRs.region.push_back(Point2D<int>(px,py)); 00309 00310 00311 // calcRegionLikelihood(newRs); 00312 // LINFO("New Likelihood %e old likelihood %e", newRs.prob, itsRegionsState[0].prob); 00313 00314 // if (newRs.prob > itsRegionsState[0].prob) 00315 // { 00316 // itsRegionsState[0] = newRs; 00317 // LINFO("Taking new point"); 00318 // } 00319 // } 00320 00321 //Calculate region likelihood 00322 itsRegionsState = itsRegionsPrior; 00323 //for(uint i=0; i<itsRegionsPrior.size(); i++) 00324 //{ 00325 // RegionState newRs = itsRegionsPrior[i]; 00326 // calcRegionLikelihood(newRs); 00327 // itsRegionsState[i] = newRs; 00328 00329 // LINFO("%i, New Likelihood %e old likelihood %e", 00330 // i, newRs.prob, itsRegionsState[i].prob); 00331 // //if (newRs.prob > itsRegionsState[i].prob) 00332 // //{ 00333 // //} 00334 //} 00335 00336 //RegionsState rs; 00337 //rs.mu = itsTempColor; 00338 //rs.sigma = 5; 00339 //for(uint j=0; j<itsRegionsCellsInput[0].getHeight(); j++) 00340 // for(uint i=0; i<itsRegionsCellsInput[0].getWidth(); i++) 00341 // { 00342 // RegionsState tmpRs = rs; 00343 00344 // tmpRs.region.push_back(Point2D<int>(i,j)); 00345 // calcRegionLikelihood(rs); 00346 00347 // } 00348 00349 00350 } 00351 00352 Layout<PixRGB<byte> > Regions::getDebugImage() 00353 { 00354 Layout<PixRGB<byte> > outDisp; 00355 00356 for(int i=0; i<1; i++) 00357 { 00358 Image<float> in = itsRegionsCellsInput[i]; 00359 //inplaceNormalize(in, 0.0F, 255.0F); 00360 00361 // Image<float> perc(in.getDims(), ZEROS); 00362 Image<PixRGB<byte> > perc = in; 00363 00364 //Show the background 00365 00366 00367 for(uint pix=0; pix<itsBackgroundRegion.region.size(); pix++) 00368 { 00369 perc.setVal(itsBackgroundRegion.region[pix], PixRGB<byte>(0,0,0)); //itsBackgroundRegion.mu); 00370 } 00371 00372 for(uint i=0; i<itsRegionsState.size(); i++) 00373 { 00374 RegionState rs = itsRegionsState[i]; 00375 // LINFO("Region %i mu=%0.2f sigma=%0.2f prob=%e ", 00376 // i, rs.mu, rs.sigma, rs.prob); 00377 for(uint pix=0; pix<rs.region.size(); pix++) 00378 { 00379 perc.setVal(rs.region[pix], PixRGB<byte>(255,0,0)); 00380 } 00381 } 00382 00383 //in += perc; 00384 00385 //Draw ponts for user polygon 00386 for(uint i=0; i<itsUserPolygon.size(); i++) 00387 { 00388 drawCircle(in, itsUserPolygon[i], 3, 255.0F); 00389 } 00390 00391 00392 outDisp = hcat(toRGB(Image<byte>(in)), perc); 00393 } 00394 00395 return outDisp; 00396 00397 } 00398 00399 // ###################################################################### 00400 /* So things look consistent in everyone's emacs... */ 00401 /* Local Variables: */ 00402 /* indent-tabs-mode: nil */ 00403 /* End: */ 00404 00405 #endif 00406