00001 /*!@file Neuro/TaskRelevanceMap.C Implementation for task-relevance map class */ 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/Neuro/TaskRelevanceMap.C $ 00035 // $Id: TaskRelevanceMap.C 14390 2011-01-13 20:17:22Z pez $ 00036 // 00037 00038 #include "Neuro/TaskRelevanceMap.H" 00039 00040 #include "Channels/ChannelOpts.H" // for OPT_LevelSpec 00041 #include "Channels/InputFrame.H" 00042 #include "Component/OptionManager.H" 00043 #include "Image/Image.H" 00044 #include "Image/MathOps.H" // for absDiff() 00045 #include "Image/ShapeOps.H" // for rescale(), downSize() 00046 #include "Image/CutPaste.H" // for concatX() 00047 #include "Image/Transforms.H" 00048 #include "Image/DrawOps.H" // for drawFilledPolygon() 00049 #include "Image/MathOps.H" 00050 #include "Image/MatrixOps.H" 00051 #include "Neuro/NeuroOpts.H" 00052 #include "Neuro/NeuroSimEvents.H" 00053 #include "Neuro/SaccadeController.H" 00054 #include "Raster/Raster.H" 00055 #include "Simulation/SimEventQueue.H" 00056 #include "Transport/FrameInfo.H" 00057 #include "Transport/FrameOstream.H" 00058 #include "Util/Types.H" 00059 #include "Util/log.H" 00060 #include "Util/StringConversions.H" 00061 #include "Util/StringUtil.H" // for toLowerCase() 00062 00063 #include "Simulation/SimEventQueueConfigurator.H" 00064 #include "Neuro/GistEstimator.H" 00065 #include "Neuro/gistParams.H" 00066 #include "GUI/XWinManaged.H" 00067 #include <vector> 00068 00069 #include <cstdio> 00070 00071 #define PI 3.141592 00072 00073 // ###################################################################### 00074 // ###################################################################### 00075 // ########## TaskRelevanceMap implementation 00076 // ###################################################################### 00077 // ###################################################################### 00078 00079 TaskRelevanceMap::TaskRelevanceMap(OptionManager& mgr, 00080 const std::string& descrName, 00081 const std::string& tagName) : 00082 SimModule(mgr, descrName, tagName) 00083 { } 00084 00085 // ###################################################################### 00086 TaskRelevanceMap::~TaskRelevanceMap() 00087 { } 00088 00089 // ###################################################################### 00090 // ###################################################################### 00091 // ########## TaskRelevanceMapConfigurator implementation 00092 // ###################################################################### 00093 // ###################################################################### 00094 TaskRelevanceMapConfigurator:: 00095 TaskRelevanceMapConfigurator(OptionManager& mgr, 00096 const std::string& descrName, 00097 const std::string& tagName) : 00098 ModelComponent(mgr, descrName, tagName), 00099 itsTRMtype(&OPT_TaskRelevanceMapType, this), 00100 itsTRM(new TaskRelevanceMapStub(mgr)) 00101 { 00102 addSubComponent(itsTRM); 00103 } 00104 00105 // ###################################################################### 00106 TaskRelevanceMapConfigurator::~TaskRelevanceMapConfigurator() 00107 { } 00108 00109 // ###################################################################### 00110 nub::ref<TaskRelevanceMap> TaskRelevanceMapConfigurator::getTRM() const 00111 { return itsTRM; } 00112 00113 // ###################################################################### 00114 void TaskRelevanceMapConfigurator:: 00115 paramChanged(ModelParamBase* const param, 00116 const bool valueChanged, 00117 ParamClient::ChangeStatus* status) 00118 { 00119 ModelComponent::paramChanged(param, valueChanged, status); 00120 00121 // was that a change of our baby's name? 00122 if (param == &itsTRMtype) { 00123 // if we had one, let's unregister it (when we later reset() the 00124 // nub::ref, the current TaskRelevanceMap will unexport its 00125 // command-line options): 00126 removeSubComponent(*itsTRM); 00127 00128 // instantiate a SM of the appropriate type: 00129 if (itsTRMtype.getVal().compare("None") == 0 || 00130 itsTRMtype.getVal().compare("Stub") == 0) // no TRM 00131 itsTRM.reset(new TaskRelevanceMapStub(getManager())); 00132 else if (itsTRMtype.getVal().compare("Std") == 0) // standard 00133 itsTRM.reset(new TaskRelevanceMapStd(getManager())); 00134 else if (itsTRMtype.getVal().compare("KillStatic") == 0) // kill-static 00135 itsTRM.reset(new TaskRelevanceMapKillStatic(getManager())); 00136 else if (itsTRMtype.getVal().compare("KillN") == 0) // kill-n 00137 itsTRM.reset(new TaskRelevanceMapKillN(getManager())); 00138 else if (itsTRMtype.getVal().compare("GistClassify") == 0) // gist-classify 00139 itsTRM.reset(new TaskRelevanceMapGistClassify(getManager())); 00140 else if (itsTRMtype.getVal().compare("Tigs") == 0) // Tigs 00141 itsTRM.reset(new TaskRelevanceMapTigs(getManager())); 00142 else if (itsTRMtype.getVal().compare("Tigs2") == 0) // Tigs(gist and pca image) 00143 itsTRM.reset(new TaskRelevanceMapTigs2(getManager())); 00144 else if (itsTRMtype.getVal().compare("Social") == 0) // Social(requires XML of data) 00145 itsTRM.reset(new TaskRelevanceMapSocial(getManager())); 00146 else 00147 LFATAL("Unknown TRM type %s", itsTRMtype.getVal().c_str()); 00148 00149 // add our baby as a subcomponent of us so that it will become 00150 // linked to the manager through us (hopefully we are registered 00151 // with the manager), which in turn will allow it to export its 00152 // command-line options and get configured: 00153 00154 addSubComponent(itsTRM); 00155 00156 // tell the controller to export its options: 00157 itsTRM->exportOptions(MC_RECURSE); 00158 00159 // some info message: 00160 LINFO("Selected TRM of type %s", itsTRMtype.getVal().c_str()); 00161 } 00162 } 00163 00164 00165 // ###################################################################### 00166 // ###################################################################### 00167 // ########## TaskRelevanceMapStub implementation 00168 // ###################################################################### 00169 // ###################################################################### 00170 00171 // ###################################################################### 00172 TaskRelevanceMapStub::TaskRelevanceMapStub(OptionManager& mgr, 00173 const std::string& descrName, 00174 const std::string& tagName) : 00175 TaskRelevanceMap(mgr, descrName, tagName) 00176 { } 00177 00178 // ###################################################################### 00179 TaskRelevanceMapStub::~TaskRelevanceMapStub() 00180 { } 00181 00182 00183 // ###################################################################### 00184 // ###################################################################### 00185 // ########## TaskRelevanceMapAdapter implementation 00186 // ###################################################################### 00187 // ###################################################################### 00188 TaskRelevanceMapAdapter:: 00189 TaskRelevanceMapAdapter(OptionManager& mgr, 00190 const std::string& descrName, 00191 const std::string& tagName) : 00192 TaskRelevanceMap(mgr, descrName, tagName), 00193 SIMCALLBACK_INIT(SimEventRetinaImage), 00194 SIMCALLBACK_INIT(SimEventSaccadeStatusEye), 00195 SIMCALLBACK_INIT(SimEventClockTick), 00196 SIMCALLBACK_INIT(SimEventSaveOutput), 00197 itsLevelSpec(&OPT_LevelSpec, this), //Channels/ChannelOpts.{H,C} 00198 itsSaveResults(&OPT_TRMsaveResults, this) // see Neuro/NeuroOpts.{H,C} 00199 { } 00200 00201 // ###################################################################### 00202 TaskRelevanceMapAdapter::~TaskRelevanceMapAdapter() 00203 { } 00204 00205 // ###################################################################### 00206 void TaskRelevanceMapAdapter::reset1() 00207 { itsMap.freeMem(); } 00208 00209 // ###################################################################### 00210 void TaskRelevanceMapAdapter:: 00211 onSimEventRetinaImage(SimEventQueue& q, rutz::shared_ptr<SimEventRetinaImage>& e) 00212 { 00213 const Dims d = e->frame().colorByte().getDims(); 00214 const int sml = itsLevelSpec.getVal().mapLevel(); 00215 00216 const Dims mapdims(d.w() >> sml, d.h() >> sml); 00217 00218 // great, here is a new input image. Initialize our map if needed: 00219 if (itsMap.getDims() != mapdims) 00220 { 00221 itsMap.resize(mapdims,true); 00222 itsMap.clear(1.0F); // neutral relevance 00223 } 00224 00225 // now do any implementation-specific processing: 00226 this->inputFrame(e->frame()); 00227 } 00228 00229 // ###################################################################### 00230 void TaskRelevanceMapAdapter:: 00231 onSimEventSaccadeStatusEye(SimEventQueue& q, rutz::shared_ptr<SimEventSaccadeStatusEye>& e) 00232 { 00233 if (e->saccadeStatus() == TSTATUS_BEGIN) this->saccadicSuppression(true); 00234 else if (e->saccadeStatus() == TSTATUS_END) this->saccadicSuppression(false); 00235 } 00236 00237 // ###################################################################### 00238 void TaskRelevanceMapAdapter:: 00239 onSimEventClockTick(SimEventQueue& q, rutz::shared_ptr<SimEventClockTick>& e) 00240 { 00241 // evolve one time step: 00242 this->integrate(q); 00243 00244 // all right, post our current internals if we have any: 00245 if (itsMap.initialized()) 00246 { 00247 rutz::shared_ptr<SimEventTaskRelevanceMapOutput> 00248 etrm(new SimEventTaskRelevanceMapOutput(this, itsMap)); 00249 q.post(etrm); 00250 } 00251 } 00252 00253 // ###################################################################### 00254 void TaskRelevanceMapAdapter:: 00255 onSimEventSaveOutput(SimEventQueue& q, rutz::shared_ptr<SimEventSaveOutput>& e) 00256 { 00257 this->save1(e->sinfo()); 00258 } 00259 00260 // ###################################################################### 00261 void TaskRelevanceMapAdapter::save1(const ModelComponentSaveInfo& sinfo) 00262 { 00263 if (itsSaveResults.getVal()) 00264 { 00265 // get the OFS to save to, assuming sinfo is of type 00266 // SimModuleSaveInfo (will throw a fatal exception otherwise): 00267 nub::ref<FrameOstream> ofs = 00268 dynamic_cast<const SimModuleSaveInfo&>(sinfo).ofs; 00269 00270 ofs->writeFloat(itsMap, FLOAT_NORM_PRESERVE, "TRM", 00271 FrameInfo("task relevance map (top-down)", SRC_POS)); 00272 } 00273 } 00274 00275 // ###################################################################### 00276 // ###################################################################### 00277 // ########## TaskRelevanceMapStd implementation 00278 // ###################################################################### 00279 // ###################################################################### 00280 00281 // ###################################################################### 00282 TaskRelevanceMapStd:: 00283 TaskRelevanceMapStd(OptionManager& mgr, const std::string& descrName, 00284 const std::string& tagName) : 00285 TaskRelevanceMapAdapter(mgr, descrName, tagName), 00286 itsLearnTRM(&OPT_LearnTRM, this), 00287 itsLearnUpdateTRM(&OPT_LearnUpdateTRM, this), 00288 itsBiasTRM(&OPT_BiasTRM, this) 00289 { } 00290 00291 // ###################################################################### 00292 TaskRelevanceMapStd::~TaskRelevanceMapStd() 00293 { } 00294 00295 // ###################################################################### 00296 void TaskRelevanceMapStd::inputFrame(const InputFrame& f) 00297 { } 00298 00299 /*FIXME 00300 void TaskRelevanceMapStd::input(const Image<float>& current) 00301 { 00302 itsMap = current; 00303 const Dims d = itsMap.getDims(); 00304 00305 // bias TRM if the option is specified 00306 if (strcmp(itsBiasTRM.getValString().c_str(), "") != 0) 00307 { 00308 LINFO("biasing TRM with %s", itsBiasTRM.getValString().c_str()); 00309 const Image<float> newtrm = 00310 Raster::ReadGray(itsBiasTRM.getValString()); 00311 itsMap = rescale(newtrm * (1.0F/255.0F), d); 00312 } 00313 } 00314 */ 00315 00316 // ###################################################################### 00317 void TaskRelevanceMapStd::saccadicSuppression(const bool on) 00318 { } 00319 00320 // ###################################################################### 00321 void TaskRelevanceMapStd::integrate(SimEventQueue& q) 00322 { } 00323 00324 /*FIXME 00325 void TaskRelevanceMapStd::update(const Point2D<int>& fixation, 00326 const Image<byte>& objectMask, 00327 const Dims& inputDims, 00328 const float relevance) 00329 { 00330 // get the object shape: 00331 Point2D<int> fixn; 00332 fixn.i = fixation.i * itsMap.getWidth() / inputDims.w(); 00333 fixn.j = fixation.j * itsMap.getHeight() / inputDims.h(); 00334 if ( ! objectMask.initialized()) 00335 { LERROR("object mask not initialized!"); return; } 00336 Image<byte> fmask = rescale(objectMask, itsMap.getDims()); 00337 Point2D<int> p; 00338 00339 //FIXME: this should be an Image function 00340 // update relevance only within object 00341 for (p.i = 0; p.i < itsMap.getWidth(); p.i ++) 00342 for (p.j = 0; p.j < itsMap.getHeight(); p.j ++) 00343 if (fmask.getVal(p) == 255) 00344 { 00345 if (relevance == 0.0f) itsMap.setVal(p, itsMap.getVal(p) - 1.0f); 00346 else itsMap.setVal(p, itsMap.getVal(p) + relevance); 00347 } 00348 00349 if (itsLearnTRM.getVal() == false) 00350 { 00351 // biasing mode / updating mode / none: 00352 // set min to 0 else normalizing will clear the entire TRM 00353 float min, max; getMinMax(itsMap, min, max); 00354 if (min > 0.0f) itsMap.setVal(0, 0, 0.0f); 00355 } 00356 00357 // normalize TRM else AGM will explode 00358 inplaceNormalize(itsMap, 0.0f, 3.0f); 00359 LINFO("Evolved TRM with relevance = %f", relevance); 00360 } 00361 */ 00362 00363 // ###################################################################### 00364 // ###################################################################### 00365 // ########## TaskRelevanceMapKillStatic implementation 00366 // ###################################################################### 00367 // ###################################################################### 00368 00369 // ###################################################################### 00370 TaskRelevanceMapKillStatic:: 00371 TaskRelevanceMapKillStatic(OptionManager& mgr, 00372 const std::string& descrName, 00373 const std::string& tagName) : 00374 TaskRelevanceMapAdapter(mgr, descrName, tagName), 00375 itsKillStaticThresh(&OPT_TRMKillStaticThresh, this), 00376 itsKillStaticCoeff(&OPT_TRMKillStaticCoeff, this), 00377 itsStaticBuff() 00378 { } 00379 00380 // ###################################################################### 00381 TaskRelevanceMapKillStatic::~TaskRelevanceMapKillStatic() 00382 { } 00383 00384 // ###################################################################### 00385 void TaskRelevanceMapKillStatic::reset1() 00386 { 00387 TaskRelevanceMapAdapter::reset1(); 00388 itsStaticBuff.freeMem(); 00389 } 00390 00391 // ###################################################################### 00392 void TaskRelevanceMapKillStatic::inputFrame(const InputFrame& f) 00393 { 00394 // NOTE: we are guaranteed that itsMap is initialized and of correct 00395 // size, as this is done by the TaskRelevanceMapAdapter before 00396 // calling us. 00397 00398 // NOTE: this is duplicating some of the computation done in the 00399 // IntensityChannel, so there is a tiny performance hit (~0.25%) in 00400 // doing this operation twice; however the benefit is that we avoid 00401 // having to somehow pick information out of an IntensityChannel and 00402 // pass it to a TaskRelevanceMap -- that was making for a mess in 00403 // Brain. In the future, we could avoid the ineffiency by caching 00404 // the intensity pyramid in the InputFrame object, and then letting 00405 // IntensityChannel and TaskRelevanceMap both share access to that 00406 // pyramid. 00407 const Image<float> img = 00408 downSize(f.grayFloat(), itsMap.getWidth(), itsMap.getHeight(), 5); 00409 00410 // is this our first time here? 00411 if (itsStaticBuff.initialized() == false) 00412 { itsStaticBuff = img; return; } 00413 00414 // otherwise derive TRM from difference between current frame and 00415 // staticBuf: 00416 Image<float> diff = absDiff(itsStaticBuff, img); 00417 00418 // useful range of diff is 0..255; anything giving an output less 00419 // that itsKillStaticThresh will be considered static; here let's 00420 // clamp to isolate that: 00421 inplaceClamp(diff, 0.0F, itsKillStaticThresh.getVal()); 00422 00423 // the more static, the greater the killing: so, first let's change 00424 // the range so that the min is at -itsKillStaticThresh and zero is 00425 // neutral: 00426 diff -= itsKillStaticThresh.getVal(); 00427 00428 // itsKillStaticCoeff determines how strong the killing should be: 00429 diff *= (1.0F / itsKillStaticThresh.getVal()) * // normalize to min at -1.0 00430 itsKillStaticCoeff.getVal(); // apply coeff 00431 00432 // mix our new TRM to the old one; we want to have a fairly high 00433 // mixing coeff for the new one so that we don't penalize recent 00434 // onset objects too much (i.e., were previously static and killed, 00435 // but are not anymore): 00436 itsMap = itsMap * 0.25F + (diff + 1.0F) * 0.75F; 00437 float mi, ma; getMinMax(itsMap, mi, ma); 00438 LINFO("TRM range = [%.2f .. %.2f] -- 1.0 is baseline", mi, ma); 00439 00440 // update our cumulative buffer: 00441 itsStaticBuff = itsStaticBuff * 0.75F + img * 0.25F; 00442 00443 } 00444 00445 // ###################################################################### 00446 void TaskRelevanceMapKillStatic::saccadicSuppression(const bool on) 00447 { 00448 // a saccade resets our cumulative buffer: 00449 itsStaticBuff.freeMem(); 00450 } 00451 00452 // ###################################################################### 00453 void TaskRelevanceMapKillStatic::integrate(SimEventQueue& q) 00454 { } 00455 00456 // ###################################################################### 00457 void TaskRelevanceMapKillStatic::save1(const ModelComponentSaveInfo& sinfo) 00458 { 00459 TaskRelevanceMapAdapter::save1(sinfo); 00460 00461 if (itsSaveResults.getVal()) 00462 { 00463 // get the OFS to save to, assuming sinfo is of type 00464 // SimModuleSaveInfo (will throw a fatal exception otherwise): 00465 nub::ref<FrameOstream> ofs = 00466 dynamic_cast<const SimModuleSaveInfo&>(sinfo).ofs; 00467 00468 ofs->writeFloat(itsStaticBuff, FLOAT_NORM_0_255, "TRM-SB", 00469 FrameInfo("task relevance map static buffer", SRC_POS)); 00470 } 00471 } 00472 00473 00474 // ###################################################################### 00475 // ###################################################################### 00476 // ########## TaskRelevanceMapKillN implementation 00477 // ###################################################################### 00478 // ###################################################################### 00479 00480 // ###################################################################### 00481 TaskRelevanceMapKillN:: 00482 TaskRelevanceMapKillN(OptionManager& mgr, const std::string& descrName, 00483 const std::string& tagName) : 00484 TaskRelevanceMapAdapter(mgr, descrName, tagName), 00485 itsN(&OPT_TRMkillN, this), itsCache() 00486 { } 00487 00488 // ###################################################################### 00489 TaskRelevanceMapKillN::~TaskRelevanceMapKillN() 00490 { } 00491 00492 // ###################################################################### 00493 void TaskRelevanceMapKillN::reset1() 00494 { 00495 TaskRelevanceMapAdapter::reset1(); 00496 itsCache.clear(); 00497 } 00498 00499 // ###################################################################### 00500 void TaskRelevanceMapKillN::start1() 00501 { 00502 itsCache.setMaxSize(itsN.getVal()); 00503 00504 TaskRelevanceMapAdapter::start1(); 00505 } 00506 00507 // ###################################################################### 00508 void TaskRelevanceMapKillN::inputFrame(const InputFrame& f) 00509 { } 00510 00511 // ###################################################################### 00512 void TaskRelevanceMapKillN::integrate(SimEventQueue& q) 00513 { 00514 // anything from the ShapeEstimator? 00515 if (SeC<SimEventShapeEstimatorOutput> e = 00516 q.check<SimEventShapeEstimatorOutput>(this)) 00517 { 00518 // get the smooth object mask: 00519 Image<float> mask = e->smoothMask(); 00520 00521 // downscale to our map's size: 00522 mask = downSize(mask, itsMap.getWidth(), itsMap.getHeight(), 5); 00523 00524 // is the mask uniform (i.e., empty)? In this case, just push 00525 // it in, otherwise let's segment the objects out: 00526 float mi, ma; getMinMax(mask, mi, ma); 00527 if (fabs(mi - ma) < 1.0e-10) 00528 itsCache.push_back(mask); 00529 else 00530 { 00531 // let's build a distance map out of the object and threhold it: 00532 Image<float> dmap = chamfer34(mask, 255.0F); 00533 inplaceClamp(dmap, 0.0F, 15.0F); 00534 dmap /= 15.0F; // 0 inside obj, 1 outside 00535 00536 // get this new input mask into our cache: 00537 itsCache.push_back(dmap); 00538 } 00539 00540 // our current relevance map is the min over our cache: 00541 itsMap = itsCache.getMin(); 00542 } 00543 } 00544 00545 // ###################################################################### 00546 void TaskRelevanceMapKillN::saccadicSuppression(const bool on) 00547 { } 00548 00549 // ###################################################################### 00550 // ###################################################################### 00551 // ########## TaskRelevanceMapGistClassify implementation 00552 // ###################################################################### 00553 // ###################################################################### 00554 // ###################################################################### 00555 TaskRelevanceMapGistClassify:: 00556 TaskRelevanceMapGistClassify(OptionManager& mgr, const std::string& descrName, 00557 const std::string& tagName) : 00558 TaskRelevanceMapAdapter(mgr, descrName, tagName), 00559 itsClusterCenterFileName(&OPT_TRMClusterCenterFile, this), 00560 itsTemplateDir(&OPT_TRMTemplateDir, this), 00561 itsPCADims(&OPT_TRMGistPCADims, this), 00562 itsPCAMatrixName(&OPT_TRMGistPCAMatrix, this), 00563 itsCacheSize(&OPT_TRMCacheSize, this), 00564 itsUpdatePeriod(&OPT_TRMUpdatePeriod, this), 00565 itsMapComputedForCurrentFrame(false), 00566 itsTDMap() 00567 { 00568 itsFrame = -1; 00569 itsTDMap.setMaxSize(itsCacheSize.getVal()); 00570 } 00571 00572 // ###################################################################### 00573 TaskRelevanceMapGistClassify::~TaskRelevanceMapGistClassify() 00574 { } 00575 00576 // ###################################################################### 00577 void TaskRelevanceMapGistClassify::reset1() 00578 { 00579 TaskRelevanceMapAdapter::reset1(); 00580 } 00581 00582 // ###################################################################### 00583 void TaskRelevanceMapGistClassify::inputFrame(const InputFrame& f) 00584 { 00585 getPCAMatrix(); 00586 itsFrame++; 00587 itsMapComputedForCurrentFrame = false; 00588 } 00589 00590 // ###################################################################### 00591 void TaskRelevanceMapGistClassify::integrate(SimEventQueue& q) 00592 { 00593 if (SeC<SimEventGistOutput> e = 00594 q.check<SimEventGistOutput>(this)) 00595 { 00596 if (itsMapComputedForCurrentFrame) 00597 return; 00598 00599 //! to make the gist feature value in a reasonable range to get the 00600 // variance and determine value 00601 itsGist = e->gv() / 10.0F; 00602 00603 gistmatch(reshape(itsGist, 00604 Dims(itsGist.getWidth() * itsGist.getHeight(), 1))); 00605 00606 if (itsCacheSize.getVal() > 0) 00607 { 00608 itsTDMap.push_back(itsTmpTDMap); 00609 if (itsFrame % itsUpdatePeriod.getVal() ==0) 00610 itsCurrentTDMap = itsTDMap.mean(); 00611 } 00612 else 00613 itsCurrentTDMap = itsTmpTDMap; 00614 00615 00616 itsMap = rescale(itsCurrentTDMap, itsMap.getDims()); 00617 00618 float mi, ma; getMinMax(itsMap, mi, ma); 00619 LINFO("\nFinal TRM range = [%.2f .. %.2f] -- 1.0 is baseline\n", mi, ma); 00620 00621 itsMapComputedForCurrentFrame = true; 00622 } 00623 } 00624 00625 // ###################################################################### 00626 void TaskRelevanceMapGistClassify::saccadicSuppression(const bool on) 00627 { } 00628 00629 // ###################################################################### 00630 void TaskRelevanceMapGistClassify:: 00631 gistmatch(Image<float> currGist) 00632 { 00633 Image<float> gistDist = computeGistDist(currGist); 00634 itsTmpTDMap = getTDMap(gistDist); 00635 00636 } 00637 // ###################################################################### 00638 void TaskRelevanceMapGistClassify:: 00639 getPCAMatrix() 00640 { 00641 FILE* itsFile = fopen(itsPCAMatrixName.getVal().c_str(), "rb"); 00642 ASSERT(itsFile != 0); 00643 00644 int gistDims = 0; 00645 if(fread(&gistDims, sizeof(int), 1, itsFile) != 1) LFATAL("fread failed"); 00646 00647 Image<float> matrixTmp(gistDims, itsPCADims.getVal(), NO_INIT); 00648 size_t sz = itsPCADims.getVal()*gistDims; 00649 if(fread(matrixTmp.beginw(), sizeof(float), sz, itsFile) != sz) LFATAL("fread failed"); 00650 00651 itsPCAMatrix = transpose(matrixTmp); 00652 00653 LDEBUG("itsPCAMatrix first 5 num: %f, %f, %f, %f, %f", itsPCAMatrix.getVal(0,0), 00654 itsPCAMatrix.getVal(1,0), itsPCAMatrix.getVal(2,0), 00655 itsPCAMatrix.getVal(3,0), itsPCAMatrix.getVal(4,0)); 00656 00657 fclose(itsFile); 00658 } 00659 00660 00661 00662 // ###################################################################### 00663 Image<float> TaskRelevanceMapGistClassify:: 00664 computeGistDist(Image<float> currGist) 00665 { 00666 FILE* itsFile = fopen(itsClusterCenterFileName.getVal().c_str(), "rb"); 00667 ASSERT(itsFile != 0); 00668 00669 if(fread(&itsNumOfCategory, sizeof(int), 1, itsFile) != 1) LFATAL("fread failed"); 00670 if(fread(&itsUsedDims, sizeof(int),1,itsFile) != 1) LFATAL("fread failed"); 00671 ASSERT(itsNumOfCategory > 0 && itsUsedDims == itsPCADims.getVal()); 00672 00673 LDEBUG("there are %4d categories, pca_dims: %4d",itsNumOfCategory, itsUsedDims); 00674 00675 Image<float> currGistCut(currGist.getDims().sz()/NUM_GIST_FEAT, 1, NO_INIT); 00676 Image<float> currGistPCA(itsPCADims.getVal(), 1, NO_INIT); 00677 00678 //! only use the whole image's gist feature to do the classification 00679 for(int i=0; i<currGistCut.getDims().sz(); i++) 00680 currGistCut.setVal(i,0, currGist.getVal(i*NUM_GIST_FEAT, 0)); 00681 00682 LDEBUG("currGistCut dim: %d, PCA matrix height: %4d", 00683 currGistCut.getWidth(), itsPCAMatrix.getHeight()); 00684 00685 ASSERT(currGistCut.getWidth() == itsPCAMatrix.getHeight()); 00686 00687 currGistPCA = matrixMult(currGistCut, itsPCAMatrix); 00688 00689 LDEBUG("currGistPCA : %f, %f, %f", currGistPCA.getVal(0,0), 00690 currGistPCA.getVal(1,0), currGistPCA.getVal(2,0)); 00691 00692 Image<float> gistDist(itsNumOfCategory, 1,NO_INIT ); 00693 Image<float> gistCenter(itsUsedDims, 1, NO_INIT); 00694 Image<float> gistCenterCovarMatrix(itsUsedDims,itsUsedDims, NO_INIT); 00695 Image<float> gistCenterCovarMatrixInv(itsUsedDims, itsUsedDims, NO_INIT); 00696 Image<float> gistDiff(itsUsedDims,1,NO_INIT); 00697 00698 float meanClusterGistDist=0.0F; 00699 float det = 0.0F; 00700 float coef1 = pow(2*PI, itsUsedDims/2.0F); 00701 float coef2 = 0.0F, coef3=0.0F, coef4=0.0F; 00702 00703 for(int i=0; i<itsNumOfCategory; i++) 00704 { 00705 if(fread(gistCenter.beginw(), sizeof(float), itsUsedDims, itsFile) != (size_t)itsUsedDims) LFATAL("fread failed"); 00706 if(fread(&meanClusterGistDist, sizeof(float), 1, itsFile) != 1) LFATAL("fread failed"); 00707 if(fread(&det, sizeof(float), 1, itsFile) != 1) LFATAL("fread failed"); 00708 size_t sz = itsUsedDims*itsUsedDims; 00709 if(fread(gistCenterCovarMatrix.beginw(), sizeof(float), sz, itsFile) != sz) LFATAL("fread failed"); 00710 00711 gistCenterCovarMatrixInv = matrixInv(gistCenterCovarMatrix); 00712 00713 gistDiff = gistCenter - currGistPCA; 00714 00715 coef2 =1.0F /( coef1 * pow(det, 0.5)+0.0000001F ); 00716 00717 Image<float> tmp = matrixMult(matrixMult(gistDiff, gistCenterCovarMatrixInv), 00718 transpose(gistDiff)); 00719 00720 coef3 = exp(-0.5F * tmp.getVal(0,0)); 00721 coef4 = coef2 * coef3 / (meanClusterGistDist+0.5F); 00722 00723 LDEBUG("%d's is %f, %f, %f , mean is %f,sumDiff is%f\n", i+1, tmp.getVal(0,0), 00724 coef3, coef4, meanClusterGistDist, sum(gistDiff*gistDiff)); 00725 gistDist.setVal(i, 0, coef4); 00726 00727 } 00728 fclose(itsFile); 00729 00730 return gistDist; 00731 } 00732 00733 // ###################################################################### 00734 Image<float> TaskRelevanceMapGistClassify:: 00735 getTDMap(Image<float> gistDist) 00736 { 00737 std::string TDMapName; 00738 Image<float> TDMap; 00739 float coef = 0.0F; 00740 00741 for(int i=1; i<= itsNumOfCategory; i++) 00742 { 00743 TDMapName = itsTemplateDir.getVal()+std::string("category") 00744 +convertToString(i)+std::string(".png"); 00745 00746 00747 Image<float> TDMapTmp = Raster::ReadGray(TDMapName); 00748 00749 if(1==i) 00750 TDMap = TDMapTmp * gistDist.getVal(i-1,0); 00751 else 00752 TDMap += TDMapTmp * gistDist.getVal(i-1,0); 00753 00754 coef += gistDist.getVal(i-1,0); 00755 } 00756 00757 TDMap = (TDMap + 0.0001F) / (coef + 0.0001F); 00758 // consider that failure in classify then use the uniform template 00759 00760 float mi, ma; getMinMax(TDMap, mi, ma); 00761 LINFO("\ncoef= %.6f TRM range = [%.2f .. %.2f] -- 1.0 is baseline\n", coef, mi, ma); 00762 return TDMap; 00763 } 00764 00765 00766 // ###################################################################### 00767 // ###################################################################### 00768 // ########## TaskRelevanceMapTigs implementation 00769 // ###################################################################### 00770 // ###################################################################### 00771 // ###################################################################### 00772 TaskRelevanceMapTigs:: 00773 TaskRelevanceMapTigs(OptionManager& mgr, const std::string& descrName, 00774 const std::string& tagName) : 00775 TaskRelevanceMapAdapter(mgr, descrName, tagName), 00776 itsTigsMatrixName(&OPT_TRMTigsMatrix, this), 00777 itsPCADims(&OPT_TRMGistPCADims, this), 00778 itsPCAMatrixName(&OPT_TRMGistPCAMatrix, this), 00779 itsCacheSize(&OPT_TRMCacheSize, this), 00780 itsUpdatePeriod(&OPT_TRMUpdatePeriod, this), 00781 itsMapComputedForCurrentFrame(false), 00782 itsTDMap() 00783 { 00784 itsFrame = -1; 00785 itsTDMap.setMaxSize(itsCacheSize.getVal()); 00786 getPCAMatrix(); 00787 getTigsMatrix(); 00788 itsPCADims.setVal(5); // fixed to 5 now 00789 } 00790 00791 // ###################################################################### 00792 TaskRelevanceMapTigs::~TaskRelevanceMapTigs() 00793 { } 00794 00795 // ###################################################################### 00796 void TaskRelevanceMapTigs::reset1() 00797 { 00798 TaskRelevanceMapAdapter::reset1(); 00799 } 00800 00801 // ###################################################################### 00802 void TaskRelevanceMapTigs::inputFrame(const InputFrame& f) 00803 { 00804 itsFrame++; 00805 itsMapComputedForCurrentFrame = false; 00806 } 00807 00808 // ###################################################################### 00809 void TaskRelevanceMapTigs::getPCAMatrix() 00810 { 00811 FILE* itsFile = fopen(itsPCAMatrixName.getVal().c_str(), "rb"); 00812 if(itsFile == 0) 00813 PLFATAL("Can not open PCAMatrix for read PCA"); 00814 int gistDims = 0; 00815 if(fread(&gistDims, sizeof(int), 1, itsFile) != 1) LFATAL("fread failed"); 00816 00817 Image<float> matrixTmp(gistDims, itsPCADims.getVal(), NO_INIT); 00818 size_t sz = itsPCADims.getVal()*gistDims; 00819 if(fread(matrixTmp.beginw(), sizeof(float), sz, itsFile) != sz) LFATAL("fread failed"); 00820 00821 itsPCAMatrix = transpose(matrixTmp); 00822 00823 fclose(itsFile); 00824 } 00825 00826 // ###################################################################### 00827 void TaskRelevanceMapTigs::getTigsMatrix() 00828 { 00829 FILE* itsFile = fopen(itsTigsMatrixName.getVal().c_str(), 00830 "rb"); 00831 if(itsFile == 0) 00832 PLFATAL("Can not open TigsMatrix for read Tigs coefficients"); 00833 int w,h; 00834 if(fread(&h, sizeof(int), 1, itsFile) != 1) LFATAL("fread failed"); 00835 if(fread(&w, sizeof(int), 1, itsFile) != 1) LFATAL("fread failed"); 00836 00837 Image<float> matrixTmp(h, w, NO_INIT); 00838 // keep in mind that the definition of Image is Image(width, height) 00839 if(fread(matrixTmp.beginw(), sizeof(float), w*h, itsFile) != size_t(w*h)) LFATAL("fread failed"); 00840 00841 itsTigsMatrix = transpose(matrixTmp); 00842 fclose(itsFile); 00843 } 00844 00845 // ###################################################################### 00846 void TaskRelevanceMapTigs::integrate(SimEventQueue& q) 00847 { 00848 if (SeC<SimEventGistOutput> e = 00849 q.check<SimEventGistOutput>(this)) 00850 { 00851 if (itsMapComputedForCurrentFrame) 00852 return; 00853 00854 itsGist = e->gv(); 00855 itsTmpTDMap = getTDMap(itsGist); 00856 00857 if (itsCacheSize.getVal() > 0) 00858 { 00859 itsTDMap.push_back(itsTmpTDMap); 00860 if (itsFrame % itsUpdatePeriod.getVal() ==0) 00861 itsCurrentTDMap = itsTDMap.mean(); 00862 } 00863 else 00864 itsCurrentTDMap = itsTmpTDMap; 00865 00866 00867 itsMap = rescale(itsCurrentTDMap, itsMap.getDims()); 00868 00869 float mi, ma; getMinMax(itsMap, mi, ma); 00870 LINFO("\nFinal TRM range = [%.2f .. %.2f] -- 1.0 is baseline\n\n", mi, ma); 00871 00872 itsMapComputedForCurrentFrame = true; 00873 } 00874 } 00875 00876 // ###################################################################### 00877 void TaskRelevanceMapTigs::saccadicSuppression(const bool on) 00878 { } 00879 00880 // ###################################################################### 00881 Image<float> TaskRelevanceMapTigs:: 00882 getTDMap(Image<float> currGist) 00883 { 00884 Image<float> currGistCut(34,1,NO_INIT); 00885 Image<float> currGistPCA(itsPCADims.getVal(), 1, NO_INIT); 00886 Image<float> tmp(300,1, NO_INIT); //300=20x15 (Rob's cvpr 2007 paper, 32x32 for 1 block) 00887 Image<float> tmp2; 00888 00889 for(int i=0; i<34; i++) 00890 { 00891 currGistCut.setVal(i, 0, currGist.getVal(i*NUM_GIST_FEAT) ); 00892 } 00893 currGistPCA = matrixMult(currGistCut, itsPCAMatrix); 00894 00895 tmp = matrixMult(currGistPCA, itsTigsMatrix); 00896 tmp2 = decode(tmp); // tranfer the 20x15 dims vector to an image 00897 00898 return tmp2; 00899 } 00900 00901 // ###################################################################### 00902 Image<float> TaskRelevanceMapTigs:: decode(Image<float> inputVec) 00903 { 00904 const int w = 20; 00905 const int h = 15; 00906 Image<float> smallTDMap(w,h,NO_INIT); 00907 Image<float> bigTDMap; 00908 00909 for(int i = 0; i< h; i++) 00910 { 00911 for(int j = 0; j < w; j++) 00912 { 00913 smallTDMap.setVal(j,i,inputVec.getVal(i*w+j,0) ); 00914 } 00915 } 00916 inplaceNormalize(smallTDMap, 1.0F, 255.0F); 00917 bigTDMap = rescale(smallTDMap,itsMap.getDims()); 00918 00919 return bigTDMap; 00920 } 00921 00922 // ###################################################################### 00923 void TaskRelevanceMapTigs::save1(const ModelComponentSaveInfo& sinfo) 00924 { 00925 if (itsSaveResults.getVal()) 00926 { 00927 // get the OFS to save to, assuming sinfo is of type 00928 // SimModuleSaveInfo (will throw a fatal exception otherwise): 00929 nub::ref<FrameOstream> ofs = 00930 dynamic_cast<const SimModuleSaveInfo&>(sinfo).ofs; 00931 00932 ofs->writeFloat(itsCurrentTDMap, FLOAT_NORM_0_255, "TRM-SB", 00933 FrameInfo("task relevance map static buffer", SRC_POS)); 00934 } 00935 } 00936 00937 // ###################################################################### 00938 // ###################################################################### 00939 // ########## TaskRelevanceMapTigs2 implementation 00940 // ###################################################################### 00941 // ###################################################################### 00942 // ###################################################################### 00943 // for the training part see /lab/tmpib/u/gist-trm/trainging/Tigs2 00944 TaskRelevanceMapTigs2:: 00945 TaskRelevanceMapTigs2(OptionManager& mgr, const std::string& descrName, 00946 const std::string& tagName) : 00947 TaskRelevanceMapAdapter(mgr, descrName, tagName), 00948 itsTigsMatrixName(&OPT_TRMTigs2Matrix, this), 00949 itsGistPCADims(&OPT_TRMGistPCADims, this), 00950 itsImgPCADims(&OPT_TRMImgPCADims, this), 00951 itsGistPCAMatrixName(&OPT_TRMGistPCAMatrix, this), 00952 itsImgPCAMatrixName(&OPT_TRMImgPCAMatrix, this), 00953 itsCacheSize(&OPT_TRMCacheSize, this), 00954 itsUpdatePeriod(&OPT_TRMUpdatePeriod, this), 00955 itsMapComputedForCurrentFrame(false), 00956 itsTDMap() 00957 { 00958 itsFrame = -1; 00959 itsTDMap.setMaxSize(itsCacheSize.getVal()); 00960 itsGistPCADims.setVal(5); // fixed to 5 now 00961 itsImgPCADims.setVal(20); // fixed to 20 now 00962 } 00963 00964 // ###################################################################### 00965 TaskRelevanceMapTigs2::~TaskRelevanceMapTigs2() 00966 { } 00967 00968 // ###################################################################### 00969 void TaskRelevanceMapTigs2::reset1() 00970 { 00971 TaskRelevanceMapAdapter::reset1(); 00972 } 00973 00974 // ###################################################################### 00975 void TaskRelevanceMapTigs2::inputFrame(const InputFrame& f) 00976 { 00977 getGistPCAMatrix(); 00978 getImgPCAMatrix(); 00979 getTigsMatrix(); 00980 itsFrame++; 00981 00982 Image<float> currFrame = rescale(f.grayFloat(),f.getDims()/16, RESCALE_SIMPLE_NOINTERP); 00983 itsCurrFrameVec = reshape 00984 (transpose(currFrame/255.0F), Dims(currFrame.getWidth()*currFrame.getHeight(),1)); 00985 00986 itsMapComputedForCurrentFrame = false; 00987 } 00988 00989 // ###################################################################### 00990 void TaskRelevanceMapTigs2::getGistPCAMatrix() 00991 { 00992 FILE* itsFile = fopen(itsGistPCAMatrixName.getVal().c_str(), "rb"); 00993 if(itsFile == 0) 00994 PLFATAL("Can not open GistPCAMatrix for read PCA"); 00995 00996 int gistDims = 0; 00997 if(fread(&gistDims, sizeof(int), 1, itsFile) != 1) LFATAL("fread failed"); 00998 00999 Image<float> matrixTmp(gistDims, itsGistPCADims.getVal(), NO_INIT); 01000 size_t sz = itsGistPCADims.getVal()*gistDims; 01001 if(fread(matrixTmp.beginw(), sizeof(float), sz, itsFile) != sz) LFATAL("fread failed"); 01002 itsGistPCAMatrix = transpose(matrixTmp); 01003 01004 fclose(itsFile); 01005 } 01006 01007 // ###################################################################### 01008 void TaskRelevanceMapTigs2::getImgPCAMatrix() 01009 { 01010 FILE* itsFile = fopen(itsImgPCAMatrixName.getVal().c_str(), "rb"); 01011 if(itsFile == 0) 01012 PLFATAL("Can not open ImgPCAMatrix for read PCA"); 01013 int imgDims = 0; 01014 if(fread(&imgDims, sizeof(int), 1, itsFile) != 1) LFATAL("fread failed"); 01015 01016 Image<float> matrixTmp(imgDims, itsImgPCADims.getVal(), NO_INIT); 01017 size_t sz = itsImgPCADims.getVal()*imgDims; 01018 if(fread(matrixTmp.beginw(), sizeof(float), sz, itsFile) != sz) LFATAL("fread failed"); 01019 01020 itsImgPCAMatrix = transpose(matrixTmp); 01021 01022 fclose(itsFile); 01023 } 01024 01025 // ###################################################################### 01026 void TaskRelevanceMapTigs2::getTigsMatrix() 01027 { 01028 FILE* itsFile = fopen(itsTigsMatrixName.getVal().c_str(), "rb"); 01029 if(itsFile == 0) 01030 PLFATAL("Can not open TigsMatrix for read Tigs coefficients"); 01031 01032 int w,h; 01033 if(fread(&h, sizeof(int), 1, itsFile) != 1) LFATAL("fread failed"); 01034 if(fread(&w, sizeof(int), 1, itsFile) != 1) LFATAL("fread failed"); 01035 01036 Image<float> matrixTmp(h, w, NO_INIT); 01037 // keep in mind that the definition of Image is Image(width, height) 01038 if(fread(matrixTmp.beginw(), sizeof(float), w*h, itsFile) != size_t(w*h)) LFATAL("fread failed"); 01039 01040 itsTigsMatrix = transpose(matrixTmp); 01041 01042 fclose(itsFile); 01043 } 01044 01045 // ###################################################################### 01046 void TaskRelevanceMapTigs2::integrate(SimEventQueue& q) 01047 { 01048 if (SeC<SimEventGistOutput> e = 01049 q.check<SimEventGistOutput>(this)) 01050 { 01051 if (itsMapComputedForCurrentFrame) 01052 return; 01053 01054 itsGist = e->gv(); 01055 01056 itsTmpTDMap = getTDMap(itsGist/10.0F); // for consistent with the training 01057 01058 if (itsCacheSize.getVal() > 0) 01059 { 01060 itsTDMap.push_back(itsTmpTDMap); 01061 if (itsFrame % itsUpdatePeriod.getVal() ==0) 01062 itsCurrentTDMap = itsTDMap.mean(); 01063 } 01064 else 01065 itsCurrentTDMap = itsTmpTDMap; 01066 01067 01068 itsMap = rescale(itsCurrentTDMap, itsMap.getDims()); 01069 01070 float mi, ma; getMinMax(itsMap, mi, ma); 01071 LINFO("\nFinal TRM range = [%.2f .. %.2f] -- 1.0 is baseline\n\n", mi, ma); 01072 01073 itsMapComputedForCurrentFrame = true; 01074 } 01075 } 01076 01077 // ###################################################################### 01078 void TaskRelevanceMapTigs2::saccadicSuppression(const bool on) 01079 { } 01080 01081 // ###################################################################### 01082 Image<float> TaskRelevanceMapTigs2:: 01083 getTDMap(Image<float> currGist) 01084 { 01085 Image<float> currGistCut(34,1,NO_INIT); 01086 Image<float> currGistPCA(itsGistPCADims.getVal(), 1, NO_INIT); 01087 Image<float> currImgPCA(itsImgPCADims.getVal(), 1, NO_INIT); 01088 Image<float> tmp(300,1, NO_INIT); //300=20x15 (Rob's cvpr 2007 paper, 32x32 for 1 block) 01089 Image<float> tmp2; 01090 01091 for(int i=0; i<34; i++) 01092 { 01093 currGistCut.setVal(i, 0, currGist.getVal(i*NUM_GIST_FEAT) ); 01094 } 01095 currGistPCA = matrixMult(currGistCut, itsGistPCAMatrix); 01096 01097 currImgPCA = matrixMult(itsCurrFrameVec, itsImgPCAMatrix); 01098 LINFO("the dim of gist is %d %d, of img is %d %d \n", 01099 currGistCut.getHeight(), currGistCut.getWidth(), 01100 itsCurrFrameVec.getHeight(), itsCurrFrameVec.getWidth()); 01101 01102 Image<float> combo = concatX(currGistPCA,currImgPCA); 01103 01104 tmp = matrixMult(combo, itsTigsMatrix); 01105 01106 tmp2 = decode(tmp); // tranfer the 20x15 dims vector to an image 01107 01108 return tmp2; 01109 } 01110 01111 // ###################################################################### 01112 Image<float> TaskRelevanceMapTigs2:: decode(Image<float> inputVec) 01113 { 01114 const int w = 20; 01115 const int h = 15; 01116 Image<float> smallTDMap(w,h,NO_INIT); 01117 Image<float> bigTDMap; 01118 01119 for(int i = 0; i< h; i++) 01120 { 01121 for(int j = 0; j < w; j++) 01122 { 01123 smallTDMap.setVal(j,i,inputVec.getVal(i*w+j,0) ); 01124 } 01125 } 01126 inplaceNormalize(smallTDMap, 1.0F, 255.0F); 01127 bigTDMap = rescale(smallTDMap,itsMap.getDims()); 01128 01129 return bigTDMap; 01130 } 01131 01132 // ###################################################################### 01133 void TaskRelevanceMapTigs2::save1(const ModelComponentSaveInfo& sinfo) 01134 { 01135 if (itsSaveResults.getVal()) 01136 { 01137 // get the OFS to save to, assuming sinfo is of type 01138 // SimModuleSaveInfo (will throw a fatal exception otherwise): 01139 nub::ref<FrameOstream> ofs = 01140 dynamic_cast<const SimModuleSaveInfo&>(sinfo).ofs; 01141 01142 ofs->writeFloat(itsCurrentTDMap, FLOAT_NORM_0_255, "TRM-SB", 01143 FrameInfo("task relevance map static buffer", SRC_POS)); 01144 } 01145 } 01146 01147 // ###################################################################### 01148 // ###################################################################### 01149 // ########## TaskRelevanceMapSocial implementation 01150 // ###################################################################### 01151 // ###################################################################### 01152 01153 // ###################################################################### 01154 TaskRelevanceMapSocial:: 01155 TaskRelevanceMapSocial(OptionManager& mgr, 01156 const std::string& descrName, 01157 const std::string& tagName) : 01158 TaskRelevanceMapAdapter(mgr, descrName, tagName), 01159 itsXMLFName(&OPT_TRMSocialRegionFName, this), 01160 itsObjectsInfo(), itsObjectsNames(), itsNumObjects(0), 01161 itsFrame(0) 01162 { } 01163 01164 // ###################################################################### 01165 void TaskRelevanceMapSocial::start1() 01166 { 01167 // copied from SVEyeRegion::start1 01168 if (itsXMLFName.getVal().empty()) 01169 LFATAL("No XML file given - use --trmsocial-input-file option with trm-social"); 01170 else 01171 { 01172 // load up the objects from the XML file 01173 itsObjectsInfo.reset(new TestImages(itsXMLFName.getVal().c_str(), 01174 TestImages::XMLFILE)); 01175 01176 // "count" the number of distinct objects by ID and get their names 01177 // this works b/c currently our script indexes objects sequentially 01178 // from 0 ... n 01179 Scene thisScene; 01180 std::string nom; 01181 for (uint i = 0; i < itsObjectsInfo->getNumScenes(); i++) 01182 { 01183 thisScene = itsObjectsInfo->getSceneData(i); 01184 for (std::vector<Object>::iterator iObj = thisScene.objects.begin(); 01185 iObj != thisScene.objects.end(); iObj++) 01186 { 01187 //if the array is too small, resize the array 01188 if((*iObj).id >= itsNumObjects) 01189 { 01190 itsNumObjects = (*iObj).id+1; 01191 itsObjectsNames.resize(itsNumObjects,std::string()); 01192 } 01193 01194 // get rid of leading and trailing underscores 01195 nom = (*iObj).name; 01196 if(!nom.empty() && (nom[nom.length()-1] == '_')) 01197 nom.erase(nom.length()-1); 01198 if(!nom.empty() && (nom[0] == '_')) nom.erase(0,1); 01199 01200 //if this is a new name, use the id to write the name 01201 if(itsObjectsNames[(*iObj).id].empty()==true) 01202 { 01203 itsObjectsNames[(*iObj).id] = nom; 01204 LINFO("assigning obj %s to obj id #%d from frame %u", 01205 nom.c_str(),(*iObj).id,i); 01206 } 01207 01208 // if this id is already used for a different object, throw an error 01209 if (itsObjectsNames[(*iObj).id].compare(nom) != 0) 01210 LFATAL("XML file %s has name conflict for object #%u, %s <-> %s", 01211 itsXMLFName.getVal().c_str(), (*iObj).id, 01212 itsObjectsNames[(*iObj).id].c_str(), nom.c_str()); 01213 } 01214 01215 } 01216 } 01217 01218 TaskRelevanceMapAdapter::start1(); 01219 } 01220 01221 // ###################################################################### 01222 TaskRelevanceMapSocial::~TaskRelevanceMapSocial() 01223 { } 01224 01225 // ###################################################################### 01226 void TaskRelevanceMapSocial::inputFrame(const InputFrame& f) 01227 { 01228 const Dims mapdims = f.getDims(); 01229 const int sml = itsLevelSpec.getVal().mapLevel(); 01230 const float EyeVal = 128.0F, MouthVal = 64.0F, FaceVal = 32.0F, BodyVal = 16.0F, PersonVal = 4.0F, BkgdVal = 1.0F; 01231 01232 Image<float> BigMap; 01233 BigMap.resize(mapdims, true); 01234 BigMap.clear(1.0F); 01235 01236 Scene sceneData = 01237 itsObjectsInfo->getSceneData(itsFrame); 01238 01239 // loop through all the regions on a given frame and assign z-stack order 01240 std::vector<float> weights(itsNumObjects, 1.0F); 01241 for (std::vector<Object>::iterator itrObject = sceneData.objects.begin(); itrObject != sceneData.objects.end(); itrObject++) { 01242 01243 uint idx = (*itrObject).id; 01244 std::string ObjName = toLowerCase(itsObjectsNames[idx]); 01245 if (ObjName.find("eye") != std::string::npos) {weights[idx] = EyeVal;} 01246 else if (ObjName.find("mouth") != std::string::npos) {weights[idx] = MouthVal;} 01247 else if (ObjName.find("head") != std::string::npos || 01248 ObjName.find("face") != std::string::npos) {weights[idx] = FaceVal;} 01249 else if (ObjName.find("body") != std::string::npos) {weights[idx] = BodyVal;} 01250 else if (ObjName.find("person") != std::string::npos || 01251 ObjName.find("people") != std::string::npos || 01252 ObjName.find("man") != std::string::npos || 01253 ObjName.find("woman") != std::string::npos) {weights[idx] = PersonVal;} 01254 else {weights[idx] = BkgdVal;} 01255 } 01256 uint i,j,tmp; 01257 // sort z-stack weights 01258 01259 const uint numInScene = sceneData.objects.size(); 01260 std::vector<uint> zorder(numInScene); 01261 for (i = 0; i < numInScene; i++) zorder[i] = i; 01262 for (i = 0; i < numInScene; i++) 01263 for (j = 0; j < numInScene-i-1; j++) 01264 if(weights[sceneData.objects[zorder[j]].id] > 01265 weights[sceneData.objects[zorder[j+1]].id]) { 01266 tmp = zorder[j]; 01267 zorder[j] = zorder[j+1]; 01268 zorder[j+1] = tmp; 01269 } 01270 01271 // fill BigMap from bottom of z-stack to top 01272 // todo: enforce C0/C1 continuity by some poisson problem? 01273 for (i = 0; i < numInScene; i++) { 01274 Object iObj = sceneData.objects[zorder[i]]; 01275 drawFilledPolygon(BigMap, iObj.polygon, weights[iObj.id]); 01276 } 01277 01278 itsMap = rescale(BigMap, mapdims.w() >> sml, mapdims.h() >> sml); 01279 itsFrame++; 01280 } 01281 01282 // ###################################################################### 01283 void TaskRelevanceMapSocial::saccadicSuppression(const bool on) 01284 { } 01285 01286 // ###################################################################### 01287 void TaskRelevanceMapSocial::integrate(SimEventQueue& q) 01288 { } 01289 01290 // ###################################################################### 01291 void TaskRelevanceMapSocial::reset1() 01292 { 01293 TaskRelevanceMapAdapter::reset1(); 01294 } 01295 01296 // ###################################################################### 01297 /* So things look consistent in everyone's emacs... */ 01298 /* Local Variables: */ 01299 /* indent-tabs-mode: nil */ 01300 /* End: */