00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
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
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
00169 mag = nonMaxSuppr(mag, ori);
00170 SHOWIMG(mag);
00171
00172
00173
00174 Model model;
00175 model.id = id;
00176
00177
00178
00179
00180
00181
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
00223
00224 Image<float> mag, ori;
00225 gradientSobel(img, mag, ori);
00226
00227
00228 mag = nonMaxSuppr(mag, ori);
00229
00230
00231
00232
00233
00234
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
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
00273
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
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
00316
00317
00318
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
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
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
00401
00402
00403
00404
00405
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;
00427
00428
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
00443
00444
00445
00446
00447
00448
00449
00450
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
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
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
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
00548
00549
00550
00551
00552
00553 CpuTimer timer;
00554 timer.reset();
00555
00556
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
00573
00574 std::vector<GHough::Acc> accScale = getVotes2(i, itsModels[i].rTables[j], features, maxVotes);
00575
00576
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
00595
00596
00597 numModels++;
00598
00599 }
00600 }
00601
00602
00603
00604
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
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
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
00674 }
00675
00676
00677
00678
00679
00680
00681
00682
00683
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
00696
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
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
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
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
00778
00779
00780
00781
00782
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
00800
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
00812 std::vector<GaussianDef> gmmF;
00813 double weight = 1.0/double(features[fi].values.size());
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));
00816
00817
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());
00829 for(uint j=0; j<feature.values.size(); j++)
00830 gmmG.push_back(GaussianDef(weight, feature.values[j], (1*M_PI/180)));
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
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
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
00881
00882
00883
00884
00885
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
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
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
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
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002 }
01003 }
01004 }
01005
01006
01007
01008
01009 }
01010
01011
01012
01013
01014
01015
01016 int idx = 1203;
01017
01018
01019 std::vector<GaussianDef> gmmF;
01020 double weight = 1.0/double(features[idx].values.size());
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));
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());
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)));
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
01088 for(uint k=0; k<iter->second.size(); k++)
01089 {
01090 numFeatures++;
01091 }
01092 }
01093 }
01094 return numFeatures;
01095
01096 }
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134 void GHough::createInvRTable(const Image<byte>& img, const Image<float>& ang)
01135 {
01136
01137
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
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
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
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
01199 Point2D<int> w2(-1,-1);
01200 double phi = ang.getVal(x,y) + M_PI/2;
01201 double m = tan(phi-alpha);
01202
01203
01204
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;
01216 break;
01217 } else {
01218
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;
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;
01239 break;
01240 } else {
01241
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;
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
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
01283 int i=(int)round((beta+(M_PI/2))/D);
01284
01285
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
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
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
01347 RTable& rTable = itsModels[i].rTables[j];
01348
01349
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
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
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
01426
01427 RTable rTable;
01428
01429
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
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
01491
01492
01493
01494
01495 #endif
01496