ObjRec.C

Go to the documentation of this file.
00001 /*!@file ObjRec/ObjRec.C Obj Reconition class */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the //
00005 // University of Southern California (USC) and the iLab at USC.         //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Lior Elazary <elazary@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/ObjRec/ObjRec.C $
00035 // $Id: ObjRec.C 10794 2009-02-08 06:21:09Z itti $
00036 //
00037 
00038 #include "ObjRec/ObjRec.H"
00039 #include "Component/OptionManager.H"
00040 #include "Image/DrawOps.H"
00041 #include "Image/ColorOps.H"
00042 #include "Image/Kernels.H"   // for dogFilter()
00043 #include "Image/Convolutions.H"
00044 #include "Image/MathOps.H"
00045 #include "Image/CutPaste.H"
00046 #include "Image/FilterOps.H"
00047 #include "GUI/DebugWin.H"
00048 #include "Util/MathFunctions.H"
00049 #include "SIFT/Histogram.H"
00050 #include "SIFT/FeatureVector.H"
00051 
00052 
00053 void findMinMax(const std::vector<double> &vec, double &min, double &max)
00054 {
00055   max = vec[0];
00056   min = max;
00057   for (uint n = 1 ; n < vec.size() ; n++)
00058   {
00059     if (vec[n] > max) max = vec[n];
00060     if (vec[n] < min) min = vec[n];
00061   }
00062 }
00063 
00064 double normalizeHist(std::vector<double> &hist)
00065 {
00066 
00067   double sum = 0;
00068   for(uint i=0; i<hist.size(); i++)
00069     sum += hist[i];
00070 
00071   for(uint i=0; i<hist.size(); i++)
00072     hist[i] /= sum;
00073 
00074   return sum;
00075 
00076 }
00077 
00078 // ######################################################################
00079 ObjRec::ObjRec(OptionManager& mgr, const std::string& descrName,
00080     const std::string& tagName) :
00081   ModelComponent(mgr, descrName, tagName),
00082   itsImageDims(256, 256),
00083   itsInitProposal(true)
00084 {
00085 
00086 }
00087 
00088 
00089 ObjRec::~ObjRec()
00090 {
00091 }
00092 
00093 void ObjRec::setImageDims(const Dims &dims)
00094 {
00095   itsImageDims = dims;
00096 }
00097 
00098 void ObjRec::start2()
00099 {
00100   initRandomNumbers();
00101 
00102   //Generate gabor patches for speed up
00103   itsGabors.resize(180);
00104   for (uint i=0; i<itsGabors.size(); i++)
00105   {
00106     //float filter_period = 5;
00107     //float elongation = 1.0;
00108     //float angle = i;
00109     //int size = -1;
00110     //const double major_stddev = filter_period / 3.0;
00111     //const double minor_stddev = major_stddev * elongation;
00112 
00113     //Image<float> gabor = gaborFilter3(major_stddev, minor_stddev,
00114     //    filter_period, 0.0f, 180 - angle + 90.0 , size);
00115 
00116     float ori = i;
00117     int scale = 1;
00118     Image<float> dog = dogFilter<float>(1.75F + 0.5F*scale, ori, 3 + 1*scale);
00119 
00120     // normalize to zero mean:
00121     dog -= mean(dog);
00122 
00123     // normalize to unit sum-of-squares:
00124     dog /= sum(squared(dog));
00125 
00126     itsGabors[i] = dog;
00127 
00128   }
00129 
00130   //initial proposal
00131   initialProposal();
00132 }
00133 
00134 void ObjRec::initialProposal()
00135 {
00136 
00137   int size = 20;
00138   itsWorldState.edges.resize(size*size);
00139   for(uint i=0; i<itsWorldState.edges.size(); i++)
00140   {
00141     int y = i/size;
00142     int x = i%size;
00143     itsWorldState.edges[i].pos = Point2D<int>(x*itsImageDims.w()/size,y*itsImageDims.h()/size);
00144     itsWorldState.edges[i].ori = 0.0;
00145     itsWorldState.edges[i].color = PixRGB<byte>(0,255,0);
00146     itsWorldState.edges[i].prob = 0.1;
00147   }
00148 
00149   itsWorldState.lines.resize(10);
00150 
00151   for(uint i=0; i<itsWorldState.lines.size(); i++)
00152   {
00153     int y = i;
00154     int x = itsImageDims.w()/2;
00155     itsWorldState.lines[i].pos = Point2D<int>(x,y*itsImageDims.h()/10);
00156     itsWorldState.lines[i].ori = 90.0;
00157     itsWorldState.lines[i].length = 30.0;
00158     itsWorldState.lines[i].color = PixRGB<byte>(255,0,255);
00159     itsWorldState.lines[i].prob = 0.1;
00160 
00161   }
00162 
00163 }
00164 
00165 void ObjRec::initialProposal(const Image<PixRGB<byte> > &worldImg)
00166 {
00167 
00168   itsWorldState.edges.clear();
00169   Image<float> mag, ori;
00170   Image<float> worldLum = luminance(worldImg);
00171   gradientSobel(worldLum, mag, ori, 3);
00172 
00173   itsWorldState.edges.clear();
00174   Image<float> edgeProb = mag / sum(mag); //normalized edge probability
00175   itsWorldState.edgeProb = edgeProb;
00176 
00177   float maxVal, minVal;
00178   getMinMax(mag, minVal, maxVal);
00179 
00180   for(int y=0; y<mag.getHeight(); y++)
00181     for(int x=0; x<mag.getWidth(); x++)
00182     {
00183       float angle = ori.getVal(x,y) + M_PI/2;
00184       while(angle > M_PI) angle-=M_PI;
00185       while (angle < 0) angle+=M_PI;
00186       float p = mag.getVal(x,y);
00187 
00188       if (p > maxVal*0.10)
00189       {
00190         EdgeState es;
00191         es.pos = Point2D<int>(x,y);
00192         es.ori = angle*180/M_PI;
00193         es.color = PixRGB<byte>(0,255,0);
00194         es.prob = p;
00195         itsWorldState.edges.push_back(es);
00196       }
00197     }
00198 
00199   itsWorldState.lines.resize(10);
00200 
00201   for(uint i=0; i<itsWorldState.lines.size(); i++)
00202   {
00203     itsWorldState.lines[i].pos = samplePosFromEdgeSpace(itsWorldState);
00204     itsWorldState.lines[i].ori =  sampleOriFromEdgeSpace(itsWorldState);
00205     itsWorldState.lines[i].length = 30.0;
00206     itsWorldState.lines[i].color = PixRGB<byte>(255,0,255);
00207     itsWorldState.lines[i].prob = 0;
00208   }
00209 
00210   itsWorldState.squares.resize(1);
00211   for(uint i=0; i<itsWorldState.squares.size(); i++)
00212   {
00213     itsWorldState.squares[i].pos = samplePosFromLineSpace(itsWorldState);
00214     itsWorldState.squares[i].ori =  sampleOriFromLineSpace(itsWorldState);
00215     itsWorldState.squares[i].size = sampleSizeFromLineSpace(itsWorldState);
00216     itsWorldState.squares[i].color = PixRGB<byte>(0,255,0);
00217     itsWorldState.squares[i].prob = 0;
00218   }
00219 
00220 }
00221 
00222 void ObjRec::generateNewState(WorldState &worldState)
00223 {
00224   generateNewEdgeState(worldState);
00225   generateNewLineState(worldState);
00226 }
00227 
00228 void ObjRec::generateNewEdgeState(WorldState &worldState)
00229 {
00230   int idum = getIdum();
00231 
00232   static int modParam = 1;
00233 
00234   for(uint i=0; i<worldState.edges.size(); i++)
00235   {
00236     if (modParam == 0)
00237     {
00238       worldState.edges[i].pos = Point2D<int>(
00239           int(itsWorldState.edges[i].pos.i + 1*gasdev(idum)),
00240           int(itsWorldState.edges[i].pos.j + 1*gasdev(idum)));
00241 
00242       if (worldState.edges[i].pos.i > itsImageDims.w())
00243         worldState.edges[i].pos.i = itsImageDims.w();
00244       if (worldState.edges[i].pos.j > itsImageDims.h())
00245         worldState.edges[i].pos.j = itsImageDims.h();
00246       if (worldState.edges[i].pos.i < 0)
00247         worldState.edges[i].pos.i = 0;
00248       if (worldState.edges[i].pos.j < 0)
00249         worldState.edges[i].pos.j = 0;
00250     }
00251 
00252     if (modParam == 1)
00253     {
00254       //Standard search
00255      worldState.edges[i].ori = itsWorldState.edges[i].ori + 5*gasdev(idum);
00256 
00257       //perceptual grouping search
00258       // Look at the neighbors and try the same position and orientation
00259 
00260       if (worldState.edges[i].prob != 0)
00261       {
00262         float avgOri = 0;
00263         int oriTotal = 0;
00264         for(uint j=0; j<worldState.edges.size(); j++)
00265         {
00266           if (j == i) continue;
00267 
00268           //Look at near neighbors
00269           float dist = worldState.edges[i].pos.distance(worldState.edges[j].pos);
00270           if (dist < 50)
00271           {
00272             avgOri += worldState.edges[j].ori;
00273             oriTotal++;
00274           }
00275         }
00276         avgOri /= oriTotal;
00277         worldState.edges[i].ori = avgOri;
00278       } else {
00279         worldState.edges[i].ori = itsWorldState.edges[i].ori + 5*gasdev(idum);
00280       }
00281 
00282 
00283       if (worldState.edges[i].ori >= 180)
00284         worldState.edges[i].ori -= 180;
00285       if (worldState.edges[i].ori < 0)
00286         worldState.edges[i].ori += 180;
00287     }
00288 
00289   }
00290 
00291   if (modParam++ > 1)
00292     modParam = 0;
00293 
00294 }
00295 
00296 void ObjRec::generateNewLineState(WorldState &worldState)
00297 {
00298   int idum = getIdum();
00299 
00300   static int modParam = 0;
00301 
00302   for(uint i=0; i<worldState.lines.size(); i++)
00303   {
00304     if (modParam == 0)
00305     {
00306       Point2D<int> probablePos = samplePosFromEdgeSpace(itsWorldState);
00307       worldState.lines[i].pos = Point2D<int>(
00308           int(probablePos.i + 1*gasdev(idum)),
00309           int(probablePos.j + 1*gasdev(idum)));
00310 
00311       if (worldState.lines[i].pos.i > itsImageDims.w())
00312         worldState.lines[i].pos.i = itsImageDims.w();
00313       if (worldState.lines[i].pos.j > itsImageDims.h())
00314         worldState.lines[i].pos.j = itsImageDims.h();
00315       if (worldState.lines[i].pos.i < 0)
00316         worldState.lines[i].pos.i = 0;
00317       if (worldState.lines[i].pos.j < 0)
00318         worldState.lines[i].pos.j = 0;
00319     }
00320 
00321 
00322     if (modParam == 1)
00323     {
00324       //use the edges as prior
00325       worldState.lines[i].ori = sampleOriFromEdgeSpace(itsWorldState) + 1*gasdev(idum);
00326 
00327       if (worldState.lines[i].ori >= 180)
00328         worldState.lines[i].ori -= 180;
00329       if (worldState.lines[i].ori < 0)
00330         worldState.lines[i].ori += 180;
00331     }
00332 
00333     if (modParam == 2)
00334     {
00335       //Standard search
00336       worldState.lines[i].length = sampleLengthFromSquareSpace(itsWorldState) + 1*gasdev(idum);
00337       //itsWorldState.lines[i].length + 3*gasdev(idum);
00338 
00339       //if (worldState.lines[i].length >= itsImageDims.w())
00340       //  worldState.lines[i].length = itsImageDims.w();
00341       if (worldState.lines[i].length < 5)
00342         worldState.lines[i].length = 5;
00343     }
00344 
00345     worldState.lines[i].color = PixRGB<byte>(0,0,255);
00346     worldState.lines[i].prob = 0.1;
00347 
00348   }
00349 
00350 
00351   if (modParam++ > 2)
00352     modParam = 0;
00353 
00354 }
00355 
00356 /*void ObjRec::generateNewSquareState(WorldState &worldState)
00357 {
00358   int idum = getIdum();
00359 
00360   static int modParam = 0;
00361 
00362   for(uint i=0; i<worldState.squares.size(); i++)
00363   {
00364     if (modParam == 0)
00365     {
00366       Point2D<int> probablePos = samplePosFromLineSpace(itsWorldState);
00367       worldState.squares[i].pos = Point2D<int>(
00368           int(probablePos.i + 1*gasdev(idum)),
00369           int(probablePos.j + 1*gasdev(idum)));
00370 
00371       if (worldState.squares[i].pos.i > itsImageDims.w())
00372         worldState.squares[i].pos.i = itsImageDims.w();
00373       if (worldState.squares[i].pos.j > itsImageDims.h())
00374         worldState.squares[i].pos.j = itsImageDims.h();
00375       if (worldState.squares[i].pos.i < 0)
00376         worldState.squares[i].pos.i = 0;
00377       if (worldState.squares[i].pos.j < 0)
00378         worldState.squares[i].pos.j = 0;
00379     }
00380 
00381     if (modParam == 1)
00382     {
00383       //use the edges as prior
00384       worldState.squares[i].ori = sampleOriFromLineSpace(itsWorldState) + 1*gasdev(idum);
00385 
00386       if (worldState.squares[i].ori >= 180)
00387         worldState.squares[i].ori -= 180;
00388       if (worldState.squares[i].ori < 0)
00389         worldState.squares[i].ori += 180;
00390     }
00391 
00392     if (modParam == 2)
00393     {
00394       //Standard search
00395       worldState.squares[i].size = sampleSizeFromLineSpace(itsWorldState) + 1*gasdev(idum);
00396 
00397       //if (worldState.squares[i].length >= itsImageDims.w())
00398       //  worldState.squares[i].length = itsImageDims.w();
00399       if (worldState.squares[i].size < 5)
00400         worldState.squares[i].size = 5;
00401     }
00402 
00403     worldState.squares[i].color = PixRGB<byte>(255,0,255);
00404     worldState.squares[i].prob = 0.1;
00405 
00406   }
00407 
00408 
00409   if (modParam++ > 2)
00410     modParam = 0;
00411 
00412 }*/
00413 
00414 void ObjRec::generateNewSquareState(WorldState &worldState)
00415 {
00416 
00417   //TODO need improtance sampling
00418   Image<float> posVotes(itsImageDims, ZEROS);
00419   Image<float> oriSizeVotes(181, itsImageDims.h(), ZEROS);
00420 
00421   for(uint i=0; i<worldState.lines.size(); i++)
00422   {
00423       float ori = worldState.lines[i].ori;
00424       float size = worldState.lines[i].length;
00425       Point2D<int> pos = worldState.lines[i].pos;
00426 
00427 
00428       int x =  int(cos((ori+90)*M_PI/180)*size/2);
00429       int y =  int(sin((ori+90)*M_PI/180)*size/2);
00430 
00431       for(int j=y-5; j<y+5; j++)
00432         for(int i=x-5; i<x+5; i++)
00433         {
00434           if (posVotes.coordsOk(pos.i+i,pos.j-j))
00435           {
00436             float val = posVotes.getVal(pos.i+i, pos.j-j);
00437             posVotes.setVal(pos.i+i, pos.j-j, val+1);
00438           }
00439 
00440           if (posVotes.coordsOk(pos.i-i,pos.j+j))
00441           {
00442             float val = posVotes.getVal(pos.i-i, pos.j+j);
00443             posVotes.setVal(pos.i-i, pos.j+j, val+1);
00444           }
00445         }
00446 
00447 
00448       for(int j=(int)size-5; j<(int)size+5; j++)
00449         for(int i=(int)ori-5; i<(int)ori+5; i++)
00450         {
00451           if (oriSizeVotes.coordsOk(i,j))
00452           {
00453             float val = oriSizeVotes.getVal(i,j);
00454             oriSizeVotes.setVal(i,j, val+1);
00455           }
00456 
00457           if (oriSizeVotes.coordsOk(i,j))
00458           {
00459             ori += 90;
00460             if (ori > 180) ori -= 180;
00461             float val = oriSizeVotes.getVal(i,j);
00462             oriSizeVotes.setVal(i,j, val+1);
00463           }
00464         }
00465 
00466   }
00467   //SHOWIMG(posVotes);
00468   //SHOWIMG(oriSizeVotes);
00469 
00470 
00471   Point2D<int> maxPos; float maxVal;
00472   findMax(oriSizeVotes, maxPos, maxVal);
00473   LINFO("Max at %ix%i %f", maxPos.i, maxPos.j, maxVal);
00474 
00475   Point2D<int> maxPos1; float maxVal1;
00476   findMax(posVotes, maxPos1, maxVal1);
00477 
00478   worldState.squares[0].pos = maxPos1;
00479   worldState.squares[0].ori = maxPos.i;
00480   worldState.squares[0].size = maxPos.j;
00481   worldState.squares[0].color = PixRGB<byte>(255,0,255);
00482   worldState.squares[0].prob = 0.1;
00483 
00484 
00485 
00486 }
00487 
00488 double ObjRec::sampleOriFromEdgeSpace(WorldState &worldState)
00489 {
00490   //Pick an edge at random and use that for orientation
00491   //Rejection sampleing
00492   for(int i=0; i<100; i++)
00493   {
00494     int j = randomUpToNotIncluding(worldState.edges.size());
00495     if (worldState.edges[j].prob != 0)
00496       return worldState.edges[j].ori;
00497   }
00498 
00499   return 0;
00500 }
00501 
00502 Point2D<int> ObjRec::samplePosFromEdgeSpace(WorldState &worldState)
00503 {
00504   //Pick an edge at random and use that for orientation
00505   //Rejection sampleing
00506   for(int i=0; i<100; i++)
00507   {
00508     int j = randomUpToNotIncluding(worldState.edges.size());
00509     if (worldState.edges[j].prob > 0)
00510       return worldState.edges[j].pos;
00511   }
00512   return Point2D<int>(100,100);
00513 }
00514 
00515 double ObjRec::sampleLengthFromSquareSpace(WorldState &worldState)
00516 {
00517 
00518   return worldState.squares[0].size;
00519 
00520 }
00521 
00522 double ObjRec::sampleOriFromLineSpace(WorldState &worldState)
00523 {
00524   //Pick an edge at random and use that for orientation
00525   //Rejection sampleing
00526   for(int i=0; i<100; i++)
00527   {
00528     int j = randomUpToNotIncluding(worldState.lines.size());
00529     if (worldState.lines[j].prob != 0)
00530       return worldState.lines[j].ori;
00531   }
00532 
00533   return 0;
00534 }
00535 
00536 Point2D<int> ObjRec::samplePosFromLineSpace(WorldState &worldState)
00537 {
00538   //Pick an edge at random and use that for orientation
00539   //Rejection sampleing
00540   for(int i=0; i<100; i++)
00541   {
00542     int j = randomUpToNotIncluding(worldState.lines.size());
00543     if (worldState.lines[j].prob > 0)
00544       return worldState.lines[j].pos;
00545   }
00546   return Point2D<int>(100,100);
00547 }
00548 
00549 double ObjRec::sampleSizeFromLineSpace(WorldState &worldState)
00550 {
00551   //Pick an edge at random and use that for orientation
00552   //Rejection sampleing
00553   for(int i=0; i<100; i++)
00554   {
00555     int j = randomUpToNotIncluding(worldState.lines.size());
00556     if (worldState.lines[j].prob > 0)
00557       return worldState.lines[j].length;
00558   }
00559   return 10;
00560 }
00561 
00562 
00563 Image<PixRGB<byte> > ObjRec::showWorld(WorldState &worldState)
00564 {
00565   Image<PixRGB<byte> > edgesWorld = showEdgesWorld(worldState);
00566   Image<PixRGB<byte> > linesWorld = showLinesWorld(worldState);
00567 
00568   Image<PixRGB<byte> > worldImg = edgesWorld + linesWorld;
00569  // Image<PixRGB<byte> > worldImg = linesWorld;
00570   return worldImg;
00571 }
00572 
00573 Image<PixRGB<byte> > ObjRec::showEdgesWorld(WorldState &worldState)
00574 {
00575 
00576   Image<PixRGB<byte> > worldImg(itsImageDims, ZEROS);
00577   Image<float> worldProbImg(itsImageDims, ZEROS);
00578 
00579   //SHOW Edges
00580   for(uint i=0; i<worldState.edges.size(); i++)
00581   {
00582     if (worldState.edges[i].prob != 0)
00583     {
00584 
00585       //PixRGB<byte> color(0, int(1/worldState.edges[i].prob*255), 0);
00586       PixRGB<byte> color = worldState.edges[i].color;
00587       drawLine(worldImg,
00588           worldState.edges[i].pos,
00589           worldState.edges[i].ori*M_PI/180,
00590           10,
00591           color);
00592       worldProbImg.setVal(worldState.edges[i].pos, worldState.edges[i].prob);
00593     }
00594   }
00595 
00596   return worldImg;
00597 
00598 }
00599 
00600 Image<PixRGB<byte> > ObjRec::showLinesWorld(WorldState &worldState)
00601 {
00602 
00603   Image<PixRGB<byte> > worldImg(itsImageDims, ZEROS);
00604   Image<float> worldProbImg(itsImageDims, ZEROS);
00605 
00606   for(uint i=0; i<worldState.lines.size(); i++)
00607   {
00608     if (worldState.lines[i].prob != 0)
00609     {
00610 
00611       //PixRGB<byte> color(0, int(worldState.lines[i].prob*255), 0);
00612       PixRGB<byte> color = worldState.lines[i].color;
00613       //color[0] = (int) ((float)color[0] * worldState.lines[i].prob);
00614       //color[1] = (int) ((float)color[1] * worldState.lines[i].prob);
00615       //color[2] = (int) ((float)color[2] * worldState.lines[i].prob);
00616 
00617       drawLine(worldImg,
00618           worldState.lines[i].pos,
00619           worldState.lines[i].ori*M_PI/180,
00620           worldState.lines[i].length,
00621           color);
00622       //worldProbImg.setVal(worldState.lines[i].pos, worldState.lines[i].prob);
00623     }
00624   }
00625 
00626   return worldImg;
00627 
00628 }
00629 
00630 Image<PixRGB<byte> > ObjRec::showSquaresWorld(WorldState &worldState)
00631 {
00632 
00633   Image<PixRGB<byte> > worldImg(itsImageDims, ZEROS);
00634   Image<float> worldProbImg(itsImageDims, ZEROS);
00635 
00636   for(uint i=0; i<worldState.squares.size(); i++)
00637   {
00638     if (worldState.squares[i].prob > 0)
00639     {
00640 
00641       //PixRGB<byte> color(0, int(worldState.lines[i].prob*255), 0);
00642       //color[0] = (int) ((float)color[0] * worldState.lines[i].prob);
00643       //color[1] = (int) ((float)color[1] * worldState.lines[i].prob);
00644       //color[2] = (int) ((float)color[2] * worldState.lines[i].prob);
00645 
00646 
00647       PixRGB<byte> color = worldState.squares[i].color;
00648       Point2D<int> pos = worldState.squares[i].pos;
00649       float size = worldState.squares[i].size;
00650       float ori = worldState.squares[i].ori*M_PI/180;
00651 
00652       drawRectOR(worldImg,
00653           Rectangle(Point2D<int>(pos.i-(int)(size/2),pos.j-(int)(size/2)), Dims((int)size, (int)size)),
00654           color,
00655           2,
00656           ori);
00657       //worldProbImg.setVal(worldState.lines[i].pos, worldState.lines[i].prob);
00658     }
00659   }
00660 
00661   return worldImg;
00662 
00663 }
00664 
00665 
00666 
00667 double ObjRec::predictWorld(const Image<PixRGB<byte> > &worldImg)
00668 {
00669   itsCurrentWorldImg = worldImg;
00670 
00671   //The Metoplis-Hastings algorithem
00672 
00673   //TODO: store and use value from storage as opposed to calculating
00674   // a new posterior each time
00675   double p_of_xi = getPosterior(itsWorldState);
00676 
00677   LINFO("Old Posterior %f", p_of_xi);
00678 
00679   //generate new proposal sample
00680   WorldState worldState = itsWorldState;
00681   generateNewState(worldState);
00682   LINFO("New world state");
00683   showWorld(worldState);
00684 
00685   double p_of_xnew = getPosterior(worldState);
00686   LINFO("New Posterior %f", p_of_xnew);
00687 
00688   //evaluate the new world
00689 
00690   double edgesWorldProb = evalNewEdgesWorld(itsWorldState, worldState);
00691   double linesWorldProb = evalNewLinesWorld(itsWorldState, worldState);
00692   LINFO("EdgesProb: %f, linesProb: %f", edgesWorldProb, linesWorldProb);
00693 
00694 
00695   //show the current world state
00696   itsPredictWorldImg = showWorld(itsWorldState);
00697 
00698   return edgesWorldProb + linesWorldProb;
00699   //return linesWorldProb;
00700 }
00701 
00702 double ObjRec::evalNewEdgesWorld(WorldState &oldWorldState, WorldState &newWorldState)
00703 {
00704   double p_of_world = 0;
00705   for(uint i=0; i<oldWorldState.edges.size(); i++)
00706   {
00707     double p_of_xnew = newWorldState.edges[i].prob;
00708     double p_of_xi = oldWorldState.edges[i].prob;
00709 
00710     float A = std::min(double(1), p_of_xnew/p_of_xi);
00711     //if (randomDouble() < A) //accept the new proposal with some probability
00712     if (A == 1.0) //always accept the new proposal if its better
00713     {
00714       oldWorldState.edges[i].pos =    newWorldState.edges[i].pos;
00715       oldWorldState.edges[i].ori =    newWorldState.edges[i].ori;
00716       oldWorldState.edges[i].color =  newWorldState.edges[i].color;
00717       oldWorldState.edges[i].prob =   newWorldState.edges[i].prob;
00718     }
00719     p_of_world += oldWorldState.edges[i].prob;
00720   }
00721 
00722   return p_of_world;
00723 }
00724 
00725 double ObjRec::evalNewLinesWorld(WorldState &oldWorldState, WorldState &newWorldState)
00726 {
00727   double p_of_world = 0;
00728   for(uint i=0; i<oldWorldState.lines.size(); i++)
00729   {
00730     double p_of_xnew = newWorldState.lines[i].prob;
00731     double p_of_xi = oldWorldState.lines[i].prob;
00732 
00733     float A = std::min(double(1), p_of_xnew/p_of_xi);
00734     //if (randomDouble() < A) //accept the new proposal with some probability
00735     if (A == 1.0) //always accept the new proposal if its better
00736     {
00737       oldWorldState.lines[i].pos =    newWorldState.lines[i].pos;
00738       oldWorldState.lines[i].ori =    newWorldState.lines[i].ori;
00739       oldWorldState.lines[i].length = newWorldState.lines[i].length;
00740       //oldWorldState.lines[i].color =  newWorldState.lines[i].color;
00741       oldWorldState.lines[i].prob =   newWorldState.lines[i].prob;
00742     }
00743     p_of_world += oldWorldState.lines[i].prob;
00744   }
00745 
00746   return p_of_world;
00747 }
00748 
00749 double ObjRec::evalNewSquaresWorld(WorldState &oldWorldState, WorldState &newWorldState)
00750 {
00751   double p_of_world = 0;
00752   for(uint i=0; i<oldWorldState.squares.size(); i++)
00753   {
00754     double p_of_xnew = newWorldState.squares[i].prob;
00755     double p_of_xi = oldWorldState.squares[i].prob;
00756 
00757     float A = std::min(double(1), p_of_xnew/p_of_xi);
00758     //if (randomDouble() < A) //accept the new proposal with some probability
00759     if (A == 1.0) //always accept the new proposal if its better
00760     {
00761       oldWorldState.squares[i].pos =    newWorldState.squares[i].pos;
00762       oldWorldState.squares[i].ori =    newWorldState.squares[i].ori;
00763       oldWorldState.squares[i].size = newWorldState.squares[i].size;
00764       //oldWorldState.squares[i].color =  newWorldState.squares[i].color;
00765       oldWorldState.squares[i].prob =   newWorldState.squares[i].prob;
00766     }
00767     p_of_world += oldWorldState.squares[i].prob;
00768   }
00769 
00770   return p_of_world;
00771 }
00772 
00773 double ObjRec::getPosterior(WorldState &worldState)
00774 {
00775   //For now just the likelihood
00776 
00777   return getLikelihood(worldState);
00778 }
00779 
00780 double ObjRec::getLikelihood(WorldState &worldState)
00781 {
00782 
00783   return getEdgeLikelihood(worldState) + getLineLikelihood(worldState);
00784 }
00785 
00786 
00787 double ObjRec::getEdgeLikelihood(WorldState &worldState)
00788 {
00789 
00790   Image<float> worldLum = luminance(itsCurrentWorldImg);
00791 
00792   //evaluate the likelihood of all the edges
00793   double totalProb = 0;
00794   for(uint i=0; i<worldState.edges.size(); i++)
00795   {
00796     int edgeOri = (int)worldState.edges[i].ori;
00797     if (edgeOri < 0) edgeOri += 180;
00798     ASSERT(edgeOri >= 0 && edgeOri < 180);
00799 
00800     Point2D<int> edgePos = worldState.edges[i].pos;
00801 
00802 
00803     Image<float> gabor = itsGabors[edgeOri];
00804     Point2D<int> gaborPos(edgePos.i - (gabor.getWidth()/2),
00805         edgePos.j - (gabor.getHeight()/2));
00806 
00807     double prob = 0;
00808     if (worldLum.coordsOk(
00809           gaborPos.i + gabor.getWidth() - 1,
00810           gaborPos.j + gabor.getHeight() -1 ) &&
00811         worldLum.coordsOk(gaborPos))
00812     {
00813       Image<float> worldPart = crop(worldLum,
00814           gaborPos,
00815           gabor.getDims());
00816 
00817       prob = sum(worldPart*gabor); //normalize to 1
00818       if (prob < 0) prob = 0.0;
00819 
00820 
00821       //Look at how many edges around this one have the same orientation
00822       //If so, the update the probability proprotianl to the number of edges
00823       //with the same orientation
00824       //Perceptual grouping
00825       if (prob != 0)
00826       {
00827         float oriTotal = 0;
00828         for(uint j=0; j<worldState.edges.size(); j++)
00829         {
00830           if (j == i) continue;
00831 
00832           //Look at near neighbors
00833           float dist = worldState.edges[i].pos.distance(worldState.edges[j].pos);
00834           if (dist < 50) //look at close neighbors
00835           {
00836             oriTotal += fabs(worldState.edges[j].ori-worldState.edges[i].ori);
00837           }
00838         }
00839         prob += 1/oriTotal;
00840       }
00841 
00842       //if (prob != 0)
00843       //{
00844       //  SHOWIMG(gabor);
00845       //  SHOWIMG(worldPart);
00846       //  LINFO("Prob %f", prob);
00847       //}
00848     }
00849     worldState.edges[i].prob = prob;
00850     totalProb += prob;
00851   }
00852 
00853   return totalProb;
00854 }
00855 
00856 
00857 /*double ObjRec::getLineLikelihood(WorldState &worldState)
00858 {
00859 
00860   double totalProb = 0;
00861   for(uint line=0; line<worldState.lines.size(); line++)
00862   {
00863 
00864     float lineOri = (int)worldState.lines[line].ori;
00865     Point2D<int> linePos = worldState.lines[line].pos;
00866     double lineLen = worldState.lines[line].length;
00867 
00868     if (lineLen < 1)
00869     {
00870       worldState.lines[line].prob = 0;
00871       continue;
00872     }
00873 
00874     float period = 15;
00875     float elongation = lineLen/(2*period);
00876     float theta = 180 - lineOri + 90.0;
00877     const double major_stddev = period / 3.0;
00878     const double minor_stddev = major_stddev * elongation;
00879 
00880     // change the angles in degree to the those in radians:
00881     const float rtDeg = M_PI / 180.0F * theta;
00882 
00883     // calculate constants:
00884     //const float omega = (2.0F * M_PI) / period;
00885     const float co = cos(rtDeg), si = sin(rtDeg);
00886     const float major_sigq = 2.0F * major_stddev * major_stddev;
00887     const float minor_sigq = 2.0F * minor_stddev * minor_stddev;
00888 
00889     float muX = linePos.i, muY = linePos.j;
00890 
00891     double probLineOri = 0;
00892     double probNotLineOri1 = 0;
00893     double probNotLineOri2 = 0;
00894 
00895  //   Image<float> probImg(worldLum.getDims(), ZEROS);
00896     for(uint i=0; i<worldState.edges.size(); i++)
00897     {
00898       Point2D<int> edgePos = worldState.edges[i].pos;
00899       int x = edgePos.i;
00900       int y = edgePos.j;
00901 
00902       float edgeProb = worldState.edges[i].prob;
00903       float edgeOri =  worldState.edges[i].ori;
00904 
00905       float lkly = edgeProb*gauss(edgeOri, lineOri, 2.0F)/50;
00906 
00907       //p(lineOri)
00908       const float major = (x-muX)*co + (y-muY)*si;
00909       const float minor = (x-muX)*si - (y-muY)*co;
00910       float prior1 = (1.0F
00911           * exp(-(major*major) / major_sigq)
00912           * exp(-(minor*minor) / minor_sigq));
00913       probLineOri += prior1*lkly;
00914 
00915      // p(edge!=lineOri)
00916       float x1 = cos(lineOri*M_PI/180)*lineLen/2;
00917       float y1 = sin(lineOri*M_PI/180)*lineLen/2;
00918 
00919       float stddev = major_stddev;
00920       float prior2 = (1.0F
00921          * exp(-( (x-muX-x1)*(x-muX-x1) )/ major_sigq)
00922          * exp(-( (y-muY+y1)*(y-muY+y1) )/ major_sigq) );
00923       probNotLineOri1 += prior2*(1-lkly);
00924 
00925       float prior3 = (1.0F
00926          * exp(-( (x-muX+x1)*(x-muX+x1) )/ (stddev*stddev))
00927          * exp(-( (y-muY-y1)*(y-muY-y1) )/ (stddev*stddev)) );
00928       probNotLineOri2 += prior3*(1-lkly);
00929 
00930     }
00931 
00932     double sum =  probLineOri + probNotLineOri1 + probNotLineOri2;
00933     double prob = probLineOri/sum *
00934       probNotLineOri1/sum *
00935       probNotLineOri2/sum;
00936 
00937     if (prob < 0) prob = 0.0;
00938 
00939     worldState.lines[line].prob = prob;
00940     LINFO("Line %i prob %f", line, prob);
00941     totalProb += prob;
00942   }
00943 
00944   return totalProb;
00945 }
00946 */
00947 
00948 double ObjRec::getLineLikelihood(WorldState &worldState)
00949 {
00950 
00951   double totalProb = 0;
00952   for(uint line=0; line<worldState.lines.size(); line++)
00953   {
00954 
00955     float lineOri = worldState.lines[line].ori;
00956     Point2D<int> linePos = worldState.lines[line].pos;
00957     double lineLen = worldState.lines[line].length*0.75; //only evaluate 75% of the length
00958 
00959     if (lineLen < 1)
00960     {
00961       worldState.lines[line].prob = 0;
00962       continue;
00963     }
00964 
00965     Image<float> lineModel(worldState.edgeProb.getDims(), ZEROS);
00966 
00967     drawLine(lineModel, linePos, lineOri*M_PI/180, lineLen, 1.0F, 1);
00968 
00969 
00970     Image<float> lineProb = lineModel*worldState.edgeProb;
00971 
00972     double sum = 0;
00973     double prob = 0;
00974     for(int i=0; i<lineModel.getSize(); i++)
00975     {
00976       if (lineModel[i] > 0)
00977       {
00978         sum++;
00979         prob += lineProb[i];
00980       }
00981     }
00982 
00983     worldState.lines[line].prob = prob;
00984     totalProb += prob;
00985   }
00986 
00987   return totalProb;
00988 }
00989 
00990 double ObjRec::getSquareLikelihood(WorldState &worldState)
00991 {
00992 
00993   double totalProb = 0;
00994   for(uint square=0; square<worldState.squares.size(); square++)
00995   {
00996 
00997     float squareOri = worldState.squares[square].ori*M_PI/180;
00998     Point2D<int> squarePos = worldState.squares[square].pos;
00999     double squareSize = worldState.squares[square].size*0.75; //only evaluate 75% of the length
01000 
01001     if (squareSize < 1)
01002     {
01003       worldState.squares[square].prob = 0;
01004       continue;
01005     }
01006 
01007     Image<float> squareModel(worldState.edgeProb.getDims(), ZEROS);
01008 
01009     drawRectOR(squareModel,
01010         Rectangle(Point2D<int>(squarePos.i-(int)(squareSize/2),squarePos.j-(int)(squareSize/2)),
01011           Dims((int)squareSize, (int)squareSize)),
01012         1.0F,
01013         2,
01014         squareOri);
01015 
01016 
01017     Image<float> squareProb = squareModel*worldState.edgeProb;
01018 
01019     double sum = 0;
01020     double prob = 0;
01021     for(int i=0; i<squareModel.getSize(); i++)
01022     {
01023       if (squareModel[i] > 0)
01024       {
01025         sum++;
01026         prob += squareProb[i];
01027       }
01028     }
01029 
01030     worldState.squares[square].prob = prob;
01031     totalProb += prob;
01032   }
01033 
01034   return totalProb;
01035 }
01036 
01037 
01038 
01039 
01040 
01041 Image<PixRGB<byte> > ObjRec::getWorldPredictImage()
01042 {
01043   return itsPredictWorldImg;
01044 }
01045 
01046 
01047 
01048 ///////////////////////////// Debuging utility functions //////////////////////////////
01049 Image<PixRGB<byte> > showHist(const std::vector<double> &hist)
01050 {
01051   int w = 256, h = 256;
01052   if (hist.size() > (uint)w) w = hist.size();
01053 
01054   if (hist.size() == 0) return Image<PixRGB<byte> >();
01055 
01056   int dw = w / hist.size();
01057   Image<byte> res(w, h, ZEROS);
01058 
01059   // draw lines for 10% marks:
01060   for (int j = 0; j < 10; j++)
01061     drawLine(res, Point2D<int>(0, int(j * 0.1F * h)),
01062              Point2D<int>(w-1, int(j * 0.1F * h)), byte(64));
01063   drawLine(res, Point2D<int>(0, h-1), Point2D<int>(w-1, h-1), byte(64));
01064 
01065   double minii, maxii;
01066   findMinMax(hist, minii, maxii);
01067 
01068    // uniform histogram
01069   if (maxii == minii) minii = maxii - 1.0F;
01070 
01071   double range = maxii - minii;
01072 
01073   printf("Hist: ");
01074   for (uint i = 0; i < hist.size(); i++)
01075     {
01076       if (hist[i] != 0)
01077         printf("%i: %0.2f ", i, hist[i]);
01078       int t = abs(h - int((hist[i] - minii) / range * double(h)));
01079 
01080       // if we have at least 1 pixel worth to draw
01081       if (t < h-1)
01082         {
01083           for (int j = 0; j < dw; j++)
01084             drawLine(res,
01085                      Point2D<int>(dw * i + j, t),
01086                      Point2D<int>(dw * i + j, h - 1),
01087                      byte(255));
01088           //drawRect(res, Rectangle::tlbrI(t,dw*i,h-1,dw*i+dw-1), byte(255));
01089         }
01090     }
01091   printf("\n");
01092   return res;
01093 }
01094 
01095 
01096 #define ORIENTARRAY 36
01097 void calculateOrientationVector(const float x, const float y, const float s,
01098                 const Image<float>& gradmag, const Image<float>& gradorie, Histogram& OV) {
01099 
01100 
01101         // compute the effective blurring sigma corresponding to the
01102         // fractional scale s:
01103         const float sigma = s;
01104 
01105         const float sig = 1.5F * sigma, inv2sig2 = - 0.5F / (sig * sig);
01106         const int dimX = gradmag.getWidth(), dimY = gradmag.getHeight();
01107 
01108         const int xi = int(x + 0.5f);
01109         const int yi = int(y + 0.5f);
01110 
01111         const int rad = int(3.0F * sig);
01112         const int rad2 = rad * rad;
01113 
01114 
01115         // search bounds:
01116         int starty = yi - rad; if (starty < 0) starty = 0;
01117         int stopy = yi + rad; if (stopy >= dimY) stopy = dimY-1;
01118 
01119         // 1. Calculate orientation vector
01120         for (int ind_y = starty; ind_y <= stopy; ind_y ++)
01121         {
01122                 // given that y, get the corresponding range of x values that
01123                 // lie within the disk (and remain within the image):
01124                 const int yoff = ind_y - yi;
01125                 const int bound = int(sqrtf(float(rad2 - yoff*yoff)) + 0.5F);
01126                 int startx = xi - bound; if (startx < 0) startx = 0;
01127                 int stopx = xi + bound; if (stopx >= dimX) stopx = dimX-1;
01128 
01129                 for (int ind_x = startx; ind_x <= stopx; ind_x ++)
01130                 {
01131                         const float dx = float(ind_x) - x, dy = float(ind_y) - y;
01132                         const float distSq = dx * dx + dy * dy;
01133 
01134                         // get gradient:
01135                         const float gradVal = gradmag.getVal(ind_x, ind_y);
01136 
01137                         // compute the gaussian weight for this histogram entry:
01138                         const float gaussianWeight = expf(distSq * inv2sig2);
01139 
01140                         // add this orientation to the histogram
01141                         // [-pi ; pi] -> [0 ; 2pi]
01142                         float angle = gradorie.getVal(ind_x, ind_y) + M_PI;
01143 
01144                         // [0 ; 2pi] -> [0 ; 36]
01145                         angle = 0.5F * angle * ORIENTARRAY / M_PI;
01146                         while (angle < 0.0F) angle += ORIENTARRAY;
01147                         while (angle >= ORIENTARRAY) angle -= ORIENTARRAY;
01148 
01149                         OV.addValueInterp(angle, gaussianWeight * gradVal);
01150                 }
01151         }
01152 
01153 
01154         // smooth the orientation histogram 3 times:
01155         for (int i = 0; i < 3; i++) OV.smooth();
01156 }
01157 
01158 // ######################################################################
01159 
01160 
01161 uint createVectorsAndKeypoints(const float x, const float y, const float s,
01162     const Image<float>& gradmag, const Image<float>& gradorie, Histogram& OV)
01163 {
01164 
01165   const float sigma = s; //itsSigma * powf(2.0F, s / float(itsLumBlur.size() - 3));
01166 
01167   // find the max in the histogram:
01168   float maxPeakValue = OV.findMax();
01169   LINFO("Max peak %f", maxPeakValue);
01170 
01171   const int xi = int(x + 0.5f);
01172   const int yi = int(y + 0.5f);
01173 
01174   uint numkp = 0;
01175 
01176   // 2. Create feature vector and keypoint for each significant
01177   // orientation peak:
01178   for (int bin = 0; bin < ORIENTARRAY; bin++)
01179   {
01180     LINFO("Looking for peaks");
01181     // consider the peak centered around 'bin':
01182     const float midval = OV.getValue(bin);
01183 
01184     // if current value much smaller than global peak, forget it:
01185     if (midval < 0.8F * maxPeakValue) continue;
01186     LINFO("Within 80 of  maximum");
01187 
01188     // get value to the left of current value
01189     const float leftval = OV.getValue((bin == 0) ? ORIENTARRAY-1 : bin-1);
01190 
01191     // get value to the right of current value
01192     const float rightval = OV.getValue((bin == ORIENTARRAY-1) ? 0 : bin+1);
01193     LINFO("%f %f %f", leftval, midval, rightval);
01194 
01195     // only consider local peaks:
01196     if (leftval > midval) continue;
01197     if (rightval > midval) continue;
01198     LINFO("Local Peak");
01199 
01200     // interpolate the values to get the orientation of the peak:
01201     //  with f(x) = ax^2 + bx + c
01202     //   f(-1) = x0 = leftval
01203     //   f( 0) = x1 = midval
01204     //   f(+1) = x2 = rightval
01205     //  => a = (x0+x2)/2 - x1
01206     //     b = (x2-x0)/2
01207     //     c = x1
01208     // f'(x) = 0 => x = -b/2a
01209     const float a  = 0.5f * (leftval + rightval) - midval;
01210     const float b  = 0.5f * (rightval - leftval);
01211     float realangle = float(bin) - 0.5F * b / a;
01212 
01213     realangle *= 2.0F * M_PI / ORIENTARRAY; // [0:36] to [0:2pi]
01214     realangle -= M_PI;                      // [0:2pi] to [-pi:pi]
01215 
01216     // ############ Create keypoint:
01217 
01218     // compute the feature vector:
01219     FeatureVector fv;
01220 
01221     const float sinAngle = sin(realangle), cosAngle = cos(realangle);
01222 
01223     // check this scale
01224     const int radius = int(5.0F * sigma + 0.5F); // NOTE: Lowe uses radius=8?
01225     const float gausssig = float(radius); // 1/2 width of descript window
01226     const float gaussfac = - 0.5F / (gausssig * gausssig);
01227 
01228 
01229     // Scan a window of diameter 2*radius+1 around the point of
01230     // interest, and we will cumulate local samples into a 4x4 grid
01231     // of bins, with interpolation. NOTE: rx and ry loop over a
01232     // square that is assumed centered around the point of interest
01233     // and rotated to the gradient orientation (realangle):
01234 
01235     int scale = abs(int(s));
01236     scale = scale > 5 ? 5 : scale;
01237 
01238     for (int ry = -radius; ry <= radius; ry++)
01239       for (int rx = -radius; rx <= radius; rx++)
01240       {
01241         // rotate the point:
01242         const float newX = rx * cosAngle - ry * sinAngle;
01243         const float newY = rx * sinAngle + ry * cosAngle;
01244 
01245         // get the coords in the image frame of reference:
01246         const float orgX = newX + float(xi);
01247         const float orgY = newY + float(yi);
01248 
01249         // if outside the image, forget it:
01250         if (gradmag.coordsOk(orgX, orgY) == false) continue;
01251 
01252         // find the fractional coords of the corresponding bin
01253         // (we subdivide our window into a 4x4 grid of bins):
01254         const float xf = 2.0F + 2.0F * float(rx) / float(radius);
01255         const float yf = 2.0F + 2.0F * float(ry) / float(radius);
01256 
01257 
01258         // find the Gaussian weight from distance to center and
01259         // get weighted gradient magnitude:
01260         const float gaussFactor = expf((newX*newX+newY*newY) * gaussfac);
01261         const float weightedMagnitude =
01262           gaussFactor * gradmag.getValInterp(orgX, orgY);
01263 
01264         // get the gradient orientation relative to the keypoint
01265         // orientation and scale it for 8 orientation bins:
01266         float gradAng = gradorie.getValInterp(orgX, orgY) - realangle;
01267 
01268         gradAng=fmod(gradAng, 2*M_PI); //bring the range from 0 to M_PI
01269 
01270         //convert from -M_PI to M_PI
01271         if (gradAng < 0.0) gradAng+=2*M_PI; //convert to -M_PI to M_PI
01272         if (gradAng >= M_PI) gradAng-=2*M_PI;
01273         //split to eight bins
01274         const float orient = (gradAng + M_PI) * 8 / (2 * M_PI);
01275 
01276         /*
01277         //reflect the angle to convert from 0 to M_PI
01278         if (gradAng >= M_PI) gradAng-=M_PI;
01279         //split to four bins
01280         const float orient = (gradAng + M_PI) * 4 / (2 * M_PI);
01281          */
01282 
01283         // will be interpolated into 2 x 2 x 2 bins:
01284         LINFO("%f %f %f %f", xf, yf, orient, weightedMagnitude);
01285 
01286         fv.addValue(xf, yf, orient, weightedMagnitude);
01287 
01288       }
01289 
01290     // normalize, clamp, scale and convert to byte:
01291     std::vector<byte> oriVec;
01292     fv.toByteKey(oriVec);
01293     //The key point
01294 
01295     ++ numkp;
01296 
01297   }
01298   return numkp;
01299 }
01300 
01301 
01302 /*double ObjRec::evalLikelihood(const Image<PixRGB<byte> > &worldImg, const Point2D<int> &pos, double angle, double length)
01303 {
01304   Image<float> mag, ori;
01305 
01306   Image<float> worldLum = luminance(worldImg);
01307   gradientSobel(worldLum, mag, ori, 3);
01308 
01309   SHOWIMG(mag);
01310   SHOWIMG(ori);
01311   Histogram OV(36);
01312 
01313   // 1. Calculate main orientation vector
01314   calculateOrientationVector(pos.i, pos.j, 1, mag, ori, OV);
01315 
01316   Image<byte> histImg = OV.getHistogramImage(256, 256, 0, -1);
01317   SHOWIMG((Image<float>)histImg);
01318 
01319   // 2. Create feature vector and keypoint for each significant
01320   // orientation peak:
01321   createVectorsAndKeypoints(pos.i, pos.j, 1, mag, ori, OV);
01322 
01323   return 0;
01324 }*/
01325 
01326 /*
01327 double ObjRec::evalLikelihood(const Image<PixRGB<byte> > &worldImg, const Point2D<int> &pos, double angle, double length)
01328 {
01329   Image<float> mag, ori;
01330 
01331   Image<float> worldLum = luminance(worldImg);
01332   gradientSobel(worldLum, mag, ori, 3);
01333 
01334   SHOWIMG(mag);
01335   SHOWIMG(ori);
01336 
01337   Image<float> posOriImg(mag.getWidth(), 180, ZEROS);
01338   for(int y=0; y<mag.getHeight(); y++)
01339     for(int x=0; x<mag.getWidth(); x++)
01340     {
01341       float angle = ori.getVal(x,y) + M_PI/2;
01342       while(angle > M_PI) angle-=M_PI;
01343       while (angle < 0) angle+=M_PI;
01344       float p = mag.getVal(x,y);
01345       posOriImg.setVal(x, (int)(angle*180/M_PI), p);
01346       if (p>0)
01347         LINFO("%ix%i %f", x,(int)(angle*180/M_PI), p);
01348     }
01349   SHOWIMG(posOriImg);
01350 
01351 
01352 
01353   return 0;
01354 }
01355 */
01356 
01357 void ObjRec::normalizeWorld(WorldState &worldState)
01358 {
01359 
01360   //normalize lines
01361   double sum = 0;
01362   for(uint i=0; i<itsWorldState.lines.size(); i++)
01363     sum += worldState.lines[i].prob;
01364 
01365   for(uint i=0; i<itsWorldState.lines.size(); i++)
01366      worldState.lines[i].prob /= sum;
01367 
01368 
01369 }
01370 
01371 //double ObjRec::evalLikelihood(const Image<PixRGB<byte> > &worldImg, const Point2D<int> &pos, double angle, double length)
01372 //{
01373 //
01374 //  itsCurrentWorldImg = worldImg;
01375 //  if (itsInitProposal)
01376 //  {
01377 //    initialProposal(worldImg);
01378 //    itsInitProposal = false;
01379 //  }
01380 //
01381 // // Image<PixRGB<byte> > edgeImage = showEdgesWorld(itsWorldState);
01382 // // SHOWIMG(edgeImage);
01383 //
01384 //  //New proposal
01385 //  WorldState worldState = itsWorldState;
01386 //  //generateNewLineState(worldState);
01387 //  for(uint i=0; i<itsWorldState.lines.size(); i++)
01388 //  {
01389 //    worldState.lines[i].pos = pos;
01390 //    worldState.lines[i].ori = angle;
01391 //    worldState.lines[i].length = length;
01392 //    worldState.lines[i].color = PixRGB<byte>(255,0,0);
01393 //    worldState.lines[i].prob = 0.1;
01394 //  }
01395 //  normalizeWorld(worldState);
01396 //  itsPredictWorldImg = showLinesWorld(worldState);
01397 //
01398 //  double newProb =  getLineLikelihood(worldState);
01399 //
01400 //  evalNewLinesWorld(itsWorldState, worldState);
01401 //
01402 //  normalizeWorld(itsWorldState);
01403 //
01404 //  itsPredictWorldImg += showLinesWorld(itsWorldState);
01405 //
01406 //  return newProb;
01407 //
01408 //}
01409 
01410 void ObjRec::samplePosterior(const Image<float> &posterior, Point2D<int> &loc, int stop)
01411 {
01412   loc.i = -1; loc.j = -1;
01413   for (int i=0; i<stop; i++)
01414   {
01415     int xRand = randomUpToNotIncluding(posterior.getWidth());
01416     int yRand = randomUpToNotIncluding(posterior.getHeight());
01417     double p = randomDouble();
01418 
01419     //rejection sampling
01420     if (p < posterior.getVal(xRand,yRand))
01421     {
01422       loc.i = xRand;
01423       loc.j = yRand;
01424       return;
01425     }
01426   }
01427 }
01428 
01429 double ObjRec::edgesProb(const Image<PixRGB<byte> > &worldImg)
01430 {
01431 
01432   return edgesLiklyProb(worldImg)*edgesPriorProb();
01433 }
01434 
01435 double ObjRec::edgesLiklyProb(const Image<PixRGB<byte> > &worldImg)
01436 {
01437   Image<float> mag, ori;
01438   Image<float> worldLum = luminance(worldImg);
01439   gradientSobel(worldLum, mag, ori, 3);
01440 
01441   itsWorldState.edges.clear();
01442 
01443   for(int y=0; y<mag.getHeight(); y++)
01444     for(int x=0; x<mag.getWidth(); x++)
01445     {
01446       float angle = ori.getVal(x,y) + M_PI/2;
01447       while(angle > M_PI) angle-=M_PI;
01448       while (angle < 0) angle+=M_PI;
01449       float p = 1.0F/(1.0F+10.0F*exp((-1.0F/100.0F)*mag.getVal(x,y)));
01450       if (p<0.1) p = 0;
01451 
01452 
01453       if (p > 0)
01454       {
01455         EdgeState es;
01456         es.pos = Point2D<int>(x,y);
01457         es.ori = angle*180/M_PI;
01458         es.color = PixRGB<byte>(0,255,0);
01459         es.prob = p;
01460         itsWorldState.edges.push_back(es);
01461       }
01462     }
01463 
01464   return 0;
01465 }
01466 
01467 double ObjRec::edgesPriorProb()
01468 {
01469 
01470   //uniform prior
01471   for(uint i=0; i<itsWorldState.edges.size(); i++)
01472   {
01473     float edgeProb = itsWorldState.edges[i].prob;
01474     float edgePrior = 0.5; //uniform over edge=on and edge=off
01475     itsWorldState.edges[i].prob = edgeProb*edgePrior;
01476   }
01477 
01478   return 0;
01479 }
01480 
01481 void ObjRec::houghLines()
01482 {
01483 
01484   //get the hough voting
01485   Image<float> posVotes(itsImageDims, ZEROS);
01486 
01487   for(uint i=0; i<itsWorldState.edges.size(); i++)
01488   {
01489     //float edgeProb = itsWorldState.edges[i].prob;
01490     Point2D<int> edgeLoc = itsWorldState.edges[i].pos;
01491 
01492     float prob = posVotes.getVal(edgeLoc) + 1;
01493     for(int j=edgeLoc.j-3; j<edgeLoc.j+3; j++)
01494       for(int i=edgeLoc.i-3; i<edgeLoc.i+3; i++)
01495       {
01496         if (posVotes.coordsOk(i,j))
01497         {
01498           float val = posVotes.getVal(i,j);
01499           posVotes.setVal(i,j, val+prob);
01500         }
01501       }
01502 
01503   }
01504   inplaceNormalize(posVotes, 0.0F, 1.0F);
01505 
01506 
01507   SHOWIMG(posVotes);
01508 
01509   Image<float> sampleSpace(posVotes.getDims(), ZEROS);
01510   for(int i=0; i<100; i++)
01511   {
01512     Point2D<int> pos;
01513     {
01514       samplePosterior(posVotes, pos);
01515       if(sampleSpace.coordsOk(pos))
01516         sampleSpace.setVal(pos, posVotes.getVal(pos));
01517     }
01518   }
01519   SHOWIMG(sampleSpace);
01520   Point2D<int> maxPos; float maxVal;
01521   findMax(posVotes, maxPos, maxVal);
01522   LINFO("Max at %ix%i %f", maxPos.i, maxPos.j, maxVal);
01523 
01524 }
01525 
01526 
01527 double ObjRec::evalLikelihood(const Image<PixRGB<byte> > &worldImg, const Point2D<int> &pos, double angle, double length)
01528 {
01529   itsCurrentWorldImg = worldImg;
01530 
01531   double prob = edgesProb(worldImg);
01532 
01533   houghLines();
01534 
01535 
01536   return prob;
01537 }
01538 
01539 
01540 /*double ObjRec::evalLikelihood(const Image<PixRGB<byte> > &worldImg, const Point2D<int> &pos, double angle, double length)
01541 {
01542   itsCurrentWorldImg = worldImg;
01543 
01544 
01545   if (itsInitProposal)
01546   {
01547     initialProposal(worldImg);
01548     itsInitProposal = false;
01549   }
01550 
01551   WorldState worldState = itsWorldState;
01552   generateNewLineState(worldState);
01553   generateNewSquareState(worldState);
01554   //for(uint i=0; i<itsWorldState.lines.size(); i++)
01555   //{
01556   //  worldState.lines[i].pos = pos;
01557   //  worldState.lines[i].ori = angle;
01558   //  worldState.lines[i].length = length;
01559   //  worldState.lines[i].color = PixRGB<byte>(255,0,0);
01560   //  worldState.lines[i].prob = 0.1;
01561   //}
01562 
01563   //for(uint i=0; i<itsWorldState.squares.size(); i++)
01564   //{
01565   //  worldState.squares[i].pos = pos;
01566   //  worldState.squares[i].ori = angle;
01567   //  worldState.squares[i].size = length;
01568   //  worldState.squares[i].color = PixRGB<byte>(255,0,0);
01569   //  worldState.squares[i].prob = 0.1;
01570   //}
01571 
01572  // itsPredictWorldImg = showLinesWorld(worldState);
01573   itsPredictWorldImg = showSquaresWorld(worldState);
01574  // SHOWIMG(itsPredictWorldImg);
01575 
01576 
01577   double newProb =  getLineLikelihood(worldState);
01578   getSquareLikelihood(worldState);
01579 
01580   evalNewLinesWorld(itsWorldState, worldState);
01581   evalNewSquaresWorld(itsWorldState, worldState);
01582 
01583  // normalizeWorld(itsWorldState);
01584 
01585   itsPredictWorldImg += showLinesWorld(itsWorldState);
01586   itsPredictWorldImg += showSquaresWorld(itsWorldState);
01587 
01588   return newProb;
01589 
01590 }*/
01591 
01592 
01593 void ObjRec::train(const Image<PixRGB<byte> > &img, const std::string label)
01594 {
01595 
01596 
01597 
01598 }
01599 
01600 std::string ObjRec::test(const Image<PixRGB<byte> > &img)
01601 {
01602 
01603 
01604   return std::string("Test");
01605 }
01606 
01607 
01608 // ######################################################################
01609 /* So things look consistent in everyone's emacs... */
01610 /* Local Variables: */
01611 /* indent-tabs-mode: nil */
01612 /* End: */
Generated on Sun May 8 08:05:30 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3