00001 /*!@file SceneUnderstanding/GHough.C Generalized Hough */ 00002 00003 00004 00005 // //////////////////////////////////////////////////////////////////// // 00006 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005 // 00007 // by the University of Southern California (USC) and the iLab at USC. // 00008 // See http://iLab.usc.edu for information about this project. // 00009 // //////////////////////////////////////////////////////////////////// // 00010 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00011 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00012 // in Visual Environments, and Applications'' by Christof Koch and // 00013 // Laurent Itti, California Institute of Technology, 2001 (patent // 00014 // pending; application number 09/912,225 filed July 23, 2001; see // 00015 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00016 // //////////////////////////////////////////////////////////////////// // 00017 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00018 // // 00019 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00020 // redistribute it and/or modify it under the terms of the GNU General // 00021 // Public License as published by the Free Software Foundation; either // 00022 // version 2 of the License, or (at your option) any later version. // 00023 // // 00024 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00025 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00026 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00027 // PURPOSE. See the GNU General Public License for more details. // 00028 // // 00029 // You should have received a copy of the GNU General Public License // 00030 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00031 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00032 // Boston, MA 02111-1307 USA. // 00033 // //////////////////////////////////////////////////////////////////// // 00034 // 00035 // Primary maintainer for this file: Lior Elazary <elazary@usc.edu> 00036 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/FeatureMatching/GHough.C $ 00037 // $Id: GHough.C 13815 2010-08-22 17:58:48Z lior $ 00038 // 00039 00040 #ifndef GHough_C_DEFINED 00041 #define GHough_C_DEFINED 00042 00043 #include "FeatureMatching/GHough.H" 00044 #include "Image/DrawOps.H" 00045 #include "GUI/DebugWin.H" 00046 #include "Image/FilterOps.H" 00047 #include <fcntl.h> 00048 #include <cstdio> 00049 00050 00051 namespace 00052 { 00053 pthread_mutex_t itsAccLock; 00054 00055 class GHTJob : public JobWithSemaphore 00056 { 00057 public: 00058 00059 GHTJob(GHough* ghough, int id, const GHough::RTable& rTable, const std::vector<GHough::Feature>& features, 00060 std::vector<GHough::Acc>& acc) : 00061 itsGHough(ghough), 00062 itsId(id), 00063 itsRTable(rTable), 00064 itsFeatures(features), 00065 itsAcc(acc) 00066 {} 00067 00068 virtual ~GHTJob() {} 00069 00070 virtual void run() 00071 { 00072 float maxVotes = 0; 00073 std::vector<GHough::Acc> acc = itsGHough->getVotes(itsId, itsRTable, itsFeatures, maxVotes); 00074 00075 pthread_mutex_lock(&itsAccLock); 00076 for(uint j=0; j<acc.size(); j++) 00077 itsAcc.push_back(acc[j]); 00078 pthread_mutex_unlock(&itsAccLock); 00079 00080 this->markFinished(); 00081 } 00082 00083 virtual const char* jobType() const { return "GHTJob"; } 00084 00085 GHough* itsGHough; 00086 int itsId; 00087 const GHough::RTable& itsRTable; 00088 const std::vector<GHough::Feature>& itsFeatures; 00089 std::vector<GHough::Acc>& itsAcc; 00090 }; 00091 } 00092 00093 // ###################################################################### 00094 GHough::GHough() : 00095 itsNumEntries(20) 00096 { 00097 00098 //itsThreadServer.reset(new WorkThreadServer("GHough", 10)); 00099 00100 if (0 != pthread_mutex_init(&itsAccLock, NULL)) 00101 LFATAL("pthread_mutex_init() failed"); 00102 00103 itsSOFM = new SOFM("Corners", 360, 25,25 ); 00104 00105 } 00106 00107 // ###################################################################### 00108 GHough::~GHough() 00109 { 00110 00111 if (0 != pthread_mutex_destroy(&itsAccLock)) 00112 LERROR("pthread_mutex_destroy() failed"); 00113 } 00114 00115 Point2D<float> GHough::addModel(int& id, const Image<byte>& img, const Image<float>& ang, 00116 Point3D<float> pos, Point3D<float> rot) 00117 { 00118 00119 Model model; 00120 model.id = 0; 00121 model.pos = pos; 00122 model.rot = rot; 00123 00124 00125 Point2D<float> imgLoc; 00126 RTable rTable = createRTable(img, ang, model.imgPos, model.numFeatures, imgLoc); 00127 if (rTable.entries.size() > 0) 00128 { 00129 model.rTables.push_back(rTable); 00130 itsModels.push_back(model); 00131 id = itsModels.size()-1; 00132 } 00133 00134 return imgLoc; 00135 00136 } 00137 00138 Point2D<float> GHough::addModel(int& id, int type, const std::vector<GHough::Feature>& features, 00139 Point3D<float> pos, Point3D<float> rot) 00140 { 00141 00142 Model model; 00143 model.id = 0; 00144 model.pos = pos; 00145 model.rot = rot; 00146 model.type = type; 00147 00148 Point2D<float> imgLoc; 00149 model.numFeatures = features.size(); 00150 RTable rTable = createRTable(features, model.imgPos, imgLoc); 00151 if (rTable.featureEntries.size() > 0) 00152 { 00153 model.rTables.push_back(rTable); 00154 itsModels.push_back(model); 00155 id = itsModels.size()-1; 00156 } 00157 00158 return imgLoc; 00159 00160 } 00161 00162 void GHough::addModel(int id, const Image<float>& img) 00163 { 00164 00165 Image<float> mag, ori; 00166 gradientSobel(img, mag, ori); 00167 00168 ////Non maximal suppersion 00169 mag = nonMaxSuppr(mag, ori); 00170 SHOWIMG(mag); 00171 00172 //createInvRTable(mag, ori); 00173 00174 Model model; 00175 model.id = id; 00176 00177 //RTable rTable = createRTable(mag, ori, model.imgPos, model.numFeatures); 00178 //if (rTable.entries.size() > 0) 00179 //{ 00180 // model.rTables.push_back(rTable); 00181 // itsModels.push_back(model); 00182 //} 00183 00184 } 00185 00186 Point2D<int> GHough::addModel(int id, const std::vector<Point2D<int> >& polygon) 00187 { 00188 00189 Point2D<int> center; 00190 00191 Image<float> mag(320, 240, ZEROS); 00192 Image<float> ori(320, 240, ZEROS); 00193 00194 for(uint i=0; i<polygon.size(); i++) 00195 { 00196 Point2D<int> p1 = polygon[i]; 00197 Point2D<int> p2 = polygon[(i+1)%polygon.size()]; 00198 00199 float ang = atan2(p1.j-p2.j, p2.i - p1.i); 00200 drawLine(mag, p1, p2, 255.0F); 00201 drawLine(ori, p1, p2, ang); 00202 } 00203 00204 Model model; 00205 model.id = id; 00206 00207 RTable rTable = createRTable(mag, ori, center, model.numFeatures); 00208 if (rTable.entries.size() > 0) 00209 { 00210 model.rTables.push_back(rTable); 00211 itsModels.push_back(model); 00212 } 00213 00214 return center; 00215 00216 } 00217 00218 00219 std::vector<GHough::Acc> GHough::getVotes(const Image<float>& img) 00220 { 00221 00222 //std::vector<Acc> acc; 00223 00224 Image<float> mag, ori; 00225 gradientSobel(img, mag, ori); 00226 00227 ////Non maximal suppersion 00228 mag = nonMaxSuppr(mag, ori); 00229 00230 //Image<float> acci = getInvVotes(mag, ori); 00231 //Point2D<int> loc; float max; 00232 //findMax(acci, loc, max); 00233 ////drawCircle(acci, loc, 10, 1550.0F); 00234 //SHOWIMG(acci); 00235 00236 std::vector<GHough::Acc> acc; 00237 00238 for(uint i=0; i<itsModels.size(); i++) 00239 { 00240 for(uint j=0; j<itsModels[i].rTables.size(); j++) 00241 { 00242 std::vector<GHough::Acc> accScale = getVotes(i, itsModels[i].rTables[j], mag, ori); 00243 for(uint j=0; j<accScale.size(); j++) 00244 acc.push_back(accScale[j]); 00245 } 00246 } 00247 00248 //sort the acc 00249 std::sort(acc.begin(), acc.end(), AccCmp()); 00250 00251 drawCircle(mag, acc[0].pos, 3, 255.0F); 00252 SHOWIMG(mag); 00253 00254 return acc; 00255 } 00256 00257 std::vector<GHough::Acc> GHough::getVotes(const Image<float>& mag, const Image<float>& ori) 00258 { 00259 00260 std::vector<GHough::Acc> acc; 00261 00262 for(uint i=0; i<itsModels.size(); i++) 00263 { 00264 for(uint j=0; j<itsModels[i].rTables.size(); j++) 00265 { 00266 std::vector<GHough::Acc> accScale = getVotes(i, itsModels[i].rTables[j], mag, ori); 00267 for(uint j=0; j<accScale.size(); j++) 00268 acc.push_back(accScale[j]); 00269 } 00270 } 00271 00272 //sort the acc 00273 //std::sort(acc.begin(), acc.end(), AccCmp()); 00274 00275 return acc; 00276 } 00277 00278 00279 void GHough::setPosOffset(int id, Point3D<float> pos) 00280 { 00281 00282 itsModels[id].pos = pos; 00283 00284 } 00285 00286 GHough::RTable GHough::createRTable(const Image<byte>& img, const Image<float>& ang, 00287 Point2D<float>& imgPos, int& numFeatures, Point2D<float>& imgLoc) 00288 { 00289 RTable rTable; 00290 00291 //Compute refrance Point 00292 Point2D<int> center(0,0); 00293 int numOfPixels = 0; 00294 00295 imgLoc = Point2D<float>(0,0); 00296 for(int y=0; y<img.getHeight(); y++) 00297 for(int x=0; x<img.getWidth(); x++) 00298 { 00299 if (img.getVal(x,y) > 0) 00300 { 00301 center.i += x; 00302 center.j += y; 00303 numOfPixels++; 00304 00305 if (y > imgLoc.j) 00306 imgLoc = Point2D<float>(x,y); 00307 } 00308 } 00309 numFeatures = numOfPixels; 00310 if (numOfPixels > 0) 00311 center /= numOfPixels; 00312 else 00313 return rTable; 00314 00315 //LINFO("Learn pos"); 00316 //Image<PixRGB<byte> > tmp = img; 00317 //drawCircle(tmp, Point2D<int>(imgLoc), 3, PixRGB<byte>(255,0,0)); 00318 //SHOWIMG(tmp); 00319 00320 00321 imgPos.i = imgLoc.i - center.i; 00322 imgPos.j = imgLoc.j - center.j; 00323 00324 00325 double D=M_PI/itsNumEntries; 00326 00327 for(int y=0; y<img.getHeight(); y++) 00328 for(int x=0; x<img.getWidth(); x++) 00329 { 00330 if (img.getVal(x,y) > 0) 00331 { 00332 double phi = ang.getVal(x,y); 00333 int i = (int)round(phi/D); 00334 rTable.entries[i].push_back(Point2D<float>(x-center.i, y-center.j)); 00335 } 00336 } 00337 return rTable; 00338 } 00339 00340 GHough::RTable GHough::createRTable(const Image<byte>& img, const Image<float>& ang, 00341 Point2D<int>& center, int& numFeatures) 00342 { 00343 RTable rTable; 00344 00345 //Compute refrance Point 00346 center.i = 0; center.j = 0; 00347 int numOfPixels = 0; 00348 00349 for(int y=0; y<img.getHeight(); y++) 00350 for(int x=0; x<img.getWidth(); x++) 00351 { 00352 if (img.getVal(x,y) > 0) 00353 { 00354 center.i += x; 00355 center.j += y; 00356 numOfPixels++; 00357 } 00358 } 00359 numFeatures = numOfPixels; 00360 if (numOfPixels > 0) 00361 center /= numOfPixels; 00362 else 00363 return rTable; 00364 00365 double D=M_PI/itsNumEntries; 00366 00367 for(int y=0; y<img.getHeight(); y++) 00368 for(int x=0; x<img.getWidth(); x++) 00369 { 00370 if (img.getVal(x,y) > 0) 00371 { 00372 double phi = ang.getVal(x,y); 00373 00374 if (phi < 0) phi += M_PI; 00375 if (phi > M_PI) phi -= M_PI; 00376 00377 int i = (int)round(phi/D); 00378 rTable.entries[i].push_back(Point2D<float>(x-center.i, y-center.j)); 00379 } 00380 } 00381 return rTable; 00382 } 00383 00384 GHough::RTable GHough::createRTable(const std::vector<Feature>& features, 00385 Point2D<float>& imgPos, Point2D<float>& imgLoc) 00386 { 00387 RTable rTable; 00388 00389 //Compute refrance Point 00390 imgLoc = Point2D<float>(0,0); 00391 Point2D<float> center(0,0); 00392 for(uint i=0; i<features.size(); i++) 00393 { 00394 center += features[i].loc; 00395 if (features[i].loc.j > imgLoc.j) 00396 imgLoc = features[i].loc; 00397 } 00398 center /= features.size(); 00399 00400 //LINFO("Learn pos"); 00401 //Image<PixRGB<byte> > tmp(150,150,ZEROS); 00402 //for(uint i=0; i<features.size(); i++) 00403 // tmp.setVal(Point2D<int>(features[i].loc), PixRGB<byte>(0,255,0)); 00404 //drawCircle(tmp, Point2D<int>(imgLoc), 3, PixRGB<byte>(255,0,0)); 00405 //SHOWIMG(tmp); 00406 00407 imgPos.i = imgLoc.i - center.i; 00408 imgPos.j = imgLoc.j - center.j; 00409 00410 for(uint i=0; i<features.size(); i++) 00411 { 00412 long idx = getIndex(features[i].values); 00413 00414 Feature f; 00415 f.loc = features[i].loc - center; 00416 f.values = features[i].values; 00417 rTable.featureEntries[idx].push_back(f); 00418 } 00419 00420 return rTable; 00421 } 00422 00423 long GHough::getIndex(const std::vector<float>& values) 00424 { 00425 00426 double D=2*M_PI/45; //itsNumEntries; 00427 00428 //Generate a histogram 00429 int hist[360]; 00430 for(uint i=0; i<360; i++) 00431 hist[i] = 0; 00432 00433 for(uint i=0; i<values.size(); i++) 00434 { 00435 float ang = values[i]; 00436 if (ang < 0) ang += 2*M_PI; 00437 if (ang > 2*M_PI) ang -= M_PI*2; 00438 int idx = (int)round(ang/D); 00439 hist[idx]++; 00440 } 00441 00442 //Show histogram 00443 00444 //for(uint i=0; i<360; i++) 00445 // if (hist[i] > 0) 00446 // printf("%i:%i ", i, hist[i]); 00447 //printf("\n"); 00448 00449 00450 //Generate the index from the histogram 00451 long idx = 0; 00452 for(uint i=0; i<360; i++) 00453 { 00454 if (hist[i] > 0) 00455 idx = (360*idx) + i; 00456 } 00457 //LINFO("Index %ld", idx); 00458 00459 return idx; 00460 00461 } 00462 00463 Point3D<float> GHough::getModelRot(const int id) 00464 { 00465 if (id >= 0 && id < (int)itsModels.size()) 00466 return itsModels[id].rot; 00467 else 00468 { 00469 LFATAL("Invalid model id %i", id); 00470 return Point3D<float>(0,0,0); 00471 } 00472 00473 } 00474 00475 Point2D<float> GHough::getModelImgPos(const int id) 00476 { 00477 if (id >= 0 && id < (int)itsModels.size()) 00478 return itsModels[id].imgPos; 00479 else 00480 { 00481 LFATAL("Invalid model id %i", id); 00482 return Point2D<float>(0,0); 00483 } 00484 } 00485 00486 int GHough::getModelType(const int id) 00487 { 00488 if (id >= 0 && id < (int)itsModels.size()) 00489 return itsModels[id].type; 00490 else 00491 { 00492 LFATAL("Invalid model id %i", id); 00493 return -1; 00494 } 00495 } 00496 00497 Point3D<float> GHough::getModelPosOffset(const int id) 00498 { 00499 if (id >= 0 && id < (int)itsModels.size()) 00500 return itsModels[id].pos; 00501 else 00502 { 00503 LFATAL("Invalid model id %i", id); 00504 return Point3D<float>(0,0,0); 00505 } 00506 } 00507 00508 std::vector<GHough::Acc> GHough::getVotes(const Image<byte>& img, const Image<float>& ang) 00509 { 00510 std::vector<GHough::Acc> acc; 00511 00512 for(uint i=0; i<itsModels.size(); i++) 00513 { 00514 for(uint j=0; j<itsModels[i].rTables.size(); j++) 00515 { 00516 std::vector<GHough::Acc> accScale = getVotes(i, itsModels[i].rTables[j], img, ang); 00517 for(uint j=0; j<accScale.size(); j++) 00518 acc.push_back(accScale[j]); 00519 } 00520 } 00521 00522 //sort the acc 00523 std::sort(acc.begin(), acc.end(), AccCmp()); 00524 00525 return acc; 00526 00527 } 00528 00529 std::vector<GHough::Acc> GHough::getVotes(const std::vector<Feature>& features) 00530 { 00531 00532 //Show the features 00533 Image<PixRGB<byte> > cornersImg(320, 240, ZEROS); 00534 for(uint i=0; i<features.size(); i++) 00535 { 00536 for(uint ai=0; ai<features[i].values.size(); ai++) 00537 { 00538 int x1 = int(cos(features[i].values[ai])*30.0/2.0); 00539 int y1 = int(sin(features[i].values[ai])*30.0/2.0); 00540 Point2D<float> p1(features[i].loc.i-x1, features[i].loc.j+y1); 00541 00542 drawLine(cornersImg, Point2D<int>(features[i].loc), Point2D<int>(p1), PixRGB<byte>(0,255,0)); 00543 } 00544 } 00545 SHOWIMG(cornersImg); 00546 00547 //itsSOFM->RandomWeights(0,1); 00548 //itsSOFM->ReadNet("hough.sofm"); 00549 //for(uint i=0; i<10; i++) 00550 //trainSOFM(); 00551 00552 00553 CpuTimer timer; 00554 timer.reset(); 00555 00556 //std::vector<rutz::shared_ptr<GHTJob> > jobs; 00557 00558 std::vector<GHough::Acc> acc; 00559 uint numModels = 0; 00560 for(uint i=0; i<itsModels.size(); i++) 00561 { 00562 00563 for(uint j=0; j<itsModels[i].rTables.size(); j++) 00564 { 00565 uint numFeatures = getNumFeatures(i); 00566 if (numFeatures < 3) 00567 continue; 00568 if (itsModels[i].type != 1) 00569 continue; 00570 00571 float maxVotes =0; 00572 //Image<PixRGB<byte> > rTableImg = getRTableImg(i); 00573 //SHOWIMG(rTableImg); 00574 std::vector<GHough::Acc> accScale = getVotes2(i, itsModels[i].rTables[j], features, maxVotes); 00575 00576 //if (accScale.size() > 0 && maxVotes > 0.01) 00577 { 00578 LINFO("Model %i/%i rt %i nf %i maxVotes %f rot %f,%f,%f", i, 00579 (uint)itsModels.size(), j, numFeatures, maxVotes, 00580 itsModels[i].rot.x,itsModels[i].rot.y,itsModels[i].rot.z); 00581 Image<PixRGB<byte> > rTableImg = getRTableImg(i); 00582 SHOWIMG(rTableImg); 00583 00584 Image<float> accImg = getAccImg(accScale); 00585 inplaceNormalize(accImg, 0.0F, 255.0F); 00586 Image<PixRGB<byte> > tmp = accImg; 00587 tmp += cornersImg; 00588 SHOWIMG(tmp); 00589 } 00590 00591 for(uint j=0; j<accScale.size(); j++) 00592 acc.push_back(accScale[j]); 00593 00594 //jobs.push_back(rutz::make_shared(new GHTJob(this, i, itsModels[i].rTables[j], features, acc))); 00595 //itsThreadServer->enqueueJob(jobs.back()); 00596 00597 numModels++; 00598 00599 } 00600 } 00601 00602 ////wait for jobs to finish 00603 //while(itsThreadServer->size() > 0) 00604 // usleep(10000); 00605 00606 timer.mark(); 00607 LINFO("Total time %0.2f sec for %i models (%i proposals)", timer.real_secs(), numModels, (uint)acc.size()); 00608 00609 //sort the acc 00610 std::sort(acc.begin(), acc.end(), AccCmp()); 00611 00612 return acc; 00613 00614 } 00615 00616 00617 std::vector<GHough::Acc> GHough::getVotes(int id, const RTable& rTable, 00618 const Image<byte>& img, const Image<float>& ang) 00619 { 00620 double D=M_PI/itsNumEntries; 00621 00622 00623 std::map<unsigned long, Acc> tmpAcc; 00624 00625 Image<float> accImg(320, 240, ZEROS); 00626 00627 for(int y=0; y<img.getHeight(); y++) 00628 for(int x=0; x<img.getWidth(); x++) 00629 { 00630 if (img.getVal(x,y) > 0) 00631 { 00632 double phi = ang.getVal(x,y); 00633 if (phi < 0) phi += M_PI; 00634 if (phi > M_PI) phi -= M_PI; 00635 int i = (int)round(phi/D); 00636 00637 std::map<int, std::vector<Point2D<float> > >::const_iterator iter = 00638 rTable.entries.find(i); 00639 00640 if (iter != rTable.entries.end()) 00641 { 00642 ////Vote 00643 for(uint j=0; j<iter->second.size(); j++) 00644 { 00645 Point2D<float> loc =iter->second[j]; 00646 Point2D<int> voteLoc(int(x-loc.i),int(y-loc.j)); 00647 if (voteLoc.i > 0 && voteLoc.i < 512 && 00648 voteLoc.j > 0 && voteLoc.j < 512) 00649 { 00650 if (accImg.coordsOk(voteLoc)) 00651 accImg.setVal(voteLoc, accImg.getVal(voteLoc) + 1); 00652 unsigned long key = id*512*512 + voteLoc.j*512 + voteLoc.i; 00653 std::map<unsigned long, Acc>::iterator it = tmpAcc.find(key); 00654 if (it != tmpAcc.end()) 00655 it->second.votes++; 00656 else 00657 tmpAcc[key] = Acc(id, voteLoc,1); 00658 } 00659 } 00660 } 00661 } 00662 } 00663 00664 std::vector<Acc> acc; 00665 00666 for(uint i=0; i<100; i++) 00667 { 00668 Point2D<int> maxLoc; float maxVal; 00669 findMax(accImg, maxLoc, maxVal); 00670 00671 acc.push_back(Acc(0, maxLoc, maxVal)); 00672 drawDisk(accImg, maxLoc, 10, 0.0F); 00673 //SHOWIMG(accImg); 00674 } 00675 00676 00677 //std::map<unsigned long, Acc>::iterator it; 00678 //for(it = tmpAcc.begin(); it != tmpAcc.end(); it++) 00679 //{ 00680 // it->second.prob = float(it->second.votes)/float(itsModels[it->second.id].numFeatures); 00681 // //if (it->second.prob > 0.20) 00682 // { 00683 // acc.push_back(it->second); 00684 // } 00685 //} 00686 00687 return acc; 00688 } 00689 00690 00691 std::vector<GHough::Acc> GHough::getVotes(int id, const RTable& rTable, const std::vector<Feature>& features, float& maxVotes) 00692 { 00693 std::map<unsigned long, Acc> tmpAcc; 00694 00695 //Used for appliing a variance over position 00696 //TODO change to a veriance in feature position, not its endpoint 00697 float stddevX = 1.1; 00698 float stddevY = 1.1; 00699 int voteSizeX = int(ceil(stddevX * sqrt(-2.0F * log(exp(-5.0F))))); 00700 int voteSizeY = int(ceil(stddevY * sqrt(-2.0F * log(exp(-5.0F))))); 00701 00702 Image<PixRGB<byte> > tmp(320,240,ZEROS); 00703 00704 int numFeatures = 0; 00705 for(uint fi=0; fi<features.size(); fi++) 00706 { 00707 long idx = getIndex(features[fi].values); 00708 00709 00710 /************/ 00711 for(uint ai=0; ai<features[fi].values.size(); ai++) 00712 { 00713 int x1 = int(cos(features[fi].values[ai])*30.0/2.0); 00714 int y1 = int(sin(features[fi].values[ai])*30.0/2.0); 00715 Point2D<float> p1(features[fi].loc.i-x1, features[fi].loc.j+y1); 00716 00717 drawLine(tmp, Point2D<int>(features[fi].loc), Point2D<int>(p1), PixRGB<byte>(0,255,0)); 00718 } 00719 00720 LINFO("Feature %i indx %ld\n", fi, idx); 00721 SHOWIMG(tmp); 00722 /****************/ 00723 00724 00725 00726 std::map<long, std::vector<Feature > >::const_iterator iter = 00727 rTable.featureEntries.find(idx); 00728 00729 if (iter != rTable.featureEntries.end()) 00730 { 00731 LINFO("Found match"); 00732 ////Vote 00733 for(uint j=0; j<iter->second.size(); j++) 00734 { 00735 Point2D<float> loc =iter->second[j].loc; 00736 00737 Point2D<int> voteLoc(int(features[fi].loc.i-loc.i),int(features[fi].loc.j-loc.j)); 00738 numFeatures ++; 00739 00740 00741 //Vote in a gaussien unsertinty 00742 for(int y=voteLoc.j-voteSizeY; y<voteLoc.j+voteSizeY; y++) 00743 { 00744 float diffY = y-voteLoc.j; 00745 float ry = exp(-((diffY*diffY)/(stddevY*stddevY))); 00746 for(int x=voteLoc.i-voteSizeX; x<voteLoc.i+voteSizeX; x++) 00747 { 00748 float diffX = x-voteLoc.i; 00749 float rx = exp(-((diffX*diffX)/(stddevX*stddevX))); 00750 //float weight = nafState.prob + rRot*rx*ry; 00751 float weight = rx*ry; 00752 00753 if (x > 0 && x < 512 && 00754 y > 0 && y < 512) 00755 { 00756 unsigned long key = id*512*512 + y*512 + x; 00757 00758 std::map<unsigned long, Acc>::iterator it = tmpAcc.find(key); 00759 if (it != tmpAcc.end()) 00760 it->second.votes += weight; 00761 else 00762 tmpAcc[key] = Acc(id, x,y, weight); 00763 } 00764 } 00765 } 00766 } 00767 } 00768 } 00769 00770 std::vector<Acc> acc; 00771 00772 00773 std::map<unsigned long, Acc>::iterator it; 00774 for(it = tmpAcc.begin(); it != tmpAcc.end(); it++) 00775 { 00776 it->second.prob = float(it->second.votes)/float(numFeatures); 00777 //LINFO("id:%i geons %i votes %i features %i prob %f", 00778 // it->second.id, 00779 // getModelType( it->second.id), 00780 // it->second.votes, 00781 // numFeatures, 00782 // it->second.prob); 00783 if (it->second.votes > maxVotes) 00784 maxVotes = it->second.votes; 00785 00786 if (it->second.votes > 1) 00787 { 00788 acc.push_back(it->second); 00789 } 00790 } 00791 00792 return acc; 00793 } 00794 00795 std::vector<GHough::Acc> GHough::getVotes2(int id, const RTable& rTable, const std::vector<Feature>& features, float& maxVotes) 00796 { 00797 std::map<unsigned long, Acc> tmpAcc; 00798 00799 //Used for appliing a variance over position 00800 //TODO change to a veriance in feature position, not its endpoint 00801 float stddevX = 0.5; 00802 float stddevY = 0.5; 00803 int voteSizeX = int(ceil(stddevX * sqrt(-2.0F * log(exp(-5.0F))))); 00804 int voteSizeY = int(ceil(stddevY * sqrt(-2.0F * log(exp(-5.0F))))); 00805 00806 Image<PixRGB<byte> > tmp(320,240,ZEROS); 00807 00808 int numFeatures = 0; 00809 for(uint fi=0; fi<features.size(); fi++) 00810 { 00811 //Build a GMM 00812 std::vector<GaussianDef> gmmF; 00813 double weight = 1.0/double(features[fi].values.size()); //equal weight 00814 for(uint i=0; i<features[fi].values.size(); i++) 00815 gmmF.push_back(GaussianDef(weight, features[fi].values[i], 1*M_PI/180)); //1 deg variance 00816 00817 //Find all the features that are closest to this one and vote 00818 00819 std::map<long, std::vector<Feature> >::const_iterator iter; 00820 for(iter = rTable.featureEntries.begin(); iter != rTable.featureEntries.end(); iter++) 00821 { 00822 for(uint k=0; k<iter->second.size(); k++) 00823 { 00824 const Feature& feature = iter->second[k]; 00825 if (feature.values.size() > 1) 00826 { 00827 std::vector<GaussianDef> gmmG; 00828 double weight = 1.0/double(feature.values.size()); //equal weight 00829 for(uint j=0; j<feature.values.size(); j++) 00830 gmmG.push_back(GaussianDef(weight, feature.values[j], (1*M_PI/180))); //2 deg variance 00831 00832 double dist = L2GMM(gmmF, gmmG); 00833 if (dist < 2) 00834 { 00835 Point2D<float> loc =iter->second[k].loc; 00836 Point2D<int> voteLoc(int(features[fi].loc.i-loc.i),int(features[fi].loc.j-loc.j)); 00837 numFeatures ++; 00838 00839 //Vote in a gaussien unsertinty 00840 for(int y=voteLoc.j-voteSizeY; y<voteLoc.j+voteSizeY; y++) 00841 { 00842 float diffY = y-voteLoc.j; 00843 float ry = exp(-((diffY*diffY)/(stddevY*stddevY))); 00844 for(int x=voteLoc.i-voteSizeX; x<voteLoc.i+voteSizeX; x++) 00845 { 00846 float diffX = x-voteLoc.i; 00847 float rx = exp(-((diffX*diffX)/(stddevX*stddevX))); 00848 //float weight = nafState.prob + rRot*rx*ry; 00849 float weight = rx*ry; 00850 00851 if (x > 0 && x < 512 && 00852 y > 0 && y < 512) 00853 { 00854 unsigned long key = id*512*512 + y*512 + x; 00855 00856 std::map<unsigned long, Acc>::iterator it = tmpAcc.find(key); 00857 if (it != tmpAcc.end()) 00858 it->second.votes += weight; 00859 else 00860 tmpAcc[key] = Acc(id, x,y, weight); 00861 } 00862 } 00863 } 00864 } 00865 00866 } 00867 } 00868 } 00869 00870 00871 } 00872 00873 std::vector<Acc> acc; 00874 00875 00876 std::map<unsigned long, Acc>::iterator it; 00877 for(it = tmpAcc.begin(); it != tmpAcc.end(); it++) 00878 { 00879 it->second.prob = float(it->second.votes)/float(numFeatures); 00880 //LINFO("id:%i geons %i votes %i features %i prob %f", 00881 // it->second.id, 00882 // getModelType( it->second.id), 00883 // it->second.votes, 00884 // numFeatures, 00885 // it->second.prob); 00886 if (it->second.votes > maxVotes) 00887 maxVotes = it->second.votes; 00888 00889 if (it->second.votes > 1) 00890 { 00891 acc.push_back(it->second); 00892 } 00893 } 00894 00895 return acc; 00896 } 00897 00898 //Image<float> GHough::getRTableImg(const int id) 00899 //{ 00900 // 00901 // Image<float> img(320,240,ZEROS); 00902 // for(uint tbl=0; tbl<itsModels[id].rTables.size() && tbl < 1; tbl++) 00903 // { 00904 // RTable rTable = itsModels[id].rTables[tbl]; 00905 // 00906 // std::map<int, std::vector<Point2D<float> > >::const_iterator iter; 00907 // for(iter = rTable.entries.begin(); iter != rTable.entries.end(); iter++) 00908 // { 00909 // //int ori = iter->first; 00910 // for(uint k=0; k<iter->second.size(); k++) 00911 // { 00912 // Point2D<int> loc = Point2D<int>(iter->second[k]) + Point2D<int>(320/2, 240/2); 00913 // img.setVal(loc, 255.0F); 00914 // } 00915 // } 00916 // } 00917 // 00918 // return img; 00919 // 00920 //} 00921 00922 Image<float> GHough::getAccImg(std::vector<GHough::Acc>& acc) 00923 { 00924 Image<float> img(320,240,ZEROS); 00925 00926 00927 for(uint i=0; i<acc.size(); i++) 00928 img.setVal(acc[i].pos, acc[i].votes); 00929 00930 Point2D<int> loc; float val; 00931 findMax(img, loc, val); 00932 LINFO("Max at %ix%i val %f", loc.i, loc.j, val); 00933 00934 return img; 00935 } 00936 00937 Image<PixRGB<byte> > GHough::getRTableImg(const int id) 00938 { 00939 00940 Image<PixRGB<byte> > img(320,240,ZEROS); 00941 for(uint tbl=0; tbl<itsModels[id].rTables.size() && tbl < 1; tbl++) 00942 { 00943 const RTable& rTable = itsModels[id].rTables[tbl]; 00944 00945 std::map<long, std::vector<Feature> >::const_iterator iter; 00946 for(iter = rTable.featureEntries.begin(); iter != rTable.featureEntries.end(); iter++) 00947 { 00948 //int ori = iter->first; 00949 for(uint k=0; k<iter->second.size(); k++) 00950 { 00951 const Feature& feature = iter->second[k]; 00952 Point2D<int> loc = Point2D<int>(feature.loc) + Point2D<int>(320/2, 240/2); 00953 drawCircle(img, loc, 3, PixRGB<byte>(255,0,0)); 00954 00955 for(uint ai=0; ai<feature.values.size(); ai++) 00956 { 00957 int x1 = int(cos(feature.values[ai])*30.0/2.0); 00958 int y1 = int(sin(feature.values[ai])*30.0/2.0); 00959 Point2D<float> p1(loc.i-x1, loc.j+y1); 00960 00961 drawLine(img, Point2D<int>(loc), Point2D<int>(p1), PixRGB<byte>(0,255,0)); 00962 } 00963 } 00964 } 00965 } 00966 return img; 00967 } 00968 00969 00970 void GHough::trainSOFM() 00971 { 00972 00973 Image<PixRGB<byte> > tmp = itsSOFM->getWeightsImage(); 00974 SHOWIMG(tmp); 00975 00976 std::vector<Feature> features; 00977 00978 for(uint obj=0; obj<itsModels.size(); obj++) 00979 { 00980 for(uint tbl=0; tbl<itsModels[obj].rTables.size() && tbl < 1; tbl++) 00981 { 00982 const RTable& rTable = itsModels[obj].rTables[tbl]; 00983 00984 std::map<long, std::vector<Feature> >::const_iterator iter; 00985 for(iter = rTable.featureEntries.begin(); iter != rTable.featureEntries.end(); iter++) 00986 { 00987 for(uint k=0; k<iter->second.size(); k++) 00988 { 00989 const Feature& feature = iter->second[k]; 00990 if (feature.values.size() > 1) 00991 features.push_back(feature); 00992 //Point2D<int> loc = Point2D<int>(feature.loc) + Point2D<int>(320/2, 240/2); 00993 00994 //itsSOFM->setInput(hist); 00995 //itsSOFM->Propagate(); 00996 00997 //double winnerVal; 00998 //Point2D<int> winnerId = itsSOFM->getWinner(winnerVal); 00999 01000 //itsSOFM->organize(hist); 01001 01002 } 01003 } 01004 } 01005 //LINFO("Obj %i/%lu done", obj, itsModels.size()); 01006 01007 // Image<PixRGB<byte> > tmp = itsSOFM->getWeightsImage(); 01008 // SHOWIMG(tmp); 01009 } 01010 //itsSOFM->WriteNet("hough.sofm"); 01011 01012 //Image<float> amap = itsSOFM->getActMap(); 01013 //SHOWIMG(amap); 01014 // 01015 01016 int idx = 1203; 01017 01018 //Build a GMM 01019 std::vector<GaussianDef> gmmF; 01020 double weight = 1.0/double(features[idx].values.size()); //equal weight 01021 for(uint i=0; i<features[idx].values.size(); i++) 01022 gmmF.push_back(GaussianDef(weight, features[idx].values[i], 1*M_PI/180)); //2 deg variance 01023 01024 Image<PixRGB<byte> > qImg(320,240,ZEROS); 01025 for(uint ai=0; ai<features[idx].values.size(); ai++) 01026 { 01027 int x1 = int(cos(features[idx].values[ai])*30.0/2.0); 01028 int y1 = int(sin(features[idx].values[ai])*30.0/2.0); 01029 Point2D<float> p1(320/2-x1, 240/2+y1); 01030 01031 drawLine(qImg, Point2D<int>(320/2,240/2), Point2D<int>(p1), PixRGB<byte>(0,255,0)); 01032 } 01033 SHOWIMG(qImg); 01034 01035 LINFO("Features %i", (uint)features.size()); 01036 for(uint i=0; i<features.size(); i++) 01037 { 01038 printf("Feature c: "); 01039 for(uint j=0; j<features[idx].values.size(); j++) 01040 printf("%f ", features[idx].values[j]*180/M_PI); 01041 printf("\n"); 01042 01043 printf("Feature %i: ", i); 01044 for(uint j=0; j<features[i].values.size(); j++) 01045 printf("%f ", features[i].values[j]*180/M_PI); 01046 printf("\n"); 01047 01048 01049 std::vector<GaussianDef> gmmG; 01050 double weight = 1.0/double(features[i].values.size()); //equal weight 01051 for(uint j=0; j<features[i].values.size(); j++) 01052 gmmG.push_back(GaussianDef(weight, features[i].values[j], (1*M_PI/180))); //2 deg variance 01053 01054 double dist = L2GMM(gmmF, gmmG); 01055 LINFO("Dist %f", dist); 01056 LINFO("\n"); 01057 01058 if (dist < 2) 01059 { 01060 Image<PixRGB<byte> > tmp2 = qImg; 01061 for(uint ai=0; ai<features[i].values.size(); ai++) 01062 { 01063 int x1 = int(cos(features[i].values[ai])*30.0/2.0); 01064 int y1 = int(sin(features[i].values[ai])*30.0/2.0); 01065 Point2D<float> p1(320/2-x1, 240/2+y1); 01066 01067 drawLine(tmp2, Point2D<int>(320/2,240/2), Point2D<int>(p1), PixRGB<byte>(255,0,0)); 01068 } 01069 SHOWIMG(tmp2); 01070 } 01071 } 01072 01073 } 01074 01075 01076 uint GHough::getNumFeatures(const int id) 01077 { 01078 01079 uint numFeatures=0; 01080 for(uint tbl=0; tbl<itsModels[id].rTables.size() && tbl < 1; tbl++) 01081 { 01082 const RTable& rTable = itsModels[id].rTables[tbl]; 01083 01084 std::map<long, std::vector<Feature> >::const_iterator iter; 01085 for(iter = rTable.featureEntries.begin(); iter != rTable.featureEntries.end(); iter++) 01086 { 01087 //int ori = iter->first; 01088 for(uint k=0; k<iter->second.size(); k++) 01089 { 01090 numFeatures++; 01091 } 01092 } 01093 } 01094 return numFeatures; 01095 01096 } 01097 01098 //Image<float> GHough::getCorners() 01099 //{ 01100 // 01101 // float hist[360]; 01102 // 01103 // for(uint obj=0; obj<itsModels.size(); obj++) 01104 // for(uint tbl=0; tbl<itsModels[id].rTables.size() && tbl < 1; tbl++) 01105 // { 01106 // RTable rTable = itsModels[id].rTables[tbl]; 01107 // 01108 // std::map<long, std::vector<Feature> >::const_iterator iter; 01109 // for(iter = rTable.featureEntries.begin(); iter != rTable.featureEntries.end(); iter++) 01110 // { 01111 // for(uint j=0; j<iter->second.size(); j++) 01112 // { 01113 // Point2D<float> loc =iter->second[j].loc; 01114 // numFeatures ++; 01115 // Point2D<int> voteLoc(int(features[fi].loc.i-loc.i),int(features[fi].loc.j-loc.j)); 01116 // if (voteLoc.i > 0 && voteLoc.i < 512 && 01117 // voteLoc.j > 0 && voteLoc.j < 512) 01118 // { 01119 // unsigned long key = id*512*512 + voteLoc.j*512 + voteLoc.i; 01120 // std::map<unsigned long, Acc>::iterator it = tmpAcc.find(key); 01121 // if (it != tmpAcc.end()) 01122 // it->second.votes++; 01123 // else 01124 // tmpAcc[key] = Acc(id, voteLoc); 01125 // } 01126 // } 01127 // } 01128 // } 01129 // 01130 // return Image<float>(); 01131 //} 01132 01133 01134 void GHough::createInvRTable(const Image<byte>& img, const Image<float>& ang) 01135 { 01136 01137 //Compute refrance Point 01138 Point2D<int> center(0,0); 01139 int numOfPixels = 0; 01140 01141 for(int y=0; y<img.getHeight(); y++) 01142 for(int x=0; x<img.getWidth(); x++) 01143 { 01144 if (img.getVal(x,y) > 0) 01145 { 01146 center.i += x; 01147 center.j += y; 01148 numOfPixels++; 01149 } 01150 } 01151 center /= numOfPixels; 01152 01153 int entries = 5; 01154 double D=M_PI/entries; 01155 01156 Model model; 01157 model.id = 0; 01158 01159 for(int y=0; y<img.getHeight(); y++) 01160 for(int x=0; x<img.getWidth(); x++) 01161 { 01162 if (img.getVal(x,y) > 0) 01163 { 01164 Point2D<int> w2 = findInvFeature(x,y, img, ang); 01165 01166 if (w2.isValid()) 01167 { 01168 //Compute beta 01169 double phi = tan(ang.getVal(x,y)); 01170 double phj = tan(ang.getVal(w2)); 01171 01172 double beta=1.57; 01173 if ((1.0+phi*phj) != 0) 01174 beta=atan((phi-phj)/(1.0+phi*phj)); 01175 01176 //compute k 01177 double ph=1.57; 01178 if((x-center.i)!=0) 01179 ph=atan(float(y-center.j)/float(x-center.i)); 01180 double k=ph-ang.getVal(x,y); 01181 01182 //Insert into the table 01183 int i=(int)round((beta+(M_PI/2))/D); 01184 01185 model.invRTable[i].push_back(k); 01186 01187 } 01188 } 01189 } 01190 01191 itsModels.push_back(model); 01192 } 01193 01194 01195 Point2D<int> GHough::findInvFeature(const int x, const int y, const Image<float>&img, const Image<float>& ang) 01196 { 01197 double alpha = M_PI/4; 01198 //Find a second feature point 01199 Point2D<int> w2(-1,-1); 01200 double phi = ang.getVal(x,y) + M_PI/2; 01201 double m = tan(phi-alpha); 01202 01203 //Follow a line (in bouth direction of x,y) 01204 //and find the next feature from that location 01205 if (m>-1 && m<1) 01206 { 01207 for(int i=3; i<img.getWidth(); i++) 01208 { 01209 int c = x + i; 01210 int j=(int)round(m*(x-c)+y); 01211 Point2D<int> loc(c,j); 01212 01213 if (img.coordsOk(loc) && img.getVal(loc) > 0) 01214 { 01215 w2 = loc; //We found the feature 01216 break; 01217 } else { 01218 //Look in the other direction 01219 c = x - i; 01220 j=(int)round(m*(x-c)+y); 01221 loc = Point2D<int>(c,j); 01222 if (img.coordsOk(loc) && img.getVal(loc) > 0) 01223 { 01224 w2 = loc; //We found the feature 01225 break; 01226 } 01227 } 01228 } 01229 } else { 01230 for(int i=3; i<img.getHeight(); i++) 01231 { 01232 int c = y + i; 01233 int j=(int)round(x+(y-c)/m); 01234 Point2D<int> loc(j,c); 01235 01236 if (img.coordsOk(loc) && img.getVal(loc) > 0) 01237 { 01238 w2 = loc; //We found the feature 01239 break; 01240 } else { 01241 //Look in the other direction 01242 c = y - i; 01243 j=(int)round(x+(y-c)/m); 01244 loc = Point2D<int>(j,c); 01245 if (img.coordsOk(loc) && img.getVal(loc) > 0) 01246 { 01247 w2 = loc; //We found the feature 01248 break; 01249 } 01250 } 01251 } 01252 } 01253 01254 return w2; 01255 } 01256 01257 Image<float> GHough::getInvVotes(const Image<byte>& img, 01258 const Image<float>& ang) 01259 { 01260 int entries = 5; 01261 double D=M_PI/entries; 01262 01263 Image<float> acc(img.getDims(), ZEROS); 01264 01265 for(int y=0; y<img.getHeight(); y++) 01266 for(int x=0; x<img.getWidth(); x++) 01267 { 01268 if (img.getVal(x,y) > 0) 01269 { 01270 Point2D<int> w2 = findInvFeature(x,y,img, ang); 01271 01272 if (w2.isValid()) 01273 { 01274 //Compute beta 01275 double phi = tan(ang.getVal(x,y)); 01276 double phj = tan(ang.getVal(w2)); 01277 01278 double beta=1.57; 01279 if ((1+phi*phj) != 0) 01280 beta=atan((phi-phj)/(1+phi*phj)); 01281 01282 //Read from rTable 01283 int i=(int)round((beta+(M_PI/2))/D); 01284 01285 //Search for k 01286 std::map<int, std::vector<double> >::iterator iter = 01287 itsModels[0].invRTable.find(i); 01288 01289 for(uint j=0; j<iter->second.size(); j++) 01290 { 01291 float k=iter->second[j]; 01292 //lines of votes 01293 float m=tan(k+ang.getVal(x,y)); 01294 if (m>-1 && m<1) 01295 { 01296 for(int x0=1; x0<img.getWidth(); x0++) 01297 { 01298 int y0=(int)round(y+m*(x0-x)); 01299 if(y0>0 && y0<img.getHeight()) 01300 acc.setVal(x0,y0, acc.getVal(x0,y0)+1); 01301 } 01302 } else { 01303 for(int y0=0; y0<img.getHeight(); y0++) 01304 { 01305 int x0=(int)round(x+(y0-y)/m); 01306 if(x0>0 && x0<img.getWidth()) 01307 acc.setVal(x0,y0, acc.getVal(x0,y0)+1); 01308 } 01309 } 01310 } 01311 01312 } 01313 } 01314 } 01315 01316 return acc; 01317 } 01318 01319 01320 void GHough::writeTable(const char* filename) 01321 { 01322 int fd; 01323 01324 if ((fd = creat(filename, 0644)) == -1) 01325 LFATAL("Can not open %s for saving\n", filename); 01326 01327 //Write the Dims of the table 01328 size_t numModels = itsModels.size(); 01329 int ret = write(fd, (char *) &numModels, sizeof(size_t)); 01330 01331 for(uint i=0; i<numModels; i++) 01332 { 01333 ret = write(fd, (char *) &itsModels[i].id, sizeof(int)); 01334 ret = write(fd, (char *) &itsModels[i].type, sizeof(int)); 01335 ret = write(fd, (char *) &itsModels[i].pos, sizeof(Point3D<float>)); 01336 ret = write(fd, (char *) &itsModels[i].rot, sizeof(Point3D<float>)); 01337 ret = write(fd, (char *) &itsModels[i].imgPos, sizeof(Point2D<float>)); 01338 ret = write(fd, (char *) &itsModels[i].numFeatures, sizeof(int)); 01339 01340 01341 size_t numTables = itsModels[i].rTables.size(); 01342 ret = write(fd, (char *) &numTables, sizeof(size_t)); 01343 01344 for(uint j=0; j<numTables; j++) 01345 { 01346 //Size of each table 01347 RTable& rTable = itsModels[i].rTables[j]; 01348 01349 //Entries 01350 size_t numEntries = rTable.entries.size(); 01351 ret = write(fd, (char *) &numEntries, sizeof(size_t)); 01352 01353 std::map<int, std::vector<Point2D<float> > >::const_iterator iter; 01354 for(iter = rTable.entries.begin(); iter != rTable.entries.end(); iter++) 01355 { 01356 ret = write(fd, (char *) &iter->first, sizeof(int)); 01357 01358 size_t numPos = iter->second.size(); 01359 ret = write(fd, (char *) &numPos, sizeof(size_t)); 01360 01361 for(uint k=0; k<numPos; k++) 01362 ret = write(fd, (char *) &iter->second[k], sizeof(Point2D<float>)); 01363 } 01364 01365 //Feature Entries 01366 size_t numFeatureEntries = rTable.featureEntries.size(); 01367 ret = write(fd, (char *) &numFeatureEntries, sizeof(size_t)); 01368 01369 std::map<long, std::vector<Feature> >::const_iterator fiter; 01370 for(fiter = rTable.featureEntries.begin(); fiter != rTable.featureEntries.end(); fiter++) 01371 { 01372 ret = write(fd, (char *) &fiter->first, sizeof(long)); 01373 01374 size_t numFeatures = fiter->second.size(); 01375 ret = write(fd, (char *) &numFeatures, sizeof(size_t)); 01376 01377 for(uint k=0; k<numFeatures; k++) 01378 { 01379 ret = write(fd, (char *) &fiter->second[k].loc, sizeof(Point2D<float>)); 01380 01381 size_t numValues = fiter->second[k].values.size(); 01382 ret = write(fd, (char *) &numValues, sizeof(size_t)); 01383 for(uint ii=0; ii<numValues; ii++) 01384 ret = write(fd, (char *) &fiter->second[k].values[ii], sizeof(float)); 01385 } 01386 } 01387 01388 } 01389 } 01390 01391 close(fd); 01392 } 01393 01394 void GHough::readTable(const char* filename) 01395 { 01396 int fd; 01397 if ((fd = open(filename, 0, 0644)) == -1) return; 01398 01399 LINFO("Reading from %s", filename); 01400 01401 //Write the Dims of the table 01402 size_t numModels; 01403 int ret = read(fd, (char *) &numModels, sizeof(size_t)); 01404 01405 01406 itsModels.clear(); 01407 01408 for(uint i=0; i<numModels; i++) 01409 { 01410 Model model; 01411 ret = read(fd, (char *) &model.id, sizeof(int)); 01412 ret = read(fd, (char *) &model.type, sizeof(int)); 01413 ret = read(fd, (char *) &model.pos, sizeof(Point3D<float>)); 01414 ret = read(fd, (char *) &model.rot, sizeof(Point3D<float>)); 01415 ret = read(fd, (char *) &model.imgPos, sizeof(Point2D<float>)); 01416 ret = read(fd, (char *) &model.numFeatures, sizeof(int)); 01417 01418 size_t numTables; 01419 ret = read(fd, (char *) &numTables, sizeof(size_t)); 01420 01421 int totalFeatures = 0; 01422 01423 for(uint j=0; j<numTables; j++) 01424 { 01425 //Size of each table 01426 01427 RTable rTable; 01428 01429 //features 01430 size_t numEntries; 01431 ret = read(fd, (char *) &numEntries, sizeof(size_t)); 01432 for(uint k=0; k<numEntries; k++) 01433 { 01434 int key; 01435 ret = read(fd, (char *) &key, sizeof(int)); 01436 01437 size_t numPos; 01438 ret = read(fd, (char *) &numPos, sizeof(size_t)); 01439 01440 for(uint ii=0; ii<numPos; ii++) 01441 { 01442 Point2D<float> loc; 01443 ret = read(fd, (char *) &loc, sizeof(Point2D<float>)); 01444 rTable.entries[key].push_back(loc); 01445 } 01446 } 01447 01448 //Feature Entries 01449 size_t numFeatureEntries; 01450 ret = read(fd, (char *) &numFeatureEntries, sizeof(size_t)); 01451 for(uint k=0; k<numFeatureEntries; k++) 01452 { 01453 long key; 01454 ret = read(fd, (char *) &key, sizeof(long)); 01455 01456 size_t numFeatures; 01457 ret = read(fd, (char *) &numFeatures, sizeof(size_t)); 01458 01459 for(uint ii=0; ii<numFeatures; ii++) 01460 { 01461 Feature f; 01462 ret = read(fd, (char *) &f.loc, sizeof(Point2D<float>)); 01463 totalFeatures++; 01464 01465 size_t numValues; 01466 ret = read(fd, (char *) &numValues, sizeof(size_t)); 01467 01468 for(uint jj=0; jj<numValues; jj++) 01469 { 01470 float value; 01471 ret = read(fd, (char *) &value, sizeof(float)); 01472 f.values.push_back(value); 01473 } 01474 01475 rTable.featureEntries[key].push_back(f); 01476 } 01477 } 01478 01479 model.rTables.push_back(rTable); 01480 } 01481 itsModels.push_back(model); 01482 } 01483 LINFO("Added %i models", (uint)itsModels.size()); 01484 close(fd); 01485 } 01486 01487 01488 01489 // ###################################################################### 01490 /* So things look consistent in everyone's emacs... */ 01491 /* Local Variables: */ 01492 /* indent-tabs-mode: nil */ 01493 /* End: */ 01494 01495 #endif 01496