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: */