V4d.C

Go to the documentation of this file.
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 
Generated on Sun May 8 08:05:32 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3