00001 /*!@file SceneUnderstanding/IT.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/IT.C $ 00035 // $Id: IT.C 13765 2010-08-06 18:56:17Z lior $ 00036 // 00037 00038 #ifndef IT_C_DEFINED 00039 #define IT_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 "plugins/SceneUnderstanding/IT.H" 00050 #include "Neuro/EnvVisualCortex.H" 00051 #include "GUI/DebugWin.H" 00052 #include "Util/CpuTimer.H" 00053 #include <math.h> 00054 #include <fcntl.h> 00055 #include <limits> 00056 #include <string> 00057 #include <queue> 00058 00059 const ModelOptionCateg MOC_IT = { 00060 MOC_SORTPRI_3, "IT-Related Options" }; 00061 00062 const ModelOptionDef OPT_ITShowDebug = 00063 { MODOPT_ARG(bool), "ITShowDebug", &MOC_IT, OPTEXP_CORE, 00064 "Show debug img", 00065 "it-debug", '\0', "<true|false>", "false" }; 00066 00067 // ###################################################################### 00068 IT::IT(OptionManager& mgr, const std::string& descrName, 00069 const std::string& tagName) : 00070 SimModule(mgr, descrName, tagName), 00071 SIMCALLBACK_INIT(SimEventV4Output), 00072 SIMCALLBACK_INIT(SimEventSaveOutput), 00073 itsShowDebug(&OPT_ITShowDebug, this), 00074 itsObjectsDist(370.00) 00075 { 00076 00077 //Camera parameters 00078 itsCamera = Camera(Point3D<float>(0,0,0.0), 00079 Point3D<float>(0, 0,0), 00080 450, //Focal length 00081 320, //width 00082 240); //height 00083 00084 itsHashedGeonsState.set_empty_key(-1); 00085 00086 itsObjects.resize(4); 00087 00088 00089 //Add objects 00090 //House object 00091 Object houseObject; 00092 V4::GeonState geon; 00093 geon.pos = Point3D<float>(0, -15, 0); 00094 geon.rot = 0.75*M_PI; 00095 geon.geonType = V4::TRIANGLE; 00096 geon.posSigma = Point3D<float>(2, 2, 2); 00097 geon.rotSigma = 10*M_PI/180; 00098 houseObject.geons.push_back(geon); 00099 00100 geon.pos = Point3D<float>(0, 15, 0); 00101 geon.rot = 0; 00102 geon.geonType = V4::SQUARE; 00103 geon.posSigma = Point3D<float>(2, 2, 2); 00104 geon.rotSigma = 10*M_PI/180; 00105 houseObject.geons.push_back(geon); 00106 houseObject.objectType = HOUSE; 00107 itsObjects[HOUSE] = houseObject; 00108 00109 //Woman object 00110 Object womanObject; 00111 00112 geon.pos = Point3D<float>(0, -15, 0); 00113 geon.rot = 0; 00114 geon.geonType = V4::CIRCLE; 00115 geon.posSigma = Point3D<float>(2, 2, 2); 00116 geon.rotSigma = 10*M_PI/180; 00117 womanObject.geons.push_back(geon); 00118 00119 geon.pos = Point3D<float>(0, 15, 0); 00120 geon.rot = 0.75*M_PI; 00121 geon.geonType = V4::TRIANGLE; 00122 geon.posSigma = Point3D<float>(2, 2, 2); 00123 geon.rotSigma = 10*M_PI/180; 00124 womanObject.geons.push_back(geon); 00125 womanObject.objectType = WOMAN; 00126 itsObjects[WOMAN] = womanObject; 00127 00128 00129 //Hat object 00130 Object hatObject; 00131 geon.pos = Point3D<float>(0, -15, 0); 00132 geon.rot = 0.75*M_PI; 00133 geon.geonType = V4::TRIANGLE; 00134 geon.posSigma = Point3D<float>(2, 2, 2); 00135 geon.rotSigma = 10*M_PI/180; 00136 hatObject.geons.push_back(geon); 00137 00138 geon.pos = Point3D<float>(0, 15, 0); 00139 geon.rot = 0; 00140 geon.geonType = V4::CIRCLE; 00141 geon.posSigma = Point3D<float>(2, 2, 2); 00142 geon.rotSigma = 10*M_PI/180; 00143 hatObject.geons.push_back(geon); 00144 hatObject.objectType = HAT; 00145 itsObjects[HAT] = hatObject; 00146 00147 //Man object 00148 Object manObject; 00149 00150 geon.pos = Point3D<float>(0, -15, 0); 00151 geon.rot = 0; 00152 geon.geonType = V4::CIRCLE; 00153 geon.posSigma = Point3D<float>(2, 2, 2); 00154 geon.rotSigma = 10*M_PI/180; 00155 manObject.geons.push_back(geon); 00156 00157 geon.pos = Point3D<float>(0, 15, 0); 00158 geon.rot = 0; 00159 geon.geonType = V4::SQUARE; 00160 geon.posSigma = Point3D<float>(2, 2, 2); 00161 geon.rotSigma = 10*M_PI/180; 00162 manObject.geons.push_back(geon); 00163 manObject.objectType = MAN; 00164 itsObjects[MAN] = manObject; 00165 00166 buildRTables(); 00167 00168 itsObjectsParticles.resize(1000); 00169 for(uint i=0; i<itsObjectsParticles.size(); i++) 00170 { 00171 itsObjectsParticles[i].objectType = HOUSE; 00172 itsObjectsParticles[i].weight = 1.0/100.0; 00173 } 00174 00175 00176 00177 } 00178 00179 // ###################################################################### 00180 IT::~IT() 00181 { 00182 00183 } 00184 00185 // ###################################################################### 00186 void IT::buildRTables() 00187 { 00188 //Position relative to the camera 00189 for(uint objId=0; objId<itsObjects.size(); objId++) 00190 { 00191 Point3D<float> pos(0,0,itsObjectsDist); 00192 float rot = 0; 00193 00194 for(uint gid = 0; gid < itsObjects[objId].geons.size(); gid++) 00195 { 00196 V4::GeonState geonState = itsObjects[objId].geons[gid]; 00197 00198 geonState.rot += rot; 00199 float x = geonState.pos.x; 00200 float y = geonState.pos.y; 00201 float z = geonState.pos.z; 00202 geonState.pos.x = (cos(rot)*x - sin(rot)*y) + pos.x; 00203 geonState.pos.y = (sin(rot)*x + cos(rot)*y) + pos.y; 00204 geonState.pos.z = z + pos.z; 00205 00206 Point2D<int> loc = (Point2D<int>)itsCamera.project(geonState.pos); 00207 00208 RTableEntry rTableEntry; 00209 rTableEntry.geonType = geonState.geonType; 00210 rTableEntry.loc.i = loc.i - 320/2; 00211 rTableEntry.loc.j = loc.j - 240/2; 00212 rTableEntry.rot = geonState.rot; 00213 00214 itsObjects[objId].rTable.push_back(rTableEntry); 00215 } 00216 //Image<PixRGB<byte> > img(320,240,ZEROS); 00217 //showObject(img, itsObjects[objId], pos, rot); 00218 //SHOWIMG(img); 00219 } 00220 } 00221 00222 // ###################################################################### 00223 void IT::init(Dims numCells) 00224 { 00225 00226 } 00227 00228 // ###################################################################### 00229 void IT::onSimEventV4Output(SimEventQueue& q, 00230 rutz::shared_ptr<SimEventV4Output>& e) 00231 { 00232 std::vector<V4::GeonState> geonsState = e->getCells(); 00233 00234 00235 itsHashedGeonsState.clear(); 00236 00237 itsGeonsState.clear(); 00238 for(uint i=0; i<geonsState.size(); i++) 00239 { 00240 if (geonsState[i].prob > 0) 00241 { 00242 itsGeonsState.push_back(geonsState[i]); 00243 //TODO use a 3D hash key 00244 int key = i; //(int)(geonsState[i].pos.x + 1000.0*geonsState[i].pos.y); 00245 itsHashedGeonsState[key] = geonsState[i]; 00246 } 00247 } 00248 00249 evolve(); 00250 00251 //q.post(rutz::make_shared(new SimEventITOutput(this, itsFeaturesParticles))); 00252 00253 00254 } 00255 00256 // ###################################################################### 00257 void IT::onSimEventSaveOutput(SimEventQueue& q, rutz::shared_ptr<SimEventSaveOutput>& e) 00258 { 00259 if (itsShowDebug.getVal()) 00260 { 00261 // get the OFS to save to, assuming sinfo is of type 00262 // SimModuleSaveInfo (will throw a fatal exception otherwise): 00263 nub::ref<FrameOstream> ofs = 00264 dynamic_cast<const SimModuleSaveInfo&>(e->sinfo()).ofs; 00265 Layout<PixRGB<byte> > disp = getDebugImage(); 00266 ofs->writeRgbLayout(disp, "IT", FrameInfo("IT", SRC_POS)); 00267 } 00268 } 00269 00270 // ###################################################################### 00271 void IT::setInput(const std::vector<V4::GeonState> &geonsState) 00272 { 00273 itsHashedGeonsState.clear(); 00274 for(uint i=0; i<geonsState.size(); i++) 00275 { 00276 //TODO use a 3D hash key 00277 int key = i; //(int)(geonsState[i].pos.x + 1000.0*geonsState[i].pos.y); 00278 itsHashedGeonsState[key] = geonsState[i]; 00279 } 00280 00281 evolve(); 00282 } 00283 00284 // ###################################################################### 00285 void IT::showObject(Image<PixRGB<byte> > &img, Object& object, Point3D<float>& pos, float rot) 00286 { 00287 00288 PixRGB<byte> col; 00289 switch (object.objectType) 00290 { 00291 case HOUSE: col = PixRGB<byte>(255,0,0); break; 00292 case WOMAN: col = PixRGB<byte>(0,255,0); break; 00293 case HAT: col = PixRGB<byte>(0,255,255); break; 00294 case MAN: col = PixRGB<byte>(0,0,255); break; 00295 default: break; 00296 } 00297 //Position relative to the camera 00298 for(uint geonId=0; geonId<object.geons.size(); geonId++) 00299 { 00300 //Transform the object relative to the camera; 00301 V4::GeonState geonState = object.geons[geonId]; 00302 00303 geonState.rot += rot; 00304 float x = geonState.pos.x; 00305 float y = geonState.pos.y; 00306 float z = geonState.pos.z; 00307 geonState.pos.x = (cos(rot)*x - sin(rot)*y) + pos.x; 00308 geonState.pos.y = (sin(rot)*x + cos(rot)*y) + pos.y; 00309 geonState.pos.z = z + pos.z; 00310 00311 Point2D<int> loc = (Point2D<int>)itsCamera.project(geonState.pos); 00312 00313 switch(geonState.geonType) 00314 { 00315 case V4::SQUARE: 00316 drawRectOR(img, Rectangle(loc - Point2D<int>(20,20), Dims((int)40,(int)40)), 00317 col, 1, geonState.rot); 00318 break; 00319 case V4::CIRCLE: 00320 if (object.objectType != HAT) 00321 drawCircle(img, loc, 20, col); 00322 break; 00323 case V4::TRIANGLE: 00324 { 00325 std::vector<Point3D<float> > outline; 00326 outline.push_back(Point3D<float>(0.0,0, 0.0)); 00327 outline.push_back(Point3D<float>(0.0,-40.0, 0.0)); 00328 outline.push_back(Point3D<float>(40.0, 0.0, 0.0)); 00329 00330 //get the center of the object; 00331 float centerX = 0, centerY = 0, centerZ = 0; 00332 for(uint i=0; i<outline.size(); i++) 00333 { 00334 centerX += outline[i].x; 00335 centerY += outline[i].y; 00336 centerZ += outline[i].z; 00337 } 00338 centerX /= outline.size(); 00339 centerY /= outline.size(); 00340 centerZ /= outline.size(); 00341 00342 for(uint i=0; i<outline.size(); i++) 00343 outline[i] -= Point3D<float>(centerX, centerY, centerZ); 00344 00345 for(uint i=0; i<outline.size(); i++) 00346 { 00347 float x = outline[i].x; 00348 float y = outline[i].y; 00349 float z = outline[i].z; 00350 outline[i].x = (cos(geonState.rot)*x - sin(geonState.rot)*y) + geonState.pos.x; 00351 outline[i].y = (sin(geonState.rot)*x + cos(geonState.rot)*y) + geonState.pos.y; 00352 outline[i].z = z + geonState.pos.z; 00353 } 00354 00355 //Project the object to camera cordinats 00356 std::vector<Point2D<int> > points; 00357 00358 for(uint i=0; i<outline.size(); i++) 00359 { 00360 Point2D<float> loc = itsCamera.project(outline[i]); 00361 points.push_back(Point2D<int>(loc)); 00362 } 00363 00364 for(uint i=0; i<points.size(); i++) 00365 drawLine(img, points[i], points[(i+1)%points.size()], col, 1); 00366 00367 } 00368 break; 00369 } 00370 } 00371 00372 } 00373 00374 // ###################################################################### 00375 void IT::evolve() 00376 { 00377 00378 ////Resample 00379 //resampleParticles(itsObjectsParticles); 00380 proposeParticles(itsObjectsParticles, 0.0F); 00381 00382 ////Evaluate the particles; 00383 evaluateObjectParticles(itsObjectsParticles); 00384 00385 } 00386 00387 // ###################################################################### 00388 float IT::evaluateObjectParticles(std::vector<ObjectState>& objectParticles) 00389 { 00390 00391 for(uint p=0; p<objectParticles.size(); p++) 00392 getObjectLikelihood(objectParticles[p]); 00393 00394 //Normalize the particles; 00395 double sum = 0; 00396 double Neff = 0; //Number of efictive particles 00397 for(uint i=0; i<objectParticles.size(); i++) 00398 sum += objectParticles[i].prob; 00399 00400 for(uint i=0; i<objectParticles.size(); i++) 00401 { 00402 objectParticles[i].weight = objectParticles[i].prob/sum; 00403 Neff += squareOf(objectParticles[i].weight); 00404 } 00405 00406 Neff = 1/Neff; 00407 00408 00409 return Neff; 00410 00411 } 00412 00413 void IT::GHT(std::vector<GHTAcc>& accRet, OBJECT_TYPE objectType) 00414 { 00415 ImageSet<float> acc(360, Dims(320,240), ZEROS); 00416 00417 CpuTimer timer; 00418 timer.reset(); 00419 //for(int angIdx = 0; angIdx < 360; angIdx++) 00420 //{ 00421 //// jobs.push_back(rutz::make_shared(new GHTJob(this, acc[angIdx], angIdx, geonOutline.rTable))); 00422 //// itsThreadServer->enqueueJob(jobs.back()); 00423 // //voteForFeature(acc[angIdx], angIdx, geonOutline.rTable); 00424 //} 00425 00426 int angIdx = 0; 00427 voteForFeature(acc[angIdx], angIdx, itsObjects[objectType].rTable); 00428 00429 timer.mark(); 00430 LINFO("Total time %0.2f sec", timer.real_secs()); 00431 00432 00433 // Image<float> tmp(320, 240, ZEROS); 00434 // for(uint angIdx=0; angIdx<acc.size(); angIdx++) 00435 // { 00436 // for(uint i=0; i<acc[angIdx].size(); i++) 00437 // { 00438 // if (acc[angIdx].getVal(i) > tmp.getVal(i)) 00439 // tmp.setVal(i, acc[angIdx].getVal(i)); 00440 // } 00441 // } 00442 // SHOWIMG(tmp); 00443 00444 00445 for(uint rot=0; rot<acc.size(); rot++) 00446 for(int y=0; y<acc[rot].getHeight(); y++) 00447 for(int x=0; x<acc[rot].getWidth(); x++) 00448 if (acc[rot].getVal(x,y) > 0) 00449 { 00450 GHTAcc ghtAcc; 00451 ghtAcc.objectType = objectType; 00452 ghtAcc.pos = Point2D<int>(x,y); 00453 ghtAcc.ang = rot; 00454 ghtAcc.scale = -1; 00455 ghtAcc.sum = acc[rot].getVal(x,y); 00456 accRet.push_back(ghtAcc); 00457 } 00458 00459 } 00460 00461 void IT::voteForFeature(Image<float>& acc, int angIdx, std::vector<RTableEntry>& rTable) 00462 { 00463 00464 for(uint g=0; g < itsGeonsState.size(); g++) 00465 { 00466 V4::GeonState geonState = itsGeonsState[g]; 00467 if (geonState.prob > 0) 00468 { 00469 Point2D<int> loc = (Point2D<int>)itsCamera.project(geonState.pos); 00470 00471 00472 for(uint rIdx = 0; rIdx < rTable.size(); rIdx++) 00473 { 00474 if (rTable[rIdx].geonType == geonState.geonType) 00475 { 00476 float ang = angIdx * M_PI/180; 00477 00478 float featureAng = rTable[rIdx].rot + ang; 00479 if (featureAng < 0) 00480 featureAng += M_PI*2; 00481 if (featureAng > M_PI*2) 00482 featureAng -= M_PI*2; 00483 00484 float diffRot = acos(cos(geonState.rot - featureAng)); 00485 00486 float stddevRot = 1.5; 00487 int sizeRot = int(ceil(stddevRot * sqrt(-2.0F * log(exp(-5.0F))))); 00488 00489 if (fabs(diffRot) < sizeRot*M_PI/180) //TODO change to a for loop with hash 00490 { 00491 float rRot = exp(-((diffRot*diffRot)/(stddevRot*stddevRot))); 00492 00493 //Apply a variance over position and angle 00494 //TODO change to a veriance in feature position, not its endpoint 00495 float stddevX = 1.5; 00496 float stddevY = 1.5; 00497 int sizeX = int(ceil(stddevX * sqrt(-2.0F * log(exp(-5.0F))))); 00498 int sizeY = int(ceil(stddevY * sqrt(-2.0F * log(exp(-5.0F))))); 00499 00500 for(int y=loc.j-sizeY; y<loc.j+sizeY; y++) 00501 { 00502 float diffY = y-loc.j; 00503 float ry = exp(-((diffY*diffY)/(stddevY*stddevY))); 00504 for(int x=loc.i-sizeX; x<loc.i+sizeX; x++) 00505 { 00506 float diffX = x-loc.i; 00507 float rx = exp(-((diffX*diffX)/(stddevX*stddevX))); 00508 //float weight = nafState.prob + rRot*rx*ry; 00509 float weight = rRot*rx*ry; 00510 00511 int a0 = x - int(rTable[rIdx].loc.i*cos(ang) - rTable[rIdx].loc.j*sin(ang)); 00512 int b0 = y - int(rTable[rIdx].loc.i*sin(ang) + rTable[rIdx].loc.j*cos(ang)); 00513 if (acc.coordsOk(a0, b0)) 00514 { 00515 float val = acc.getVal(a0, b0); 00516 val += weight; 00517 acc.setVal(a0, b0, val); 00518 } 00519 } 00520 } 00521 } 00522 } 00523 } 00524 } 00525 } 00526 } 00527 00528 void IT::normalizeAcc(std::vector<GHTAcc>& acc) 00529 { 00530 00531 double sum = 0; 00532 for(uint i=0; i<acc.size(); i++) 00533 sum += acc[i].sum; 00534 00535 for(uint i=0; i<acc.size(); i++) 00536 acc[i].sum /= sum; 00537 } 00538 00539 // ###################################################################### 00540 Image<float> IT::showParticles(const std::vector<ObjectState>& objectParticles) 00541 { 00542 Image<float> probImg(320,240, ZEROS); 00543 00544 for(uint i=0; i<objectParticles.size(); i++) 00545 { 00546 Point2D<int> loc = (Point2D<int>)itsCamera.project(objectParticles[i].pos); 00547 if (probImg.coordsOk(loc)) 00548 probImg.setVal(loc, probImg.getVal(loc) + objectParticles[i].weight); 00549 } 00550 inplaceNormalize(probImg, 0.0F, 255.0F); 00551 00552 return probImg; 00553 00554 } 00555 00556 // ###################################################################### 00557 void IT::proposeParticles(std::vector<ObjectState>& objectParticles, const double Neff) 00558 { 00559 LINFO("Propose Particles"); 00560 00561 float probThresh = 1.0e-2; 00562 00563 //If we have good hypothisis then just adjest them 00564 uint objectsAboveProb = 0; 00565 00566 for(uint i=0; i<objectParticles.size(); i++) 00567 { 00568 if (objectParticles[i].prob > probThresh) 00569 { 00570 objectParticles[i].pos.x += randomDoubleFromNormal(1.0); 00571 objectParticles[i].pos.y += randomDoubleFromNormal(1.0); 00572 objectParticles[i].pos.z = itsObjectsDist + randomDoubleFromNormal(0.05); 00573 objectParticles[i].rot += randomDoubleFromNormal(1.0)*M_PI/180; 00574 objectParticles[i].weight = 1.0/(float)objectParticles.size(); 00575 objectsAboveProb++; 00576 } 00577 } 00578 00579 //LINFO("Objects Above prob %i/%lu", 00580 // objectsAboveProb, objectParticles.size()); 00581 00582 if (objectsAboveProb < objectParticles.size()) 00583 { 00584 00585 LINFO("GHT sampleing"); 00586 std::vector<GHTAcc> acc; 00587 GHT(acc, HOUSE); 00588 GHT(acc, WOMAN); 00589 GHT(acc, HAT); 00590 GHT(acc, MAN); 00591 //LINFO("Acc size %lu", acc.size()); 00592 LINFO("GHT Done "); 00593 00594 if (acc.size() == 0) 00595 return; 00596 normalizeAcc(acc); 00597 00598 std::priority_queue <GHTAcc> pAcc; 00599 for(uint i=0; i<acc.size(); i++) 00600 pAcc.push(acc[i]); 00601 00602 ////Sample from acc 00603 for(uint i=0; i<objectParticles.size(); i++) 00604 { 00605 if (objectParticles[i].prob <= probThresh) 00606 { 00607 //add this point to the list 00608 if (pAcc.empty()) 00609 break; 00610 GHTAcc p = pAcc.top(); pAcc.pop(); 00611 00612 Point3D<float> iPoint = itsCamera.inverseProjection(Point2D<float>(p.pos), itsObjectsDist); 00613 objectParticles[i].pos.x = iPoint.x + randomDoubleFromNormal(1); 00614 objectParticles[i].pos.y = iPoint.y + randomDoubleFromNormal(1); 00615 objectParticles[i].pos.z = itsObjectsDist + randomDoubleFromNormal(0.05); 00616 objectParticles[i].rot = (p.ang + randomDoubleFromNormal(1))*M_PI/180; 00617 objectParticles[i].objectType = p.objectType; 00618 objectParticles[i].weight = 1.0/(float)objectParticles.size(); 00619 objectParticles[i].prob = 1.0e-50; 00620 } 00621 } 00622 } 00623 } 00624 00625 // ###################################################################### 00626 void IT::resampleParticles(std::vector<ObjectState>& objectParticles) 00627 { 00628 LINFO("Resample"); 00629 00630 std::vector<ObjectState> newParticles; 00631 00632 //Calculate a Cumulative Distribution Function for our particle weights 00633 std::vector<double> CDF; 00634 CDF.resize(objectParticles.size()); 00635 00636 CDF.at(0) = objectParticles.at(0).weight; 00637 for(uint i=1; i<CDF.size(); i++) 00638 CDF.at(i) = CDF.at(i-1) + objectParticles.at(i).weight; 00639 00640 uint i = 0; 00641 double u = randomDouble()* 1.0/double(objectParticles.size()); 00642 00643 for(uint j=0; j < objectParticles.size(); j++) 00644 { 00645 while(u > CDF.at(i)) 00646 i++; 00647 00648 ObjectState p = objectParticles.at(i); 00649 p.weight = 1.0/double(objectParticles.size()); 00650 newParticles.push_back(p); 00651 00652 u += 1.0/double(objectParticles.size()); 00653 } 00654 00655 objectParticles = newParticles; 00656 00657 } 00658 00659 // ###################################################################### 00660 void IT::getObjectLikelihood(ObjectState& objectState) 00661 { 00662 00663 Object object = itsObjects[objectState.objectType]; 00664 Point2D<int> loc = (Point2D<int>)itsCamera.project(objectState.pos); 00665 float rot = objectState.rot + M_PI; 00666 00667 00668 double totalProb = 1; 00669 00670 for(uint rIdx=0; rIdx<object.rTable.size(); rIdx++) 00671 { 00672 float ang = rot; 00673 float a0 = loc.i - (object.rTable[rIdx].loc.i*cos(ang) - object.rTable[rIdx].loc.j*sin(ang)); 00674 float b0 = loc.j - (object.rTable[rIdx].loc.i*sin(ang) + object.rTable[rIdx].loc.j*cos(ang)); 00675 00676 //Get the expected geon 00677 V4::GeonState geonState; 00678 geonState.pos = itsCamera.inverseProjection(Point2D<float>(a0,b0), itsObjectsDist); 00679 geonState.rot = rot + object.rTable[rIdx].rot + M_PI; 00680 geonState.geonType = object.rTable[rIdx].geonType; 00681 geonState.prob = -1; 00682 00683 while (geonState.rot < 0) 00684 geonState.rot += M_PI*2; 00685 while(geonState.rot > M_PI*2) 00686 geonState.rot -= M_PI*2; 00687 00688 00689 //Find the closest naf 00690 int nearPart = 0; 00691 float partDist = 1.0e100; 00692 for(uint i=0; i<itsGeonsState.size(); i++) 00693 { 00694 if (itsGeonsState[i].prob > 0) 00695 { 00696 float distance = geonState.distance(itsGeonsState[i]); 00697 if (distance < partDist) 00698 { 00699 partDist = distance; 00700 nearPart = i; 00701 } 00702 } 00703 } 00704 00705 float sig = 0.75F; 00706 float prob = (1.0F/(sig*sqrt(2*M_PI))*exp(-0.5*squareOf(partDist)/squareOf(sig))); 00707 // LINFO("Dist %f %e", partDist, prob); 00708 totalProb *= prob; 00709 } 00710 00711 // LINFO("Total prob : %e", totalProb); 00712 00713 objectState.prob = totalProb; 00714 00715 00716 } 00717 // ###################################################################### 00718 void IT::fixAngle(float& ang) 00719 { 00720 if (ang > M_PI) 00721 ang -= 2*M_PI; 00722 00723 if (ang < M_PI) 00724 ang += 2*M_PI; 00725 } 00726 00727 00728 // ###################################################################### 00729 V4::GeonState IT::findNearestGeon(const V4::GeonState& geonState) 00730 { 00731 00732 V4::GeonState nearestGeon; 00733 nearestGeon.prob = -1; 00734 float minDistance = 1.0e100; 00735 00736 dense_hash_map<int, V4::GeonState>::const_iterator iter; 00737 for(iter = itsHashedGeonsState.begin(); iter != itsHashedGeonsState.end(); iter++) 00738 { 00739 if (geonState.geonType == iter->second.geonType && iter->second.prob > 0.5) 00740 { 00741 00742 //geon distance 00743 float dist = getGeonDistance(geonState, iter->second); 00744 if (dist < minDistance) 00745 { 00746 minDistance = dist; 00747 nearestGeon = iter->second; 00748 } 00749 } 00750 } 00751 00752 return nearestGeon; 00753 } 00754 00755 // ###################################################################### 00756 double IT::getGeonDistance(const V4::GeonState& g1, const V4::GeonState& g2) 00757 { 00758 00759 double posDist = g1.pos.squdist(g2.pos); 00760 double rotDist = 0; 00761 00762 return sqrt(posDist + rotDist); 00763 00764 } 00765 00766 // ###################################################################### 00767 Layout<PixRGB<byte> > IT::getDebugImage() 00768 { 00769 Layout<PixRGB<byte> > outDisp; 00770 00771 //Show the gabor states 00772 Image<float> perc(320,240, ZEROS); 00773 00774 Image<PixRGB<byte> > objectDisp = toRGB(Image<byte>(perc)); 00775 00776 //for(uint i=0; i<itsObjectsParticles.size(); i++) 00777 //{ 00778 // if (itsObjectsParticles[i].weight > 0) 00779 // { 00780 // Object object=itsObjects[itsObjectsParticles[i].objectType]; 00781 // ObjectState objectState = itsObjectsParticles[i]; 00782 // showObject(objectDisp, object, objectState.pos, objectState.rot); 00783 00784 // Point2D<int> textLoc = (Point2D<int>)itsCamera.project(objectState.pos); 00785 // 00786 // char msg[255]; 00787 // msg[0] = NULL; 00788 // switch (itsObjectsParticles[i].objectType) 00789 // { 00790 // case HOUSE: sprintf(msg, "HOUSE"); break; 00791 // case WOMAN: sprintf(msg, "WOMAN"); break; 00792 // case HAT: sprintf(msg, "HAT"); textLoc.j -= 15; break; 00793 // case MAN: sprintf(msg, "MAN"); break; 00794 // default: 00795 // break; 00796 // } 00797 // writeText(objectDisp, textLoc, msg, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0)); 00798 // 00799 // } 00800 //} 00801 00802 00803 //Show only the max object from each type 00804 for(uint obj = 0; obj < itsObjects.size(); obj++) 00805 { 00806 int maxObj = -1; 00807 float max = 0; 00808 00809 for(uint i=0; i<itsObjectsParticles.size(); i++) 00810 { 00811 if (itsObjectsParticles[i].weight > 0 && itsObjectsParticles[i].objectType == itsObjects[obj].objectType) 00812 { 00813 if (itsObjectsParticles[i].weight > max) 00814 { 00815 max = itsObjectsParticles[i].weight; 00816 maxObj = i; 00817 } 00818 } 00819 } 00820 00821 //Show the max object 00822 if (maxObj != -1) 00823 { 00824 Object object=itsObjects[itsObjectsParticles[maxObj].objectType]; 00825 ObjectState objectState = itsObjectsParticles[maxObj]; 00826 showObject(objectDisp, object, objectState.pos, objectState.rot); 00827 00828 Point2D<int> textLoc = (Point2D<int>)itsCamera.project(objectState.pos); 00829 textLoc.i -= 10; 00830 00831 char msg[255]; 00832 msg[0] = 0; 00833 switch (itsObjectsParticles[maxObj].objectType) 00834 { 00835 case HOUSE: sprintf(msg, "HOUSE"); break; 00836 case WOMAN: sprintf(msg, "WOMAN"); break; 00837 case HAT: sprintf(msg, "HAT"); textLoc.j -= 20; break; 00838 case MAN: sprintf(msg, "MAN"); break; 00839 default: 00840 break; 00841 } 00842 writeText(objectDisp, textLoc, msg, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0)); 00843 00844 } 00845 00846 } 00847 00848 00849 Image<float> particles = showParticles(itsObjectsParticles); 00850 00851 char msg[255]; 00852 sprintf(msg, "IT"); 00853 writeText(objectDisp, Point2D<int>(0,0), msg, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0)); 00854 00855 outDisp = hcat(objectDisp, toRGB(Image<byte>(particles))); 00856 00857 return outDisp; 00858 00859 } 00860 00861 // ###################################################################### 00862 /* So things look consistent in everyone's emacs... */ 00863 /* Local Variables: */ 00864 /* indent-tabs-mode: nil */ 00865 /* End: */ 00866 00867 #endif 00868