00001 /*!@file SceneUnderstanding/V4d.C non-accidental features */ 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/V4d.C $ 00035 // $Id: V4d.C 13551 2010-06-10 21:56:32Z itti $ 00036 // 00037 00038 #ifndef V4d_C_DEFINED 00039 #define V4d_C_DEFINED 00040 00041 #include "plugins/SceneUnderstanding/V4d.H" 00042 00043 #include "Image/DrawOps.H" 00044 #include "Image/MathOps.H" 00045 #include "Image/Kernels.H" 00046 #include "Image/FilterOps.H" 00047 #include "Image/Convolutions.H" 00048 #include "Image/fancynorm.H" 00049 #include "Image/Point3D.H" 00050 #include "SIFT/FeatureVector.H" 00051 #include "Simulation/SimEventQueue.H" 00052 #include "Neuro/EnvVisualCortex.H" 00053 #include "GUI/DebugWin.H" 00054 #include "Util/CpuTimer.H" 00055 #include "Util/JobServer.H" 00056 #include "Util/JobWithSemaphore.H" 00057 #include <math.h> 00058 #include <fcntl.h> 00059 #include <limits> 00060 #include <string> 00061 00062 const ModelOptionCateg MOC_V4d = { 00063 MOC_SORTPRI_3, "V4d-Related Options" }; 00064 00065 // Used by: SimulationViewerEyeMvt 00066 const ModelOptionDef OPT_V4dShowDebug = 00067 { MODOPT_ARG(bool), "V4dShowDebug", &MOC_V4d, OPTEXP_CORE, 00068 "Show debug img", 00069 "v4d-debug", '\0', "<true|false>", "false" }; 00070 00071 namespace 00072 { 00073 class GHTJob : public JobWithSemaphore 00074 { 00075 public: 00076 GHTJob(V4d* v4d, Image<float>& acc, int angIdx, std::vector<V1::EdgeState>& rTable) : 00077 itsV4d(v4d), 00078 itsAcc(acc), 00079 itsAngIdx(angIdx), 00080 itsRTable(rTable) 00081 {} 00082 00083 virtual ~GHTJob() {} 00084 00085 virtual void run() 00086 { 00087 itsV4d->voteForFeature(itsAcc, itsAngIdx, itsRTable); 00088 00089 this->markFinished(); 00090 } 00091 00092 virtual const char* jobType() const { return "GHTJob"; } 00093 V4d* itsV4d; 00094 Image<float>& itsAcc; 00095 int itsAngIdx; 00096 std::vector<V1::EdgeState>& itsRTable; 00097 }; 00098 00099 class LikelihoodJob : public JobWithSemaphore 00100 { 00101 public: 00102 LikelihoodJob(V4d* v4d, V4d::NAFState& nafState) : 00103 itsV4d(v4d), 00104 itsNAFState(nafState) 00105 {} 00106 00107 virtual ~LikelihoodJob() {} 00108 00109 virtual void run() 00110 { 00111 itsV4d->getParticleLikelihood(itsNAFState); 00112 this->markFinished(); 00113 } 00114 00115 virtual const char* jobType() const { return "LikelihoodJob"; } 00116 00117 V4d* itsV4d; 00118 V4d::NAFState& itsNAFState; 00119 00120 00121 }; 00122 } 00123 00124 00125 // ###################################################################### 00126 V4d::V4d(OptionManager& mgr, const std::string& descrName, 00127 const std::string& tagName) : 00128 SimModule(mgr, descrName, tagName), 00129 SIMCALLBACK_INIT(SimEventV2Output), 00130 SIMCALLBACK_INIT(SimEventSaveOutput), 00131 SIMCALLBACK_INIT(SimEventUserInput), 00132 SIMCALLBACK_INIT(SimEventV4BiasOutput), 00133 itsShowDebug(&OPT_V4dShowDebug, this), 00134 itsMaxVal(0), 00135 itsGHTAngStep(1), 00136 itsObjectsDist(370.00) 00137 { 00138 00139 itsThreadServer.reset(new WorkThreadServer("V4d", 100)); 00140 00141 //Camera parameters 00142 itsCamera = Camera(Point3D<float>(0,0,0.0), 00143 Point3D<float>(0, 0,0), 00144 450, //Focal length 00145 320, //width 00146 240); //height 00147 00148 // ///NAF 00149 itsNAFeatures.resize(3); 00150 00151 00152 FeatureTemplate rightVertixFeature; 00153 rightVertixFeature.featureType = RIGHT_VERTIX; 00154 rightVertixFeature.outline.push_back(Point3D<float>(11.0,0.0, 0.0)); 00155 rightVertixFeature.outline.push_back(Point3D<float>(0.0,0, 0.0)); 00156 rightVertixFeature.outline.push_back(Point3D<float>(0.0,11.0, 0.0)); 00157 00158 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(0,4), 0)); 00159 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(0,5), 0)); 00160 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(0,6), 0)); 00161 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(0,7), 0)); 00162 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(0,8), 0)); 00163 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(0,9), 0)); 00164 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(0,10), 0)); 00165 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(0,11), 0)); 00166 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(0,12), 0)); 00167 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(4,0), M_PI/2)); 00168 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(5,0), M_PI/2)); 00169 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(6,0), M_PI/2)); 00170 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(7,0), M_PI/2)); 00171 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(8,0), M_PI/2)); 00172 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(9,0), M_PI/2)); 00173 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(10,0), M_PI/2)); 00174 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(11,0), M_PI/2)); 00175 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(12,0), M_PI/2)); 00176 00177 alignToCenterOfMass(rightVertixFeature); 00178 itsNAFeatures[RIGHT_VERTIX] = rightVertixFeature; 00179 00180 FeatureTemplate vertixFeature; 00181 vertixFeature.featureType = VERTIX; 00182 vertixFeature.outline.push_back(Point3D<float>(0.0,0, 0.0)); 00183 vertixFeature.outline.push_back(Point3D<float>(0.0,11.0, 0.0)); 00184 vertixFeature.outline.push_back(Point3D<float>(11.0,0.0, 0.0)); 00185 00186 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(5,0), M_PI/2)); 00187 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(6,0), M_PI/2)); 00188 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(7,0), M_PI/2)); 00189 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(8,0), M_PI/2)); 00190 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(9,0), M_PI/2)); 00191 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(10,0), M_PI/2)); 00192 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(11,0), M_PI/2)); 00193 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(12,0), M_PI/2)); 00194 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(13,0), M_PI/2)); 00195 00196 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(5,-5), -M_PI/4)); 00197 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(6,-6), -M_PI/4)); 00198 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(7,-7), -M_PI/4)); 00199 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(8,-8), -M_PI/4)); 00200 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(9,-9), -M_PI/4)); 00201 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(10,-10), -M_PI/4)); 00202 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(11,-11), -M_PI/4)); 00203 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(12,-12), -M_PI/4)); 00204 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(13,-13), -M_PI/4)); 00205 00206 alignToCenterOfMass(vertixFeature); 00207 itsNAFeatures[VERTIX] = vertixFeature; 00208 00209 FeatureTemplate arcFeature; 00210 arcFeature.featureType = ARC; 00211 arcFeature.outline.push_back(Point3D<float>(0.0,0, 0.0)); 00212 arcFeature.outline.push_back(Point3D<float>(5.0,0.0, 0.0)); 00213 00214 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(5,0), 1.885212)); 00215 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(3,1), 2.082733)); 00216 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(4,1), 1.941421)); 00217 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(5,1), 1.841154)); 00218 00219 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(1,2), 2.076972)); 00220 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(2,2), 1.954276)); 00221 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(3,2), 1.959018)); 00222 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(4,2), 1.903953)); 00223 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(5,2), 1.816486)); 00224 00225 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(0,3), 2.045129)); 00226 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(1,3), 2.006197)); 00227 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(2,3), 1.965587)); 00228 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(3,3), 1.968628)); 00229 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(4,3), 1.873842)); 00230 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(5,3), 1.809913)); 00231 00232 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(0,4), 1.992570)); 00233 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(1,4), 1.990212)); 00234 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(2,4), 2.023316)); 00235 00236 00237 alignToCenterOfMass(arcFeature); 00238 itsNAFeatures[ARC] = arcFeature; 00239 00240 //Image<float> tmp(320,240, ZEROS); 00241 //for(uint i=0; i<vertixFeature.edges.size(); i++) 00242 //{ 00243 // LINFO("%i %i %f", 00244 // vertixFeature.edges[i].pos.i, 00245 // vertixFeature.edges[i].pos.j, 00246 // vertixFeature.edges[i].ori + M_PI/2); 00247 // drawLine(tmp, vertixFeature.edges[i].pos + Point2D<int>(320/2,240/2), vertixFeature.edges[i].ori + M_PI/2, 5.0F, 30.0F); 00248 //} 00249 //SHOWIMG(tmp); 00250 00251 buildRTables(); 00252 itsFeaturesParticles.resize(1000); 00253 for(uint i=0; i<itsFeaturesParticles.size(); i++) 00254 { 00255 itsFeaturesParticles[i].pos = Point3D<float>(-53.444447,0.000000,370.000000); 00256 itsFeaturesParticles[i].rot = 35*M_PI/180; 00257 //itsFeaturesParticles[i].pos = Point3D<float>(0,0,370); 00258 itsFeaturesParticles[i].featureType = VERTIX; 00259 itsFeaturesParticles[i].weight = 1.0/double(itsFeaturesParticles.size()); 00260 itsFeaturesParticles[i].prob = 0; 00261 } 00262 00263 itsHashedEdgesState.set_empty_key(-1); 00264 00265 itsDebugImg = Image<PixRGB<byte> >(320,240,ZEROS); 00266 } 00267 00268 // ###################################################################### 00269 V4d::~V4d() 00270 { 00271 00272 } 00273 00274 00275 // ###################################################################### 00276 void V4d::alignToCenterOfMass(FeatureTemplate& featureTemplate) 00277 { 00278 //Set the 0,0 location around the center of mass 00279 //get the center of the object; 00280 float centerX = 0, centerY = 0, centerZ = 0; 00281 for(uint i=0; i<featureTemplate.outline.size(); i++) 00282 { 00283 centerX += featureTemplate.outline[i].x; 00284 centerY += featureTemplate.outline[i].y; 00285 centerZ += featureTemplate.outline[i].z; 00286 } 00287 centerX /= featureTemplate.outline.size(); 00288 centerY /= featureTemplate.outline.size(); 00289 centerZ /= featureTemplate.outline.size(); 00290 00291 for(uint i=0; i<featureTemplate.outline.size(); i++) 00292 featureTemplate.outline[i] -= Point3D<float>(centerX, centerY, centerZ); 00293 00294 } 00295 00296 00297 // ###################################################################### 00298 void V4d::buildRTables() 00299 { 00300 for(uint fid=0; fid<itsNAFeatures.size(); fid++) 00301 { 00302 if (itsNAFeatures[fid].outline.size() > 0) 00303 { 00304 NAFState naFeature; 00305 naFeature.pos = Point3D<float>(0, 0, itsObjectsDist); 00306 naFeature.rot = 0; 00307 naFeature.featureType = (NAF_TYPE)fid; 00308 naFeature.prob = 0; 00309 00310 std::vector<Point2D<int> > outline = getImageOutline(naFeature); 00311 Image<float> tmp(320,240, ZEROS); 00312 for(uint i=0; i<outline.size()-1; i++) 00313 drawLine(tmp, outline[i], outline[i+1], 1.0F, 1); 00314 00315 //build R table 00316 for(int x=0; x<tmp.getWidth(); x+=1) 00317 for(int y=0; y<tmp.getHeight(); y+=1) 00318 { 00319 if (tmp.getVal(x,y) == 1.0) 00320 { 00321 int rx = x-tmp.getWidth()/2; 00322 int ry = y-tmp.getHeight()/2; 00323 00324 RTableEntry rTableEntry; 00325 rTableEntry.loc = Point2D<int>(rx, ry); 00326 rTableEntry.rot = atan2(ry, rx); 00327 itsNAFeatures[fid].rTable.push_back(rTableEntry); 00328 } 00329 } 00330 } 00331 } 00332 } 00333 00334 // ###################################################################### 00335 void V4d::onSimEventV4BiasOutput(SimEventQueue& q, 00336 rutz::shared_ptr<SimEventV4BiasOutput>& e) 00337 { 00338 itsBias = e->getCells(); 00339 //LINFO("Got bias of size %lu", itsBias.size()); 00340 } 00341 00342 // ###################################################################### 00343 void V4d::onSimEventV2Output(SimEventQueue& q, 00344 rutz::shared_ptr<SimEventV2Output>& e) 00345 { 00346 std::vector<V1::EdgeState> edgesState; // = e->getEdges(); 00347 std::vector<V2::CornerState> cornersState = e->getCorners(); 00348 itsEdgesState = edgesState; 00349 00350 LINFO("Build priority queue for corners"); 00351 //Corners queue should be empty (We get all corners during proposals) 00352 ASSERT(cornersState.size()); 00353 for(uint i=0; i<cornersState.size(); i++) 00354 itsCornersState.push(cornersState[i]); 00355 00356 //LINFO("Found %lu corners\n", 00357 // itsCornersState.size()); 00358 00359 Image<float> tmp(320,240,ZEROS); 00360 itsHashedEdgesState.clear(); 00361 for(uint i=0; i<edgesState.size(); i++) 00362 { 00363 int key = edgesState[i].pos.i + 320*edgesState[i].pos.j; 00364 tmp.setVal(edgesState[i].pos, edgesState[i].prob); 00365 itsHashedEdgesState[key] = edgesState[i]; 00366 } 00367 //SHOWIMG(tmp); 00368 00369 //evolveSift(); 00370 evolve(); 00371 00372 //q.post(rutz::make_shared(new SimEventV4dOutput(this, itsFeaturesParticles))); 00373 00374 } 00375 00376 // ###################################################################### 00377 void V4d::onSimEventSaveOutput(SimEventQueue& q, rutz::shared_ptr<SimEventSaveOutput>& e) 00378 { 00379 if (itsShowDebug.getVal()) 00380 { 00381 // get the OFS to save to, assuming sinfo is of type 00382 // SimModuleSaveInfo (will throw a fatal exception otherwise): 00383 nub::ref<FrameOstream> ofs = 00384 dynamic_cast<const SimModuleSaveInfo&>(e->sinfo()).ofs; 00385 Layout<PixRGB<byte> > disp = getDebugImage(); 00386 ofs->writeRgbLayout(disp, "V4d", FrameInfo("V4d", SRC_POS)); 00387 00388 //ofs->writeRGB(itsDebugImg, "V4dDebug", FrameInfo("V4dDebug", SRC_POS)); 00389 } 00390 } 00391 00392 // ###################################################################### 00393 void V4d::onSimEventUserInput(SimEventQueue& q, rutz::shared_ptr<SimEventUserInput>& e) 00394 { 00395 00396 LINFO("Got event %s %ix%i key=%i", 00397 e->getWinName(), 00398 e->getMouseClick().i, 00399 e->getMouseClick().j, 00400 e->getKey()); 00401 00402 Image<float> mag(320,240,ZEROS); 00403 Image<float> ori(320,240,ZEROS); 00404 00405 Point2D<int> loc = e->getMouseClick(); 00406 00407 if (loc.i > 320) 00408 loc.i -= 320; 00409 //Draw the edges 00410 for(uint i=0; i<itsEdgesState.size(); i++) 00411 { 00412 mag.setVal(itsEdgesState[i].pos, itsEdgesState[i].prob); 00413 ori.setVal(itsEdgesState[i].pos, itsEdgesState[i].ori); 00414 } 00415 00416 //Histogram OV(360); 00417 //float mainOri = calculateOrientationVector(loc, OV); 00418 //LINFO("Main ori %f", mainOri); 00419 00420 //createDescriptor(loc, OV, 0); 00421 00422 Image<float> magC = crop(mag, loc - 10, Dims(20,20)); 00423 Image<float> oriC = crop(ori, loc - 10, Dims(20,20)); 00424 //oriC *= 180.0/M_PI; 00425 00426 for(int y=0; y<oriC.getHeight(); y++) 00427 for(int x=0; x<oriC.getWidth(); x++) 00428 { 00429 if (magC.getVal(x,y) > 0.1) 00430 printf("%i ", (int)(oriC.getVal(x,y)*180/M_PI + 90)); 00431 } 00432 printf("\n"); 00433 00434 double sumSin = 0, sumCos = 0; 00435 float numElem = 0; 00436 for(uint i=0; i<oriC.size(); i++) 00437 { 00438 if (magC[i] > 0.1) 00439 { 00440 printf("%0.1f ", oriC[i]*180/M_PI+90); 00441 sumSin += sin(oriC[i]+ M_PI/2); 00442 sumCos += cos(oriC[i] + M_PI/2); 00443 numElem++; 00444 } 00445 } 00446 double sum = sqrt( squareOf(sumSin/numElem) + squareOf(sumCos/numElem)); 00447 printf("\n"); 00448 LINFO("sin %f cos %f Var %f", sumSin, sumCos, sum); 00449 00450 00451 SHOWIMG(magC); 00452 SHOWIMG(oriC); 00453 00454 //Image<float> magN = maxNormalize(magC, 0.0F, 1.0F, VCXNORM_FANCYONE); 00455 //Image<float> oriN = maxNormalize(oriC, 0.0F, 1.0F, VCXNORM_FANCYONE); 00456 00457 //for(uint i=0; i<oriN.size(); i++) 00458 //{ 00459 // if (oriN[i] > 0.1) 00460 // magC[i] = 128; 00461 //} 00462 // 00463 //SHOWIMG(magN); 00464 //SHOWIMG(oriC); 00465 //SHOWIMG(oriN); 00466 //SHOWIMG(magC); 00467 00468 00469 //if (e->getMouseClick().isValid()) 00470 //{ 00471 // Point3D<float> iPoint = itsCamera.inverseProjection((Point2D<float>)e->getMouseClick(), itsObjectsDist); 00472 // itsFeaturesParticles[0].pos = iPoint; 00473 //} 00474 00475 //switch(e->getKey()) 00476 //{ 00477 // case 98: itsFeaturesParticles[0].rot += 5*M_PI/180; break; 00478 // case 104: itsFeaturesParticles[0].rot -= 5*M_PI/180; break; 00479 //} 00480 00481 //itsFeaturesParticles[0].featureType = VERTIX; 00482 //itsFeaturesParticles[0].weight = 1.0/double(itsFeaturesParticles.size()); 00483 //itsFeaturesParticles[0].prob = 0; 00484 00485 } 00486 00487 // ###################################################################### 00488 void V4d::evolveSift() 00489 { 00490 Image<float> tmp(320,240,ZEROS); 00491 00492 dense_hash_map<int, V1::EdgeState>::const_iterator iter; 00493 for(iter = itsHashedEdgesState.begin(); iter != itsHashedEdgesState.end(); iter++) 00494 { 00495 V1::EdgeState edgeState = iter->second; 00496 00497 if (edgeState.prob > 0) 00498 { 00499 tmp.setVal(edgeState.pos, edgeState.prob); 00500 // Histogram OV(36); 00501 00502 // calculateOrientationVector(edgeState.pos, OV); 00503 // //LINFO("Main ori %f", mainOri); 00504 00505 // createDescriptor(edgeState.pos, OV, 0); 00506 } 00507 } 00508 LINFO("Done"); 00509 SHOWIMG(tmp); 00510 00511 IplImage* img = img2ipl(tmp); 00512 IplImage* hImg = cvCreateImage( cvSize(img->width, img->height), IPL_DEPTH_32F, 1 ); 00513 00514 cvCornerHarris(img, hImg, 5, 5, 0); 00515 SHOWIMG(ipl2float(hImg)); 00516 00517 00518 SHOWIMG(ipl2float(hImg)); 00519 00520 //Point2D<int> loc(68,81); 00521 // Point2D<int> loc(127,127); 00522 // Histogram OV(36); 00523 // 00524 // float mainOri = calculateOrientationVector(loc, OV); 00525 // LINFO("Main ori %f", mainOri); 00526 // 00527 // createDescriptor(loc, OV, 0); 00528 00529 } 00530 00531 float V4d::createDescriptor(Point2D<int>& loc, Histogram& OV, float mainOri) 00532 { 00533 //TODO hash me 00534 Image<float> perc(320,240, ZEROS); 00535 Image<float> ori(320,240, ZEROS); 00536 dense_hash_map<int, V1::EdgeState>::const_iterator iter; 00537 for(iter = itsHashedEdgesState.begin(); iter != itsHashedEdgesState.end(); iter++) 00538 { 00539 V1::EdgeState edgeState = iter->second; 00540 perc.setVal(edgeState.pos, edgeState.prob); 00541 ori.setVal(edgeState.pos, edgeState.ori + M_PI/2); 00542 } 00543 00544 00545 float s = 1.5; 00546 // compute the effective blurring sigma corresponding to the 00547 // fractional scale s: 00548 const float sigma = 2; 00549 00550 const int xi = int(loc.i + 0.5f); 00551 const int yi = int(loc.j + 0.5f); 00552 00553 00554 const float sinAngle = sin(mainOri), cosAngle = cos(mainOri); 00555 00556 // check this scale 00557 const int radius = int(5.0F * sigma + 0.5F); // NOTE: Lowe uses radius=8? 00558 const float gausssig = float(radius); // 1/2 width of descript window 00559 const float gaussfac = - 0.5F / (gausssig * gausssig); 00560 00561 // Scan a window of diameter 2*radius+1 around the point of 00562 // interest, and we will cumulate local samples into a 4x4 grid 00563 // of bins, with interpolation. NOTE: rx and ry loop over a 00564 // square that is assumed centered around the point of interest 00565 // and rotated to the gradient orientation (realangle): 00566 00567 int scale = abs(int(s)); 00568 scale = scale > 5 ? 5 : scale; 00569 00570 FeatureVector fv; 00571 00572 Image<float> tmp(radius*2+1, radius*2+1, ZEROS); 00573 for (int ry = -radius; ry <= radius; ry++) 00574 for (int rx = -radius; rx <= radius; rx++) 00575 { 00576 // rotate the point: 00577 const float newX = rx * cosAngle - ry * sinAngle; 00578 const float newY = rx * sinAngle + ry * cosAngle; 00579 00580 // get the coords in the image frame of reference: 00581 const float orgX = newX + float(xi); 00582 const float orgY = newY + float(yi); 00583 00584 // if outside the image, forget it: 00585 if (perc.coordsOk(orgX, orgY) == false) continue; 00586 00587 //LINFO("%i %i %i", rx, ry, radius*2); 00588 tmp.setVal(rx+radius, ry+radius, perc.getValInterp(orgX, orgY)); 00589 00590 // find the fractional coords of the corresponding bin 00591 // (we subdivide our window into a 4x4 grid of bins): 00592 const float xf = 2.0F + 2.0F * float(rx) / float(radius); 00593 const float yf = 2.0F + 2.0F * float(ry) / float(radius); 00594 00595 00596 // find the Gaussian weight from distance to center and 00597 // get weighted gradient magnitude: 00598 const float gaussFactor = expf((newX*newX+newY*newY) * gaussfac); 00599 const float weightedMagnitude = 00600 gaussFactor * perc.getValInterp(orgX, orgY); 00601 00602 // get the gradient orientation relative to the keypoint 00603 // orientation and scale it for 8 orientation bins: 00604 float gradAng = ori.getValInterp(orgX, orgY) - mainOri; 00605 00606 gradAng=fmod(gradAng, 2*M_PI); //bring the range from 0 to M_PI 00607 00608 //convert from -M_PI to M_PI 00609 if (gradAng < 0.0) gradAng+=2*M_PI; //convert to -M_PI to M_PI 00610 if (gradAng >= M_PI) gradAng-=2*M_PI; 00611 //split to eight bins 00612 const float orient = (gradAng + M_PI) * 8 / (2 * M_PI); 00613 00614 /* 00615 //reflect the angle to convert from 0 to M_PI 00616 if (gradAng >= M_PI) gradAng-=M_PI; 00617 //split to four bins 00618 const float orient = (gradAng + M_PI) * 4 / (2 * M_PI); 00619 */ 00620 00621 // will be interpolated into 2 x 2 x 2 bins: 00622 fv.addValue(xf, yf, orient, weightedMagnitude); 00623 00624 00625 } 00626 SHOWIMG(tmp); 00627 00628 // normalize, clamp, scale and convert to byte: 00629 std::vector<byte> oriVec; 00630 fv.toByteKey(oriVec); 00631 00632 SHOWIMG(fv.getFeatureVectorImage(oriVec)); 00633 00634 return 0; 00635 } 00636 00637 float V4d::calculateOrientationVector(Point2D<int>& loc, Histogram& OV) 00638 { 00639 00640 //TODO hash me 00641 Image<float> perc(320,240, ZEROS); 00642 Image<float> ori(320,240, ZEROS); 00643 dense_hash_map<int, V1::EdgeState>::const_iterator iter; 00644 for(iter = itsHashedEdgesState.begin(); iter != itsHashedEdgesState.end(); iter++) 00645 { 00646 V1::EdgeState edgeState = iter->second; 00647 perc.setVal(edgeState.pos, edgeState.prob); 00648 ori.setVal(edgeState.pos, edgeState.ori); 00649 } 00650 00651 int histSize = 36; 00652 00653 // compute the effective blurring sigma corresponding to the 00654 // fractional scale s: 00655 const float sigma = 1; 00656 00657 const float sig = 1.5F * sigma, inv2sig2 = - 0.5F / (sig * sig); 00658 const int dimX = perc.getWidth(), dimY = perc.getHeight(); 00659 00660 const int xi = int(loc.i + 0.5f); 00661 const int yi = int(loc.j + 0.5f); 00662 00663 const int rad = int(3.0F * sig); 00664 const int rad2 = rad * rad; 00665 00666 // search bounds: 00667 int starty = yi - rad; if (starty < 0) starty = 0; 00668 int stopy = yi + rad; if (stopy >= dimY) stopy = dimY-1; 00669 00670 // 1. Calculate orientation vector 00671 for (int ind_y = starty; ind_y <= stopy; ind_y ++) 00672 { 00673 // given that y, get the corresponding range of x values that 00674 // lie within the disk (and remain within the image): 00675 const int yoff = ind_y - yi; 00676 const int bound = int(sqrtf(float(rad2 - yoff*yoff)) + 0.5F); 00677 int startx = xi - bound; if (startx < 0) startx = 0; 00678 int stopx = xi + bound; if (stopx >= dimX) stopx = dimX-1; 00679 00680 for (int ind_x = startx; ind_x <= stopx; ind_x ++) 00681 { 00682 const float dx = float(ind_x) - loc.i, dy = float(ind_y) - loc.j; 00683 const float distSq = dx * dx + dy * dy; 00684 00685 // get gradient: 00686 const float gradVal = perc.getVal(ind_x, ind_y); 00687 00688 // compute the gaussian weight for this histogram entry: 00689 const float gaussianWeight = expf(distSq * inv2sig2); 00690 00691 // add this orientation to the histogram 00692 // [-pi ; pi] -> [0 ; 2pi] 00693 float angle = ori.getVal(ind_x, ind_y) + M_PI; 00694 00695 // [0 ; 2pi] -> [0 ; 36] 00696 angle = 0.5F * angle * histSize / M_PI; 00697 while (angle < 0.0F) angle += histSize; 00698 while (angle >= histSize) angle -= histSize; 00699 00700 OV.addValueInterp(angle, gaussianWeight * gradVal); 00701 } 00702 } 00703 00704 00705 // smooth the orientation histogram 3 times: 00706 for (int i = 0; i < 3; i++) OV.smooth(); 00707 00708 // find the max in the histogram: 00709 float maxPeakValue = OV.findMax(); 00710 float peakAngle = 0; 00711 int ai =0; 00712 for (int bin = 0; bin < histSize; bin++) 00713 { 00714 // consider the peak centered around 'bin': 00715 const float midval = OV.getValue(bin); 00716 00717 // if current value much smaller than global peak, forget it: 00718 //if (midval != maxPeakValue) continue; 00719 if (midval < 0.8F * maxPeakValue) continue; 00720 00721 // get value to the left of current value 00722 const float leftval = OV.getValue((bin == 0) ? histSize-1 : bin-1); 00723 00724 // get value to the right of current value 00725 const float rightval = OV.getValue((bin == histSize-1) ? 0 : bin+1); 00726 00727 // interpolate the values to get the orientation of the peak: 00728 // with f(x) = ax^2 + bx + c 00729 // f(-1) = x0 = leftval 00730 // f( 0) = x1 = midval 00731 // f(+1) = x2 = rightval 00732 // => a = (x0+x2)/2 - x1 00733 // b = (x2-x0)/2 00734 // c = x1 00735 // f'(x) = 0 => x = -b/2a 00736 const float a = 0.5f * (leftval + rightval) - midval; 00737 const float b = 0.5f * (rightval - leftval); 00738 float realangle = float(bin) - 0.5F * b / a; 00739 00740 realangle *= 2.0F * M_PI / histSize; // [0:36] to [0:2pi] 00741 realangle -= M_PI; // [0:2pi] to [-pi:pi] 00742 peakAngle = realangle; 00743 ai++; 00744 LINFO("Ang %i %f", ai, realangle*180/M_PI + 90); 00745 } 00746 00747 return peakAngle; 00748 00749 } 00750 00751 // ###################################################################### 00752 void V4d::evolve() 00753 { 00754 00755 ///Resample 00756 //for(uint i=0; i<itsFeaturesParticles.size(); i++) 00757 // printf("%i %f %f %f %e %e;\n",i, 00758 // itsFeaturesParticles[i].pos.x, 00759 // itsFeaturesParticles[i].pos.y, 00760 // itsFeaturesParticles[i].rot, 00761 // itsFeaturesParticles[i].weight, itsFeaturesParticles[i].prob); 00762 //getchar(); 00763 00764 //resampleParticles(itsFeaturesParticles); 00765 //proposeParticlesHarris(itsFeaturesParticles, 0.0F); 00766 proposeParticles(itsFeaturesParticles, 0.0F); 00767 00768 //Evaluate the particles; 00769 evaluateParticles(itsFeaturesParticles); 00770 00771 // LINFO("Particle (%fx%fx%f) rot %f Prob %e", 00772 // itsFeaturesParticles[0].pos.x, 00773 // itsFeaturesParticles[0].pos.y, 00774 // itsFeaturesParticles[0].pos.z, 00775 // itsFeaturesParticles[0].rot*180/M_PI, 00776 // itsFeaturesParticles[0].prob); 00777 // LINFO("\n\n"); 00778 00779 } 00780 00781 // ###################################################################### 00782 float V4d::evaluateParticles(std::vector<NAFState>& particles) 00783 { 00784 00785 LINFO("Evaluate Particles"); 00786 CpuTimer timer; 00787 timer.reset(); 00788 00789 std::vector<rutz::shared_ptr<LikelihoodJob> > jobs; 00790 for(uint p=0; p<particles.size(); p++) 00791 { 00792 //jobs.push_back(rutz::make_shared(new LikelihoodJob(this, particles[p]))); 00793 //itsThreadServer->enqueueJob(jobs.back()); 00794 getParticleLikelihood(particles[p]); 00795 } 00796 00797 //wait for jobs to finish 00798 while(itsThreadServer->size() > 0) 00799 usleep(10000); 00800 00801 timer.mark(); 00802 LINFO("Total time %0.2f sec", timer.real_secs()); 00803 00804 //Normalize the particles; 00805 double sum = 0; 00806 double Neff = 0; //Number of efictive particles 00807 for(uint i=0; i<particles.size(); i++) 00808 sum += particles[i].prob; 00809 00810 for(uint i=0; i<particles.size(); i++) 00811 { 00812 particles[i].weight = particles[i].prob/sum; 00813 Neff += squareOf(particles[i].weight); 00814 } 00815 00816 Neff = 1/Neff; 00817 00818 00819 return Neff; 00820 00821 } 00822 00823 void V4d::GHT(std::vector<V4d::GHTAcc>& accRet, const FeatureTemplate& featureTemplate) 00824 { 00825 ImageSet<float> acc(int(360/itsGHTAngStep), Dims(320,240), ZEROS); 00826 00827 00828 //Image<float> tmp2(320,240,ZEROS); 00829 //for(iter = itsHashedEdgesState.begin(); iter != itsHashedEdgesState.end(); iter++) 00830 //{ 00831 // V1::EdgeState edgeState = iter->second; 00832 // tmp2.setVal(edgeState.pos, edgeState.prob); 00833 //} 00834 00835 //IplImage* img2 = img2ipl(tmp2); 00836 //IplImage* hImg = cvCreateImage( cvSize(img2->width, img2->height), IPL_DEPTH_32F, 1 ); 00837 00838 //cvCornerHarris(img2, hImg, 5, 5, 0); 00839 // 00840 00841 //Image<float> harris = ipl2float(hImg); 00842 //inplaceNormalize(harris, 0.0F, 1.0F); 00843 //SHOWIMG(harris); 00844 00845 00846 //float totalSum = 0; 00847 CpuTimer timer; 00848 timer.reset(); 00849 std::vector<V1::EdgeState> rTable = featureTemplate.edges; 00850 00851 //Parallel votes 00852 std::vector<rutz::shared_ptr<GHTJob> > jobs; 00853 00854 for(int angIdx=0; angIdx<int(360/itsGHTAngStep); angIdx++) 00855 { 00856 jobs.push_back(rutz::make_shared(new GHTJob(this, acc[angIdx], angIdx, rTable))); 00857 itsThreadServer->enqueueJob(jobs.back()); 00858 //voteForFeature(acc[angIdx], angIdx, rTable); 00859 } 00860 00861 //wait for jobs to finish 00862 while(itsThreadServer->size() > 0) 00863 usleep(10000); 00864 00865 //for (size_t i = 0; i < jobs.size(); ++i) 00866 // jobs[i]->wait(); 00867 timer.mark(); 00868 LINFO("Total time %0.2f sec", timer.real_secs()); 00869 00870 //Image<float> tmp(320, 240, ZEROS); 00871 //for(int angIdx=0; angIdx<int(360/itsGHTAngStep); angIdx++) 00872 //{ 00873 // for(uint i=0; i<acc[angIdx].size(); i++) 00874 // { 00875 // if (acc[angIdx].getVal(i) > tmp.getVal(i)) 00876 // tmp.setVal(i, acc[angIdx].getVal(i)); 00877 // } 00878 //} 00879 //SHOWIMG(tmp); 00880 00881 00882 for(uint i=0; i<acc.size(); i++) 00883 for(int y=0; y<acc[i].getHeight(); y++) 00884 for(int x=0; x<acc[i].getWidth(); x++) 00885 if (acc[i].getVal(x,y) > 0) 00886 { 00887 GHTAcc ghtAcc; 00888 ghtAcc.pos = Point2D<int>(x,y); 00889 ghtAcc.ang = i*itsGHTAngStep; 00890 if (featureTemplate.featureType == VERTIX) 00891 ghtAcc.ang = i*itsGHTAngStep + 45; 00892 ghtAcc.scale = -1; 00893 ghtAcc.featureType = featureTemplate.featureType; 00894 ghtAcc.sum = acc[i].getVal(x,y); ///totalSum; 00895 accRet.push_back(ghtAcc); 00896 } 00897 } 00898 00899 float V4d::voteForFeature(Image<float>& acc, int angIdx, std::vector<V1::EdgeState>& rTable) 00900 { 00901 float sum = 0; 00902 00903 for(uint ei = 0; ei < itsEdgesState.size(); ei++) 00904 { 00905 V1::EdgeState& edgeState = itsEdgesState[ei]; 00906 00907 if (edgeState.prob > 0) // && harris.getVal(edgeState.pos) > 0.1) 00908 { 00909 for(uint j=0; j<rTable.size(); j++) 00910 { 00911 //Rotate 00912 float ang = (angIdx*itsGHTAngStep)*M_PI/180; 00913 00914 float diffRot = edgeState.ori - (rTable[j].ori - ang); 00915 diffRot = atan(sin(diffRot)/cos(diffRot)); //wrap to 180 deg to 0 00916 00917 float stddevRot = 1; 00918 int sizeRot = int(ceil(stddevRot * sqrt(-2.0F * log(exp(-5.0F))))); 00919 00920 if (fabs(diffRot) < sizeRot*M_PI/180) //TODO change to a for loop with hash 00921 { 00922 float rRot = exp(-((diffRot*diffRot)/(stddevRot*stddevRot))); 00923 00924 // drawLine(acc[0], edgeState.pos, Point2D<int>(a0, b0), 1.0F); 00925 //acc[0].setVal(a0, b0, 0.5); 00926 00927 float stddevX = 0.1; 00928 float stddevY = 0.1; 00929 int sizeX = int(ceil(stddevX * sqrt(-2.0F * log(exp(-5.0F))))); 00930 int sizeY = int(ceil(stddevY * sqrt(-2.0F * log(exp(-5.0F))))); 00931 00932 //Apply a variance over position 00933 for(int y=edgeState.pos.j-sizeY; y<edgeState.pos.j+sizeY; y++) 00934 { 00935 float diffY = y-edgeState.pos.j; 00936 float ry = exp(-((diffY*diffY)/(stddevY*stddevY))); 00937 for(int x=edgeState.pos.i-sizeX; x<edgeState.pos.i+sizeX; x++) 00938 { 00939 float diffX = x-edgeState.pos.i; 00940 float rx = exp(-((diffX*diffX)/(stddevX*stddevX))); 00941 float weight = rRot*rx*ry; 00942 00943 int a0 = x - int((float)rTable[j].pos.i*cos(ang) - (float)rTable[j].pos.j*sin(ang)); 00944 int b0 = y - int((float)rTable[j].pos.i*sin(ang) + (float)rTable[j].pos.j*cos(ang)); 00945 00946 if (acc.coordsOk(a0, b0)) 00947 { 00948 sum += edgeState.prob + weight; 00949 float val = acc.getVal(a0, b0); 00950 val += weight*edgeState.prob; //Add the strength of the feature 00951 acc.setVal(a0, b0, val); 00952 } 00953 } 00954 } 00955 } 00956 } 00957 } 00958 } 00959 00960 return sum; 00961 } 00962 00963 Image<PixRGB<byte> > V4d::showParticles(const std::vector<NAFState>& particles) 00964 { 00965 //LINFO("Show part %lu %lu", itsBias.size(), particles.size()); 00966 Image<float> probImg(320,240, ZEROS); 00967 Image<PixRGB<byte> > particlesImg(probImg.getDims(),ZEROS); 00968 for(uint i=0; i<particles.size(); i++) 00969 { 00970 Point2D<int> loc = (Point2D<int>)itsCamera.project(particles[i].pos); 00971 if (particlesImg.coordsOk(loc) && 00972 particles[i].weight > probImg.getVal(loc) ) 00973 { 00974 PixRGB<byte> col; 00975 if (particles[i].featureType == RIGHT_VERTIX) 00976 col = PixRGB<byte>(0, 255, 0); 00977 else if (particles[i].featureType == VERTIX) 00978 col = PixRGB<byte>(255, 0, 0); 00979 else 00980 col = PixRGB<byte>(0, 0, 255); 00981 00982 probImg.setVal(loc, particles[i].weight); 00983 00984 particlesImg.setVal(loc, col); 00985 } 00986 } 00987 inplaceNormalize(probImg, 0.0F, 255.0F); 00988 00989 //particlesImg *= probImg; 00990 //for(uint i=0; i<probImg.size(); i++) 00991 //{ 00992 // int pColor = (int)probImg.getVal(i); 00993 // particlesImg.setVal(i, PixRGB<byte>(0,pColor,0)); 00994 //} 00995 00996 //Image<float> biasProbImg(320,240, ZEROS); 00997 //float h = 2; //smoothing paramter 00998 //for(int y=0; y<240; y++) 00999 // for(int x=0; x<320; x++) 01000 // { 01001 // Point2D<int> sampleLoc(x,y); 01002 01003 // //Particles 01004 // float sum = 0; 01005 // for(uint i=0; i<particles.size(); i++) 01006 // { 01007 // Point2D<int> loc = (Point2D<int>)itsCamera.project(particles[i].pos); 01008 // sum += (1.0F/sqrt(2*M_PI)*exp(-0.5*squareOf(sampleLoc.distance(loc)/h)))*particles[i].weight; 01009 // } 01010 // float val = 1.0/(float(particles.size())*h) * sum; 01011 01012 // //Bias 01013 // float biasSum = 0; 01014 // for(uint i=0; i<itsBias.size(); i++) 01015 // { 01016 // if (itsBias[i].weight > 0) 01017 // { 01018 // Point2D<int> loc = (Point2D<int>)itsCamera.project(itsBias[i].pos); 01019 // biasSum += (1.0F/sqrt(2*M_PI)*exp(-0.5*squareOf(sampleLoc.distance(loc)/h))); //*itsBias[i].weight; 01020 // } 01021 // } 01022 // float biasVal = 1.0/(float(itsBias.size())*h) * biasSum; 01023 01024 // probImg.setVal(sampleLoc, biasVal+val); 01025 // } 01026 01027 inplaceNormalize(probImg, 0.0F, 255.0F); 01028 particlesImg = toRGB(probImg); 01029 01030 //LINFO("Done part"); 01031 01032 return particlesImg; 01033 01034 } 01035 01036 void V4d::proposeParticles(std::vector<NAFState>& particles, const double Neff) 01037 { 01038 01039 LINFO("Propose Particles"); 01040 //SEt the veriance to the number of effective particles 01041 //Basicly we always want all the particles to cover the space with 01042 //some probability 01043 //double posVar = 10*Neff/geonParticles.size(); 01044 // LINFO("NEff %0.2f %lu", 01045 // Neff, geonParticles.size()); 01046 // 01047 float probThresh = 0.5; //1.0e-10; 01048 01049 //If we have good hypothisis then just adjest them by a small amount 01050 uint particlesAboveProb = 0; 01051 for(uint i=0; i<particles.size(); i++) 01052 { 01053 if (particles[i].prob > probThresh) 01054 { 01055 particles[i].pos.x += randomDoubleFromNormal(1.0); 01056 particles[i].pos.y += randomDoubleFromNormal(1.0); 01057 particles[i].pos.z = itsObjectsDist + randomDoubleFromNormal(0.05); 01058 particles[i].rot += randomDoubleFromNormal(1)*M_PI/180; 01059 particles[i].weight = 1.0/(float)particles.size(); 01060 particlesAboveProb++; 01061 } 01062 } 01063 01064 01065 //LINFO("Particles Above prob %i/%lu", 01066 // particlesAboveProb, particles.size()); 01067 01068 01069 if (particlesAboveProb < particles.size()) 01070 { 01071 LINFO("GHT "); 01072 std::vector<GHTAcc> acc; 01073 //GHT(acc, itsNAFeatures[RIGHT_VERTIX]); 01074 //GHT(acc, itsNAFeatures[VERTIX]); 01075 //GHT(acc, itsNAFeatures[ARC]); 01076 01077 01078 Image<float> tmp(320,240,ZEROS); 01079 for(uint i=0; i<itsEdgesState.size(); i++) 01080 tmp.setVal(itsEdgesState[i].pos, itsEdgesState[i].prob); 01081 inplaceNormalize(tmp, 0.0F, 255.0F); 01082 01083 01084 Dims win(15,15); 01085 float hist[360]; 01086 for(int i=0; i<360; i++) 01087 hist[i] = 0; 01088 while(!itsCornersState.empty()) 01089 { 01090 V2::CornerState cornerState = itsCornersState.top(); itsCornersState.pop(); 01091 tmp.setVal((Point2D<int>)cornerState.pos, cornerState.prob); 01092 drawCircle(tmp, (Point2D<int>)cornerState.pos, 6, (float)255.0); 01093 SHOWIMG(tmp); 01094 01095 Image<float> edges(win,ZEROS); 01096 for(int wy=0; wy<win.h(); wy++) 01097 for(int wx=0; wx<win.w(); wx++) 01098 { 01099 int x = (int)cornerState.pos.i + wx - (win.w()/2); 01100 int y = (int)cornerState.pos.j + wy - (win.h()/2); 01101 01102 int key = x + 320 * y; 01103 if (key > 0) 01104 { 01105 dense_hash_map<int, V1::EdgeState>::const_iterator iter = itsHashedEdgesState.find(key); 01106 if (iter != itsHashedEdgesState.end()) 01107 { 01108 edges.setVal(wx,wy, iter->second.prob); 01109 int ang = (int)(iter->second.ori*180.0/M_PI); 01110 if (ang < 0) ang += 360; 01111 if (ang > 360) ang -= 360; 01112 hist[ang] += iter->second.prob; 01113 //drawLine(edges, Point2D<int>(wx,wy), (float)iter->second.ori, (float)5, (float)255.0); 01114 } 01115 } 01116 } 01117 for(int i=1; i<359; i++) 01118 if (hist[i] > 1) 01119 if (hist[i] > hist[i-1] && hist[i] > hist[i+1]) 01120 printf("%i %0.1f\n",i, hist[i]); 01121 printf("\n"); 01122 01123 SHOWIMG(edges); 01124 01125 } 01126 01127 01128 01129 LINFO("GHT Done "); 01130 //if (acc.size() == 0) 01131 // return; 01132 01133 CpuTimer timer; 01134 timer.reset(); 01135 ////Normalize to values from 0 to 1 01136 normalizeAcc(acc); 01137 01138 //Combine the bias with the proposal 01139 //if (itsBias.size() > 0) 01140 // mergeBias(acc); 01141 01142 01143 01144 // //Sample from the accumilator 01145 // Image<float> tmp(320,240,ZEROS); 01146 // for(uint i=0; i<acc.size(); i++) 01147 // tmp.setVal(acc[i].pos, tmp.getVal(acc[i].pos) + acc[i].sum); 01148 // SHOWIMG(tmp); 01149 01150 ////Sample from acc 01151 01152 LINFO("Build priority queue"); 01153 std::priority_queue <GHTAcc> pAcc; 01154 for(uint i=0; i<acc.size(); i++) 01155 pAcc.push(acc[i]); 01156 01157 LINFO("Get particules"); 01158 //tmp.clear(); 01159 for(uint i=0; i<particles.size(); i++) 01160 { 01161 if (particles[i].prob <= probThresh) 01162 { 01163 //add this point to the list 01164 if (pAcc.empty()) 01165 break; 01166 GHTAcc p = pAcc.top(); pAcc.pop(); 01167 01168 NAFState nafState; 01169 Point3D<float> iPoint = itsCamera.inverseProjection(Point2D<float>(p.pos), itsObjectsDist); 01170 nafState.pos.x = iPoint.x; // + randomDoubleFromNormal(1); 01171 nafState.pos.y = iPoint.y; // + randomDoubleFromNormal(1); 01172 nafState.pos.z = itsObjectsDist; // + randomDoubleFromNormal(0.05); 01173 nafState.rot = p.ang*M_PI/180; // ((p.ang + 180) + randomDoubleFromNormal(5))*M_PI/180; 01174 nafState.featureType = p.featureType; 01175 nafState.weight = 1.0/(float)particles.size(); 01176 nafState.prob = 1.0e-50; 01177 01178 //check to see how lcose this particle is to the reset of the group 01179 01180 //int nearPart = 0; 01181 //float partDist = particles[nearPart].distance(nafState); 01182 //for(uint p=1; p<particles.size(); p++) 01183 //{ 01184 // float distance = particles[p].distance(nafState); 01185 // if (distance < partDist) 01186 // { 01187 // partDist = distance; 01188 // nearPart = p; 01189 // } 01190 //} 01191 01192 //if (partDist > 3) //we dont have this particle in our list, addit 01193 { 01194 particles[i].pos = nafState.pos; 01195 particles[i].rot = nafState.rot; 01196 particles[i].featureType = nafState.featureType; 01197 particles[i].weight = nafState.weight; 01198 particles[i].prob = nafState.prob; 01199 } 01200 01201 //std::vector<Point2D<int> > outline = getImageOutline(particles[i]); 01202 //for(uint i=0; i<outline.size()-1; i++) 01203 // drawLine(tmp, outline[i], outline[i+1], 1.0F, 1); 01204 } 01205 } 01206 timer.mark(); 01207 LINFO("Get particles: Total time %0.2f sec", timer.real_secs()); 01208 //SHOWIMG(tmp); 01209 } 01210 LINFO("Done proposeing"); 01211 } 01212 01213 void V4d::mergeBias(std::vector<GHTAcc>& acc) 01214 { 01215 LINFO("Merge bias"); 01216 CpuTimer timer; 01217 timer.reset(); 01218 //find the nearset bias, if it close then increase the probability of that location 01219 //if not, then add this bias particle to the list to be concidered for sampleing 01220 01221 01222 ImageSet<float> tmpAcc(360*2, Dims(320,240), ZEROS); 01223 01224 for(uint p=0; p<itsBias.size(); p++) 01225 { 01226 if (itsBias[p].prob > 0) //only look at worty particles 01227 { 01228 GHTAcc ghtAcc; 01229 Point2D<int> pos = (Point2D<int>)itsCamera.project(itsBias[p].pos); 01230 int ang = int(itsBias[p].rot*180/M_PI); 01231 01232 int fType = 0; 01233 switch(itsBias[p].featureType) 01234 { 01235 case RIGHT_VERTIX: fType = 0; break; 01236 case VERTIX: fType = 1; break; 01237 case ARC: fType = 1; break; 01238 } 01239 if (tmpAcc[fType*360 + ang].coordsOk(pos)) 01240 tmpAcc[fType*360 + ang].setVal(pos,itsBias[p].prob); 01241 } 01242 } 01243 01244 //Image<float> tmp(320, 240, ZEROS); 01245 //for(uint j=0; j<tmpAcc.size(); j++) 01246 //{ 01247 // for(uint i=0; i<tmpAcc[j].size(); i++) 01248 // { 01249 // if (tmpAcc[j].getVal(i) > tmp.getVal(i)) 01250 // tmp.setVal(i, tmpAcc[j].getVal(i)); 01251 // } 01252 //} 01253 //SHOWIMG(tmp); 01254 01255 01256 for(uint i=0; i<acc.size(); i++) 01257 { 01258 Point2D<int> pos = acc[i].pos; 01259 int rot = acc[i].ang; 01260 float sum = acc[i].sum; 01261 01262 int fType = 0; 01263 switch(acc[i].featureType) 01264 { 01265 case RIGHT_VERTIX: fType = 0; break; 01266 case VERTIX: fType = 1; break; 01267 case ARC: fType = 1; break; 01268 } 01269 01270 if (rot > 360) rot -= 360; 01271 if (rot == 360) rot = 0; 01272 01273 if (tmpAcc[fType*360 + rot].coordsOk(pos)) 01274 { 01275 float prior = tmpAcc[fType*360 + rot].getVal(pos); 01276 01277 float post = sum+prior; 01278 01279 tmpAcc[fType*360 + rot].setVal(pos, post); 01280 } 01281 } 01282 01283 //tmp.clear(); 01284 //for(uint j=0; j<tmpAcc.size(); j++) 01285 //{ 01286 // for(uint i=0; i<tmpAcc[j].size(); i++) 01287 // { 01288 // if (tmpAcc[j].getVal(i) > tmp.getVal(i)) 01289 // tmp.setVal(i, tmpAcc[j].getVal(i)); 01290 // } 01291 //} 01292 //SHOWIMG(tmp); 01293 01294 01295 01296 acc.clear(); 01297 for(uint i=0; i<tmpAcc.size(); i++) 01298 for(int y=0; y<tmpAcc[i].getHeight(); y++) 01299 for(int x=0; x<tmpAcc[i].getWidth(); x++) 01300 if (tmpAcc[i].getVal(x,y) > 0) 01301 { 01302 GHTAcc ghtAcc; 01303 ghtAcc.pos = Point2D<int>(x,y); 01304 01305 if (i > 360) 01306 { 01307 ghtAcc.featureType = VERTIX; 01308 ghtAcc.ang =(i - 360); 01309 } 01310 else 01311 { 01312 ghtAcc.featureType = RIGHT_VERTIX; 01313 ghtAcc.ang = i; 01314 } 01315 ghtAcc.scale = -1; 01316 ghtAcc.sum = tmpAcc[i].getVal(x,y); ///totalSum; 01317 acc.push_back(ghtAcc); 01318 } 01319 01320 normalizeAcc(acc); 01321 01322 //std::vector<GHTAcc> tmpAcc; 01323 01324 //for(uint p=0; p<itsBias.size(); p++) 01325 //{ 01326 // if (itsBias[p].prob > 0) //only look at worty particles 01327 // { 01328 // findAngMerge(acc, itsBias[p], tmpAcc); 01329 // } 01330 //} 01331 ////merge the temp acc and the acc 01332 //for(uint i=0; i<tmpAcc.size(); i++) 01333 // acc.push_back(tmpAcc[i]); 01334 timer.mark(); 01335 LINFO("Merge bias: Total time %0.2f sec", timer.real_secs()); 01336 01337 } 01338 01339 void V4d::findAngMerge(std::vector<GHTAcc>& acc, const NAFState& biasNafState, std::vector<GHTAcc> tmpAcc) 01340 { 01341 //find for the closest value in the acc 01342 int nearPart = 0; 01343 float partDist = 1.0e100; 01344 for(uint i=0; i<acc.size(); i++) 01345 { 01346 NAFState nafState; 01347 nafState.pos = itsCamera.inverseProjection(Point2D<float>(acc[i].pos), itsObjectsDist); 01348 nafState.rot = acc[i].ang*M_PI/180; 01349 nafState.featureType = acc[i].featureType; 01350 01351 float distance = nafState.distance(biasNafState); 01352 if (distance < partDist) 01353 { 01354 partDist = distance; 01355 nearPart = i; 01356 } 01357 } 01358 01359 //If we are close, then increase this acc probability, we we will sample it more 01360 if (partDist < 10) 01361 acc[nearPart].sum += (0.1 + biasNafState.prob); 01362 else 01363 { 01364 GHTAcc ghtAcc; 01365 ghtAcc.pos = (Point2D<int>)itsCamera.project(biasNafState.pos); 01366 ghtAcc.ang = int(biasNafState.rot*180/M_PI); 01367 ghtAcc.featureType = biasNafState.featureType; 01368 ghtAcc.scale = -1; 01369 ghtAcc.sum = 0.1 + biasNafState.prob; 01370 //LINFO("Add to acc with sum %f (prob %f)", ghtAcc.sum, itsBias[p].prob); 01371 tmpAcc.push_back(ghtAcc); //Add to temp, so that we dont search for it int the next iteration 01372 } 01373 01374 } 01375 01376 void V4d::harrisDetector(std::vector<V4d::GHTAcc>& accRet, const FeatureTemplate& featureTemplate) 01377 { 01378 Image<float> tmp(320,240,ZEROS); 01379 dense_hash_map<int, V1::EdgeState>::const_iterator iter; 01380 for(iter = itsHashedEdgesState.begin(); iter != itsHashedEdgesState.end(); iter++) 01381 { 01382 V1::EdgeState edgeState = iter->second; 01383 tmp.setVal(edgeState.pos, edgeState.prob); 01384 } 01385 01386 IplImage* img = img2ipl(tmp); 01387 IplImage* hImg = cvCreateImage( cvSize(img->width, img->height), IPL_DEPTH_32F, 1 ); 01388 01389 cvCornerHarris(img, hImg, 5, 5, 0); 01390 SHOWIMG(ipl2float(hImg)); 01391 01392 Image<float> acc = ipl2float(hImg); 01393 01394 inplaceNormalize(acc, 0.0F, 1.0F); 01395 for(int y=0; y<acc.getHeight(); y++) 01396 for(int x=0; x<acc.getWidth(); x++) 01397 if (acc.getVal(x,y) > 0) 01398 { 01399 GHTAcc ghtAcc; 01400 ghtAcc.pos = Point2D<int>(x,y); 01401 ghtAcc.ang = 0; //i*itsGHTAngStep; 01402 //ghtAcc.ang = i*itsGHTAngStep; 01403 //if (featureTemplate.featureType == VERTIX) 01404 // ghtAcc.ang = i*itsGHTAngStep + 45; 01405 ghtAcc.scale = -1; 01406 ghtAcc.featureType = featureTemplate.featureType; 01407 ghtAcc.sum = acc.getVal(x,y); 01408 accRet.push_back(ghtAcc); 01409 } 01410 01411 } 01412 void V4d::proposeParticlesHarris(std::vector<NAFState>& particles, const double Neff) 01413 { 01414 01415 LINFO("Propose Particles"); 01416 float probThresh = 0.5; //1.0e-10; 01417 01418 //If we have good hypothisis then just adjest them 01419 uint particlesAboveProb = 0; 01420 for(uint i=0; i<particles.size(); i++) 01421 { 01422 if (particles[i].prob > probThresh) 01423 { 01424 particles[i].pos.x += randomDoubleFromNormal(1.0); 01425 particles[i].pos.y += randomDoubleFromNormal(1.0); 01426 particles[i].pos.z = itsObjectsDist + randomDoubleFromNormal(0.05); 01427 particles[i].rot += randomDoubleFromNormal(1)*M_PI/180; 01428 particles[i].weight = 1.0/(float)particles.size(); 01429 particlesAboveProb++; 01430 } 01431 } 01432 01433 //LINFO("Particles Above prob %i/%lu", 01434 // particlesAboveProb, particles.size()); 01435 01436 if (particlesAboveProb < particles.size()) 01437 { 01438 std::vector<GHTAcc> acc; 01439 harrisDetector(acc, itsNAFeatures[RIGHT_VERTIX]); 01440 01441 for(uint i=0; i<particles.size(); i++) 01442 { 01443 if (particles[i].prob <= probThresh) 01444 { 01445 //find max; 01446 float maxVal = acc[0].sum; int maxIdx = 0; 01447 for(uint j=0; j<acc.size(); j++) 01448 { 01449 if (acc[j].sum > maxVal) 01450 { 01451 maxVal = acc[j].sum; 01452 maxIdx = j; 01453 } 01454 } 01455 01456 //add this point to the list 01457 GHTAcc p = acc.at(maxIdx); 01458 // LINFO("Max at %i,%i %i %i", p.pos.i, p.pos.j, p.ang, p.featureType); 01459 Point3D<float> iPoint = itsCamera.inverseProjection(Point2D<float>(p.pos), itsObjectsDist); 01460 particles[i].pos.x = iPoint.x; // + randomDoubleFromNormal(1); 01461 particles[i].pos.y = iPoint.y; // + randomDoubleFromNormal(1); 01462 particles[i].pos.z = itsObjectsDist; // + randomDoubleFromNormal(0.05); 01463 particles[i].rot = ((p.ang + 180) + randomDoubleFromNormal(5))*M_PI/180; 01464 particles[i].featureType = p.featureType; 01465 particles[i].weight = 1.0/(float)particles.size(); 01466 particles[i].prob = 1.0e-50; 01467 acc[maxIdx].sum = 0; 01468 } 01469 } 01470 } 01471 } 01472 01473 void V4d::normalizeAcc(std::vector<GHTAcc>& acc) 01474 { 01475 01476 double sum = 0; 01477 for(uint i=0; i<acc.size(); i++) 01478 sum += acc[i].sum; 01479 01480 for(uint i=0; i<acc.size(); i++) 01481 acc[i].sum /= sum; 01482 } 01483 01484 void V4d::resampleParticles2(std::vector<NAFState>& particles) 01485 { 01486 std::vector<NAFState> newParticles; 01487 01488 while(newParticles.size() < particles.size()) 01489 { 01490 //Find max 01491 int maxP = 0; double maxVal = particles[maxP].weight; 01492 for(uint j=1; j<particles.size(); j++) 01493 { 01494 if (particles[j].weight > maxVal) 01495 { 01496 maxP = j; 01497 maxVal = particles[j].weight; 01498 } 01499 } 01500 01501 if (maxVal > 0) 01502 { 01503 for(int np=0; np<10; np++) 01504 { 01505 //Add the particle to the list 01506 NAFState p = particles[maxP]; 01507 p.weight = 1.0/double(particles.size()); 01508 newParticles.push_back(p); 01509 } 01510 01511 //IOR 01512 float sigmaX = 0.1, sigmaY = 0.1; 01513 float fac = 0.5f / (M_PI * sigmaX * sigmaY); 01514 float vx = -0.5f / (sigmaX * sigmaX); 01515 float vy = -0.5f / (sigmaY * sigmaY); 01516 01517 for(uint j=0; j<particles.size(); j++) 01518 { 01519 float x = particles[j].pos.x; 01520 float y = particles[j].pos.y; 01521 01522 float vydy2 = y - particles[maxP].pos.y; vydy2 *= vydy2 * vy; 01523 float dx2 = x - particles[maxP].pos.x; dx2 *= dx2; 01524 particles[j].weight -= particles[j].weight * fac*expf(vx * dx2 + vydy2); 01525 if (particles[j].weight < 0) 01526 particles[j].weight = 0; 01527 01528 } 01529 particles[maxP].weight = 0; 01530 } else { 01531 NAFState p = particles[0]; 01532 p.weight = 1.0/double(particles.size()); 01533 newParticles.push_back(p); 01534 } 01535 01536 } 01537 01538 particles = newParticles; 01539 01540 } 01541 01542 01543 void V4d::resampleParticles(std::vector<NAFState>& particles) 01544 { 01545 01546 LINFO("Resample particles"); 01547 std::vector<NAFState> newParticles; 01548 01549 if(particles.size() == 0) 01550 return; 01551 01552 //Calculate a Cumulative Distribution Function for our particle weights 01553 uint i = 0; 01554 double c = particles.at(0).weight; 01555 double U = randomDouble()* 1.0/double(particles.size()); 01556 01557 for(uint j=0; j < particles.size(); j++) 01558 { 01559 01560 while(U > c) 01561 { 01562 i++; 01563 c += particles.at(i).weight; 01564 } 01565 01566 NAFState p = particles.at(i); 01567 p.weight = 1.0/double(particles.size()); 01568 newParticles.push_back(p); 01569 01570 U += 1.0/double(particles.size()); 01571 } 01572 01573 particles = newParticles; 01574 01575 } 01576 01577 std::vector<Point2D<int> > V4d::getImageOutline(NAFState& nafState) 01578 { 01579 01580 FeatureTemplate featureCameraOutline = itsNAFeatures[nafState.featureType]; 01581 01582 //Transofrm the object relative to the camera 01583 for(uint i=0; i<featureCameraOutline.outline.size(); i++) 01584 { 01585 float x = featureCameraOutline.outline[i].x; 01586 float y = featureCameraOutline.outline[i].y; 01587 float z = featureCameraOutline.outline[i].z; 01588 featureCameraOutline.outline[i].x = (cos(nafState.rot)*x - sin(nafState.rot)*y) + nafState.pos.x; 01589 featureCameraOutline.outline[i].y = (sin(nafState.rot)*x + cos(nafState.rot)*y) + nafState.pos.y; 01590 featureCameraOutline.outline[i].z = z + nafState.pos.z; 01591 } 01592 01593 //Project the object to camera cordinats 01594 std::vector<Point2D<int> > outline; 01595 for(uint i=0; i<featureCameraOutline.outline.size(); i++) 01596 { 01597 Point2D<float> loc = itsCamera.project(featureCameraOutline.outline[i]); 01598 outline.push_back(Point2D<int>(loc)); 01599 } 01600 01601 return outline; 01602 01603 } 01604 /* 01605 void V4d::getParticleLikelihood2(NAFState& particle) 01606 { 01607 01608 while(particle.rot > M_PI*2) 01609 particle.rot =- M_PI*2; 01610 01611 while(particle.rot < 0) 01612 particle.rot =+ M_PI*2; 01613 01614 //Transofrm the object position relative to the camera 01615 std::vector<Point2D<int> > outline = getImageOutline(particle); 01616 01617 double totalProb = 1; //.0e-5; 01618 for(uint i=0; i<outline.size()-1; i++) 01619 { 01620 Point2D<int> pLoc1 = outline[i]; 01621 Point2D<int> pLoc2 = outline[i+1]; 01622 double prob = getLineProbability(pLoc1, pLoc2); 01623 totalProb *= prob; 01624 } 01625 particle.prob = totalProb; 01626 01627 //Apply bias by finding the closest particle, and if it is within some threahold, increase 01628 //the probability by a factor of this amount. 01629 01630 if (itsBias.size() > 0) 01631 { 01632 int nearPart = 0; 01633 float partDist = itsBias[nearPart].distance(particle); 01634 01635 for(uint p=1; p<itsBias.size(); p++) 01636 { 01637 float distance = itsBias[p].distance(particle); 01638 if (distance < partDist) 01639 { 01640 partDist = distance; 01641 nearPart = p; 01642 } 01643 } 01644 01645 //If we are close, then increase this particle probability 01646 if (partDist < 10) 01647 particle.prob += (0.1 + itsBias[nearPart].prob); 01648 if (particle.prob > 1) 01649 particle.prob = 1; 01650 } 01651 } 01652 */ 01653 01654 void V4d::getParticleLikelihood(NAFState& particle) 01655 { 01656 while(particle.rot > M_PI*2) 01657 particle.rot =- M_PI*2; 01658 01659 while(particle.rot < 0) 01660 particle.rot =+ M_PI*2; 01661 01662 FeatureTemplate featureTemplate = itsNAFeatures[particle.featureType]; 01663 01664 01665 Image<float> tmp(320,240,ZEROS); 01666 double totalProb = 1; 01667 //Get the position of the feature in the image 01668 Point2D<float> featureLoc = itsCamera.project(particle.pos); 01669 float featureRot = particle.rot; 01670 01671 //LINFO("Feature rot %f", featureRot*180/M_PI); 01672 if (particle.featureType == VERTIX) 01673 featureRot -= M_PI/4; 01674 int badValues = 0; 01675 for(uint i=0; i<featureTemplate.edges.size(); i++) 01676 { 01677 //Map the feature to position in the image 01678 V1::EdgeState featureEdgeState = featureTemplate.edges[i]; 01679 01680 int x = featureEdgeState.pos.i; 01681 int y = featureEdgeState.pos.j; 01682 01683 01684 featureEdgeState.pos.i = (int)(featureLoc.i + (float)x*cos(featureRot) - (float)y*sin(featureRot)); 01685 featureEdgeState.pos.j = (int)(featureLoc.j + (float)x*sin(featureRot) + (float)y*cos(featureRot)); 01686 01687 featureEdgeState.ori = featureEdgeState.ori - featureRot + M_PI/2; 01688 01689 int nearEdge = 0; 01690 //float edgeDist = itsEdgesState[nearEdge].distance(featureEdgeState); 01691 01692 double edgeDist = 1.0e100; 01693 for(uint i = 0; i < itsEdgesState.size(); i++) 01694 { 01695 if (itsEdgesState[i].prob > 0) 01696 { 01697 //double dPoint = itsEdgesState[i].pos.squdist(featureEdgeState.pos); 01698 float distance = 1.0e100; 01699 if (itsEdgesState[i].pos == featureEdgeState.pos) 01700 //if (itsEdgesState[i].distance(featureEdgeState) < 2) 01701 { 01702 double dRot = itsEdgesState[i].ori + M_PI/2 - featureEdgeState.ori; 01703 dRot = atan(sin(dRot)/cos(dRot))*180/M_PI; //wrap to 180 deg to 0 01704 distance = dRot; 01705 } 01706 01707 //float distance = sqrt(dRot*dRot); 01708 //if (dPoint > 0) 01709 // distance = 0; 01710 01711 //float distance = sqrt(dPoint + (dRot*dRot)); 01712 01713 if (distance < edgeDist) 01714 { 01715 nearEdge = i; 01716 edgeDist = distance; 01717 } 01718 } 01719 } 01720 01721 if (edgeDist == 1.0e100) 01722 badValues++; 01723 else 01724 if (badValues < 3) 01725 { 01726 01727 float sig = 10.75F; 01728 float prob = (1.0F/(sig*sqrt(2*M_PI))*exp(-0.5*squareOf(edgeDist)/squareOf(sig))); 01729 totalProb *= prob; 01730 } else { 01731 totalProb = 0; 01732 } 01733 01734 //LINFO("dist %f prob %e", edgeDist, prob); 01735 //LINFO("Edges %ix%i %f", 01736 // featureEdgeState.pos.i, featureEdgeState.pos.j, featureEdgeState.ori*180/M_PI + 360); 01737 //LINFO("Neare %ix%i %f", 01738 // itsEdgesState[nearEdge].pos.i - (int)featureLoc.i, 01739 // itsEdgesState[nearEdge].pos.j - (int)featureLoc.j, 01740 // itsEdgesState[nearEdge].ori); 01741 //// edgeDist); 01742 ////drawLine(tmp, itsEdgesState[nearEdge].pos, itsEdgesState[nearEdge].ori + M_PI/2, 5.0F, itsEdgesState[nearEdge].prob); 01743 //drawLine(tmp, featureEdgeState.pos, featureEdgeState.ori, 5.0F, 1.0F); 01744 //tmp.setVal(featureEdgeState.pos, 1.0F); 01745 } 01746 01747 //totalProb = 1; 01748 particle.prob = totalProb; 01749 //LINFO("Total prob %e", totalProb); 01750 01751 //inplaceNormalize(tmp, 0.0F, 255.0F); 01752 //itsDebugImg = toRGB(tmp); 01753 01754 //Apply bias by finding the closest particle, and if it is within some threahold, increase 01755 //the probability by a factor of this amount. 01756 01757 if (itsBias.size() > 0) 01758 { 01759 int nearPart = 0; 01760 float partDist = itsBias[nearPart].distance(particle); 01761 01762 for(uint p=1; p<itsBias.size(); p++) 01763 { 01764 float distance = itsBias[p].distance(particle); 01765 if (distance < partDist) 01766 { 01767 partDist = distance; 01768 nearPart = p; 01769 } 01770 } 01771 01772 //If we are close, then increase this particle probability 01773 if (partDist < 10) 01774 particle.prob += (0.1 + itsBias[nearPart].prob); 01775 if (particle.prob > 1) 01776 particle.prob = 1; 01777 } 01778 } 01779 01780 01781 double V4d::getLineProbability(const Point2D<int>& p1, const Point2D<int>& p2) 01782 { 01783 01784 int dx = p2.i - p1.i, ax = abs(dx) << 1, sx = signOf(dx); 01785 int dy = p2.j - p1.j, ay = abs(dy) << 1, sy = signOf(dy); 01786 int x = p1.i, y = p1.j; 01787 01788 const int w = 320; 01789 01790 double prob = 1; //1.0e-5; 01791 01792 int wSize = 1; 01793 if (ax > ay) 01794 { 01795 int d = ay - (ax >> 1); 01796 for (;;) 01797 { 01798 //search for a max edge prob in a window 01799 float maxProb = 0; //1.0e-20; 01800 for(int yy = y-wSize; yy < y+wSize; yy++) 01801 for(int xx = x-wSize; xx < x+wSize; xx++) 01802 { 01803 int key = xx + w * yy; 01804 if (key > 0) 01805 { 01806 dense_hash_map<int, V1::EdgeState>::const_iterator iter = itsHashedEdgesState.find(key); 01807 if (iter != itsHashedEdgesState.end()) 01808 { 01809 if (iter->second.prob > maxProb) 01810 maxProb = iter->second.prob; 01811 } 01812 } 01813 } 01814 prob *= maxProb; 01815 01816 if (x == p2.i) return prob; 01817 if (d >= 0) { y += sy; d -= ax; } 01818 x += sx; d += ay; 01819 } 01820 } else { 01821 int d = ax - (ay >> 1); 01822 for (;;) 01823 { 01824 float maxProb = 0; //1.0e-20; 01825 for(int yy = y-wSize; yy < y+wSize; yy++) 01826 for(int xx = x-wSize; xx < x+wSize; xx++) 01827 { 01828 int key = xx + w * yy; 01829 if (key > 0) 01830 { 01831 dense_hash_map<int, V1::EdgeState>::const_iterator iter = itsHashedEdgesState.find(key); 01832 if (iter != itsHashedEdgesState.end()) 01833 { 01834 if (iter->second.prob > maxProb) 01835 maxProb = iter->second.prob; 01836 } 01837 } 01838 } 01839 prob *= maxProb; 01840 if (y == p2.j) return prob; 01841 01842 if (d >= 0) { x += sx; d -= ay; } 01843 y += sy; d += ax; 01844 } 01845 } 01846 01847 return prob; 01848 01849 01850 } 01851 01852 Layout<PixRGB<byte> > V4d::getDebugImage() 01853 { 01854 Layout<PixRGB<byte> > outDisp; 01855 01856 //Show the gabor states 01857 Image<float> perc(320,240, ZEROS); 01858 01859 //Draw the edges 01860 for(uint i=0; i<itsEdgesState.size(); i++) 01861 perc.setVal(itsEdgesState[i].pos, itsEdgesState[i].prob); 01862 01863 inplaceNormalize(perc, 0.0F, 255.0F); 01864 01865 Image<PixRGB<byte> > NAFDisp = toRGB(Image<byte>(perc)); 01866 01867 //Get min max 01868 float minVal = itsFeaturesParticles[0].prob; 01869 float maxVal = itsFeaturesParticles[0].prob; 01870 for(uint p=0; p<itsFeaturesParticles.size(); p++) 01871 { 01872 if (itsFeaturesParticles[p].prob < minVal) 01873 minVal = itsFeaturesParticles[p].prob; 01874 if (itsFeaturesParticles[p].prob > maxVal) 01875 maxVal = itsFeaturesParticles[p].prob; 01876 } 01877 01878 float scale = maxVal - minVal; 01879 float nScale = (255.0F - 0.0F)/scale; 01880 for(uint p=0; p<itsFeaturesParticles.size(); p++) 01881 { 01882 //set the color to the probability 01883 float normProb = 0.0F + ((itsFeaturesParticles[p].prob - minVal) * nScale); 01884 //if (normProb > 0) //itsFeaturesParticles[p].prob > 0) 01885 if (itsFeaturesParticles[p].prob > 0) 01886 { 01887 normProb = 255.0; 01888 PixRGB<byte> col; 01889 if (itsFeaturesParticles[p].featureType == RIGHT_VERTIX) 01890 col = PixRGB<byte>(0,int(normProb),0); 01891 else if (itsFeaturesParticles[p].featureType == VERTIX) 01892 col = PixRGB<byte>(int(normProb),0, 0); 01893 else 01894 col = PixRGB<byte>(0,0,int(normProb)); 01895 01896 std::vector<Point2D<int> > outline = getImageOutline(itsFeaturesParticles[p]); 01897 for(uint i=0; i<outline.size()-1; i++) 01898 drawLine(NAFDisp, outline[i], outline[i+1], col, 1); 01899 } 01900 } 01901 01902 //draw bias 01903 01904 // for(uint p=0; p<itsBias.size(); p++) 01905 // { 01906 // PixRGB<byte> col; 01907 // if (itsFeaturesParticles[p].featureType == RIGHT_VERTIX) 01908 // col = PixRGB<byte>(0,255,255); 01909 // else 01910 // col = PixRGB<byte>(255,0, 255); 01911 // 01912 // std::vector<Point2D<int> > outline = getImageOutline(itsBias[p]); 01913 // for(uint i=0; i<outline.size()-1; i++) 01914 // drawLine(NAFDisp, outline[i], outline[i+1], col, 1); 01915 // } 01916 //Show the normalized particles 01917 Image<PixRGB<byte> > particlesImg = showParticles(itsFeaturesParticles); 01918 01919 outDisp = hcat(NAFDisp, particlesImg); 01920 01921 return outDisp; 01922 01923 } 01924 01925 // ###################################################################### 01926 /* So things look consistent in everyone's emacs... */ 01927 /* Local Variables: */ 01928 /* indent-tabs-mode: nil */ 01929 /* End: */ 01930 01931 #endif 01932