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 #ifndef V4_C_DEFINED
00039 #define V4_C_DEFINED
00040
00041 #include "plugins/SceneUnderstanding/V4.H"
00042
00043 #include "Image/DrawOps.H"
00044 #include "Image/MathOps.H"
00045 #include "Image/Kernels.H"
00046 #include "Image/FilterOps.H"
00047 #include "Image/Convolutions.H"
00048 #include "Image/fancynorm.H"
00049 #include "Image/Point3D.H"
00050 #include "Simulation/SimEventQueue.H"
00051 #include "Neuro/EnvVisualCortex.H"
00052 #include "GUI/DebugWin.H"
00053 #include "Util/CpuTimer.H"
00054 #include "Util/JobServer.H"
00055 #include "Util/JobWithSemaphore.H"
00056 #include <math.h>
00057 #include <fcntl.h>
00058 #include <limits>
00059 #include <string>
00060 #include <queue>
00061
00062 const ModelOptionCateg MOC_V4 = {
00063 MOC_SORTPRI_3, "V4-Related Options" };
00064
00065
00066 const ModelOptionDef OPT_V4ShowDebug =
00067 { MODOPT_ARG(bool), "V4ShowDebug", &MOC_V4, OPTEXP_CORE,
00068 "Show debug img",
00069 "v4-debug", '\0', "<true|false>", "false" };
00070
00071 namespace
00072 {
00073 class GHTJob : public JobWithSemaphore
00074 {
00075 public:
00076
00077 GHTJob(V4* v4, Image<float>& acc, int angIdx, std::vector<V4::RTableEntry>& rTable) :
00078 itsV4(v4),
00079 itsAcc(acc),
00080 itsAngIdx(angIdx),
00081 itsRTable(rTable)
00082 {}
00083
00084 virtual ~GHTJob() {}
00085
00086 virtual void run()
00087 {
00088 itsV4->voteForFeature(itsAcc, itsAngIdx, itsRTable);
00089
00090 this->markFinished();
00091 }
00092
00093 virtual const char* jobType() const { return "GHTJob"; }
00094 V4* itsV4;
00095 Image<float>& itsAcc;
00096 int itsAngIdx;
00097 std::vector<V4::RTableEntry>& itsRTable;
00098 };
00099 }
00100
00101
00102
00103 V4::V4(OptionManager& mgr, const std::string& descrName,
00104 const std::string& tagName) :
00105 SimModule(mgr, descrName, tagName),
00106 SIMCALLBACK_INIT(SimEventV2Output),
00107 SIMCALLBACK_INIT(SimEventV4dOutput),
00108 SIMCALLBACK_INIT(SimEventUserInput),
00109 SIMCALLBACK_INIT(SimEventSaveOutput),
00110 itsShowDebug(&OPT_V4ShowDebug, this),
00111 itsMaxVal(0),
00112 itsGHTAngStep(5),
00113 itsObjectsDist(370.00)
00114 {
00115 itsThreadServer.reset(new WorkThreadServer("V4", 100));
00116
00117
00118 itsDebugImg = Image<PixRGB<byte> >(302,240,ZEROS);
00119
00120
00121 itsCamera = Camera(Point3D<float>(0,0,0.0),
00122 Point3D<float>(0, 0,0),
00123 450,
00124 320,
00125 240);
00126
00127
00128 itsGeons.resize(3);
00129
00130 GeonOutline triangle;
00131 triangle.geonType = TRIANGLE;
00132 triangle.outline.push_back(Point3D<float>(0.0,0, 0.0));
00133 triangle.outline.push_back(Point3D<float>(0.0,-40.0, 0.0));
00134 triangle.outline.push_back(Point3D<float>(40.0, 0.0, 0.0));
00135
00136 triangle.NAFTemplate.push_back(
00137 V4d::NAFState(Point3D<float>(0,0,0), 135*M_PI/180, V4d::VERTIX,
00138 Point3D<float>(10,10,1), 1*M_PI/180));
00139 triangle.NAFTemplate.push_back(
00140 V4d::NAFState(Point3D<float>(0,40.0,0), -90*M_PI/180, V4d::RIGHT_VERTIX,
00141 Point3D<float>(10,10,1), 1*M_PI/180));
00142 triangle.NAFTemplate.push_back(
00143 V4d::NAFState(Point3D<float>(40.0,40.0,0), -90*M_PI/180, V4d::VERTIX,
00144 Point3D<float>(10,10,1), 1*M_PI/180));
00145
00146
00147 alignToCenterOfMass(triangle);
00148 itsGeons[TRIANGLE] = triangle;
00149
00150
00151
00152 GeonOutline square;
00153 square.geonType = SQUARE;
00154 square.outline.push_back(Point3D<float>(0.0,0, 0.0));
00155 square.outline.push_back(Point3D<float>(0.0, 30.0, 0.0));
00156 square.outline.push_back(Point3D<float>(30, 30.0, 0.0));
00157 square.outline.push_back(Point3D<float>(30,0.0, 0.0));
00158
00159 square.NAFTemplate.push_back(
00160 V4d::NAFState(Point3D<float>(0,0,0), 0*M_PI/180, V4d::RIGHT_VERTIX,
00161 Point3D<float>(10,10,1), 1*M_PI/180));
00162 square.NAFTemplate.push_back(
00163 V4d::NAFState(Point3D<float>(0,30.0,0), -90*M_PI/180, V4d::RIGHT_VERTIX,
00164 Point3D<float>(10,10,1), 1*M_PI/180));
00165 square.NAFTemplate.push_back(
00166 V4d::NAFState(Point3D<float>(30.0,30.0,0), 180*M_PI/180, V4d::RIGHT_VERTIX,
00167 Point3D<float>(10,10,1), 1*M_PI/180));
00168 square.NAFTemplate.push_back(
00169 V4d::NAFState(Point3D<float>(30.0,0.0,0), 90*M_PI/180, V4d::RIGHT_VERTIX,
00170 Point3D<float>(10,10,1), 1*M_PI/180));
00171
00172 alignToCenterOfMass(square);
00173 itsGeons[SQUARE] = square;
00174
00175
00176 GeonOutline circle;
00177 circle.geonType = CIRCLE;
00178 circle.outline.push_back(Point3D<float>(0.0,0, 0.0));
00179 circle.outline.push_back(Point3D<float>(0.0, 30.0, 0.0));
00180 circle.outline.push_back(Point3D<float>(30, 30.0, 0.0));
00181 circle.outline.push_back(Point3D<float>(30,0.0, 0.0));
00182
00183 circle.NAFTemplate.push_back(
00184 V4d::NAFState(Point3D<float>(-11.511111,-9.044445,0.000000), 5.829400, V4d::ARC,
00185 Point3D<float>(10,10,1), 1*M_PI/180));
00186 circle.NAFTemplate.push_back(
00187 V4d::NAFState(Point3D<float>(-12.333334,12.333332,0.000000), 4.572762, V4d::ARC,
00188 Point3D<float>(10,10,1), 1*M_PI/180));
00189 circle.NAFTemplate.push_back(
00190 V4d::NAFState(Point3D<float>(15.622223,14.799999,0.000000), 2.757620, V4d::ARC,
00191 Point3D<float>(10,10,1), 1*M_PI/180));
00192 circle.NAFTemplate.push_back(
00193 V4d::NAFState(Point3D<float>(13.155556,-12.333336,0.000000), 1.134464, V4d::ARC,
00194 Point3D<float>(10,10,1), 1*M_PI/180));
00195
00196 alignToCenterOfMass(circle);
00197 itsGeons[CIRCLE] = circle;
00198
00199 itsGeonsParticles.resize(1000);
00200 for(uint i=0; i<itsGeonsParticles.size(); i++)
00201 {
00202 itsGeonsParticles[i].pos = Point3D<float>(0,0,0);
00203 itsGeonsParticles[i].rot = 0;
00204 itsGeonsParticles[i].geonType = CIRCLE;
00205 itsGeonsParticles[i].weight = 1.0/double(itsGeonsParticles.size());
00206 itsGeonsParticles[i].prob = 0;
00207 }
00208
00209
00210 itsBestProb = 0;
00211 itsHashedEdgesState.set_empty_key(-1);
00212 buildRTables();
00213
00214
00215
00216
00217 }
00218
00219
00220 V4::~V4()
00221 {
00222
00223 }
00224
00225
00226 void V4::alignToCenterOfMass(GeonOutline& featureTemplate)
00227 {
00228
00229
00230 float centerX = 0, centerY = 0, centerZ = 0;
00231 for(uint i=0; i<featureTemplate.outline.size(); i++)
00232 {
00233 centerX += featureTemplate.outline[i].x;
00234 centerY += featureTemplate.outline[i].y;
00235 centerZ += featureTemplate.outline[i].z;
00236 }
00237 centerX /= featureTemplate.outline.size();
00238 centerY /= featureTemplate.outline.size();
00239 centerZ /= featureTemplate.outline.size();
00240
00241 for(uint i=0; i<featureTemplate.outline.size(); i++)
00242 featureTemplate.outline[i] -= Point3D<float>(centerX, centerY, centerZ);
00243
00244 if (featureTemplate.NAFTemplate.size() > 0)
00245 {
00246 centerX = 0; centerY = 0; centerZ = 0;
00247 for(uint i=0; i<featureTemplate.NAFTemplate.size(); i++)
00248 {
00249 centerX += featureTemplate.NAFTemplate[i].pos.x;
00250 centerY += featureTemplate.NAFTemplate[i].pos.y;
00251 centerZ += featureTemplate.NAFTemplate[i].pos.z;
00252 }
00253 centerX /= featureTemplate.NAFTemplate.size();
00254 centerY /= featureTemplate.NAFTemplate.size();
00255 centerZ /= featureTemplate.NAFTemplate.size();
00256
00257 for(uint i=0; i<featureTemplate.NAFTemplate.size(); i++)
00258 {
00259 featureTemplate.NAFTemplate[i].pos -= Point3D<float>(centerX, centerY, centerZ);
00260
00261 if (featureTemplate.NAFTemplate[i].rot < 0)
00262 featureTemplate.NAFTemplate[i].rot += M_PI*2;
00263 }
00264 }
00265
00266 }
00267
00268
00269 void V4::buildRTables()
00270 {
00271
00272
00273 for(uint geonId=0; geonId<itsGeons.size(); geonId++)
00274 {
00275 if (itsGeons[geonId].outline.size() > 0)
00276 {
00277 Point3D<float> pos(0,0,itsObjectsDist);
00278 float rot = 0;
00279
00280 for(uint fid = 0; fid < itsGeons[geonId].NAFTemplate.size(); fid++)
00281 {
00282 V4d::NAFState nafState = itsGeons[geonId].NAFTemplate[fid];
00283
00284 nafState.rot += rot;
00285 float x = nafState.pos.x;
00286 float y = nafState.pos.y;
00287 float z = nafState.pos.z;
00288 nafState.pos.x = (cos(rot)*x - sin(rot)*y) + pos.x;
00289 nafState.pos.y = (sin(rot)*x + cos(rot)*y) + pos.y;
00290 nafState.pos.z = z + pos.z;
00291
00292 Point2D<int> loc = (Point2D<int>)itsCamera.project(nafState.pos);
00293
00294 RTableEntry rTableEntry;
00295 rTableEntry.featureType = nafState.featureType;
00296 rTableEntry.loc.i = loc.i - 320/2;
00297 rTableEntry.loc.j = loc.j - 240/2;
00298 rTableEntry.rot = nafState.rot;
00299
00300 itsGeons[geonId].rTable.push_back(rTableEntry);
00301 }
00302
00303 }
00304 }
00305
00306
00307 }
00308
00309
00310 void V4::showGeon(GeonOutline& geon)
00311 {
00312
00313
00314 Point3D<float> pos(0,0,itsObjectsDist);
00315 float rot = 0;
00316
00317 Image<PixRGB<byte> > geonDisp(320, 240, ZEROS);
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337 GeonState geonState;
00338 geonState.pos = pos;
00339 geonState.rot = rot;
00340 geonState.geonType = geon.geonType;
00341
00342 std::vector<Point2D<int> > outline = getImageGeonOutline(geonState);
00343 for(uint i=0; i<outline.size(); i++)
00344 drawLine(geonDisp, outline[i], outline[(i+1)%outline.size()], PixRGB<byte>(255, 0,0), 1);
00345
00346 SHOWIMG(geonDisp);
00347 }
00348
00349
00350
00351 void V4::init(Dims numCells)
00352 {
00353
00354 }
00355
00356
00357 std::vector<V4::GeonState> V4::getOutput()
00358 {
00359 return itsGeonsParticles;
00360 }
00361
00362
00363
00364 void V4::onSimEventV2Output(SimEventQueue& q,
00365 rutz::shared_ptr<SimEventV2Output>& e)
00366 {
00367 std::vector<V1::EdgeState> edgesState;
00368
00369 itsHashedEdgesState.clear();
00370 for(uint i=0; i<edgesState.size(); i++)
00371 {
00372 int key = edgesState[i].pos.i + 320*edgesState[i].pos.j;
00373 itsHashedEdgesState[key] = edgesState[i];
00374 }
00375
00376 }
00377
00378
00379 void V4::onSimEventV4dOutput(SimEventQueue& q,
00380 rutz::shared_ptr<SimEventV4dOutput>& e)
00381 {
00382 itsNAFParticles = e->getCells();
00383 evolve();
00384
00385
00386 q.post(rutz::make_shared(new SimEventV4Output(this, itsGeonsParticles)));
00387
00388
00389 std::vector<V4d::NAFState> bias = getBias();
00390 q.post(rutz::make_shared(new SimEventV4BiasOutput(this, bias)));
00391 }
00392
00393
00394 void V4::onSimEventUserInput(SimEventQueue& q, rutz::shared_ptr<SimEventUserInput>& e)
00395 {
00396
00397 LINFO("Got event %s %ix%i key=%i",
00398 e->getWinName(),
00399 e->getMouseClick().i,
00400 e->getMouseClick().j,
00401 e->getKey());
00402
00403 if (e->getMouseClick().isValid())
00404 {
00405 Point3D<float> iPoint = itsCamera.inverseProjection((Point2D<float>)e->getMouseClick(), itsObjectsDist);
00406 itsGeonsParticles[0].pos = iPoint;
00407 }
00408
00409 itsGeonsParticles[0].geonType = CIRCLE;
00410 itsGeonsParticles[0].weight = 1.0/double(itsGeonsParticles.size());
00411 itsGeonsParticles[0].prob = 0;
00412
00413 }
00414
00415
00416 void V4::onSimEventSaveOutput(SimEventQueue& q, rutz::shared_ptr<SimEventSaveOutput>& e)
00417 {
00418 if (itsShowDebug.getVal())
00419 {
00420
00421
00422 nub::ref<FrameOstream> ofs =
00423 dynamic_cast<const SimModuleSaveInfo&>(e->sinfo()).ofs;
00424 Layout<PixRGB<byte> > disp = getDebugImage();
00425 ofs->writeRgbLayout(disp, "V4", FrameInfo("V4", SRC_POS));
00426
00427
00428 }
00429 }
00430
00431
00432
00433 void V4::setInput(const std::vector<V1::EdgeState> &edgesState)
00434 {
00435
00436 itsHashedEdgesState.clear();
00437 for(uint i=0; i<edgesState.size(); i++)
00438 {
00439 int key = edgesState[i].pos.i + 320*edgesState[i].pos.j;
00440 itsHashedEdgesState[key] = edgesState[i];
00441 }
00442 }
00443
00444
00445 void V4::setInput(const std::vector<V4d::NAFState> &nafStates)
00446 {
00447 itsNAFParticles = nafStates;
00448
00449 evolve();
00450 }
00451
00452
00453
00454
00455 void V4::evolve()
00456 {
00457
00458
00459
00460 proposeParticles(itsGeonsParticles, 0.0F);
00461
00462
00463 evaluateGeonParticles(itsGeonsParticles);
00464
00465 }
00466
00467
00468 std::vector<V4d::NAFState> V4::getBias()
00469 {
00470 std::vector<V4d::NAFState> bias;
00471 double totalProb = 0;
00472 for(uint p=0; p<itsGeonsParticles.size(); p++)
00473 {
00474
00475 if (itsGeonsParticles[p].prob > 0)
00476 {
00477 Point2D<int> loc = (Point2D<int>)itsCamera.project(itsGeonsParticles[p].pos);
00478 float rot = itsGeonsParticles[p].rot + M_PI;
00479 GeonOutline geonOutline = itsGeons[itsGeonsParticles[p].geonType];
00480
00481 for(uint rIdx = 0; rIdx < geonOutline.rTable.size(); rIdx++)
00482 {
00483 float ang = rot;
00484 float a0 = loc.i - (geonOutline.rTable[rIdx].loc.i*cos(ang) - geonOutline.rTable[rIdx].loc.j*sin(ang));
00485 float b0 = loc.j - (geonOutline.rTable[rIdx].loc.i*sin(ang) + geonOutline.rTable[rIdx].loc.j*cos(ang));
00486
00487 V4d::NAFState nafState;
00488 nafState.pos = itsCamera.inverseProjection(Point2D<float>(a0,b0), itsObjectsDist);
00489 nafState.rot = rot + geonOutline.rTable[rIdx].rot + M_PI;
00490 nafState.featureType = geonOutline.rTable[rIdx].featureType;
00491 nafState.prob = itsGeonsParticles[p].prob;
00492 totalProb += nafState.prob;
00493
00494 while (nafState.rot < 0)
00495 nafState.rot += M_PI*2;
00496 while(nafState.rot > M_PI*2)
00497 nafState.rot -= M_PI*2;
00498
00499 bias.push_back(nafState);
00500 }
00501 }
00502 }
00503
00504 for(uint i=0; i<bias.size(); i++)
00505 bias[i].prob /= totalProb;
00506
00507 return bias;
00508
00509 }
00510
00511
00512 float V4::evaluateGeonParticles(std::vector<GeonState>& geonParticles)
00513 {
00514
00515 LINFO("Evaluate particles");
00516 for(uint p=0; p<geonParticles.size(); p++)
00517 getGeonLikelihood(geonParticles[p]);
00518
00519
00520
00521 double sum = 0;
00522 double Neff = 0;
00523 for(uint i=0; i<geonParticles.size(); i++)
00524 sum += geonParticles[i].prob;
00525
00526 for(uint i=0; i<geonParticles.size(); i++)
00527 {
00528 geonParticles[i].weight = geonParticles[i].prob/sum;
00529 Neff += squareOf(geonParticles[i].weight);
00530 }
00531
00532 Neff = 1/Neff;
00533
00534 return Neff;
00535
00536 }
00537
00538
00539 void V4::GHT(std::vector<V4::GHTAcc>& accRet, GeonOutline &geonOutline)
00540 {
00541 ImageSet<float> acc(360, Dims(320,240), ZEROS);
00542
00543 CpuTimer timer;
00544 timer.reset();
00545
00546
00547 std::vector<rutz::shared_ptr<GHTJob> > jobs;
00548
00549 for(int angIdx = 0; angIdx < 360; angIdx++)
00550 {
00551 jobs.push_back(rutz::make_shared(new GHTJob(this, acc[angIdx], angIdx, geonOutline.rTable)));
00552 itsThreadServer->enqueueJob(jobs.back());
00553
00554 }
00555
00556 while(itsThreadServer->size() > 0)
00557 usleep(10000);
00558
00559 timer.mark();
00560 LINFO("Total time %0.2f sec", timer.real_secs());
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575 for(uint rot=0; rot<acc.size(); rot++)
00576 for(int y=0; y<acc[rot].getHeight(); y++)
00577 for(int x=0; x<acc[rot].getWidth(); x++)
00578 if (acc[rot].getVal(x,y) > 0)
00579 {
00580 GHTAcc ghtAcc;
00581 ghtAcc.geonType = geonOutline.geonType;
00582 ghtAcc.pos = Point2D<int>(x,y);
00583 ghtAcc.ang = rot;
00584 ghtAcc.scale = -1;
00585 ghtAcc.sum = acc[rot].getVal(x,y);
00586 accRet.push_back(ghtAcc);
00587 }
00588
00589 }
00590
00591 void V4::voteForFeature(Image<float>& acc, int angIdx, std::vector<RTableEntry>& rTable)
00592 {
00593
00594
00595 for(uint p=0; p < itsNAFParticles.size(); p++)
00596 {
00597 V4d::NAFState nafState = itsNAFParticles[p];
00598 if (nafState.prob > 0)
00599 {
00600 Point2D<int> loc = (Point2D<int>)itsCamera.project(nafState.pos);
00601
00602
00603
00604
00605
00606 for(uint rIdx = 0; rIdx < rTable.size(); rIdx++)
00607 {
00608 if (rTable[rIdx].featureType == nafState.featureType)
00609 {
00610
00611 float ang = angIdx * M_PI/180;
00612
00613 float featureAng = rTable[rIdx].rot + ang;
00614 if (featureAng < 0)
00615 featureAng += M_PI*2;
00616 if (featureAng > M_PI*2)
00617 featureAng -= M_PI*2;
00618
00619 float diffRot = acos(cos(nafState.rot - featureAng));
00620
00621
00622
00623
00624
00625
00626 float stddevRot = 1.5;
00627 int sizeRot = int(ceil(stddevRot * sqrt(-2.0F * log(exp(-5.0F)))));
00628
00629 if (fabs(diffRot) < sizeRot*M_PI/180)
00630 {
00631 float rRot = exp(-((diffRot*diffRot)/(stddevRot*stddevRot)));
00632
00633
00634
00635 float stddevX = 1.5;
00636 float stddevY = 1.5;
00637 int sizeX = int(ceil(stddevX * sqrt(-2.0F * log(exp(-5.0F)))));
00638 int sizeY = int(ceil(stddevY * sqrt(-2.0F * log(exp(-5.0F)))));
00639
00640 for(int y=loc.j-sizeY; y<loc.j+sizeY; y++)
00641 {
00642 float diffY = y-loc.j;
00643 float ry = exp(-((diffY*diffY)/(stddevY*stddevY)));
00644 for(int x=loc.i-sizeX; x<loc.i+sizeX; x++)
00645 {
00646 float diffX = x-loc.i;
00647 float rx = exp(-((diffX*diffX)/(stddevX*stddevX)));
00648
00649 float weight = rRot*rx*ry;
00650
00651 int a0 = x - int(rTable[rIdx].loc.i*cos(ang) - rTable[rIdx].loc.j*sin(ang));
00652 int b0 = y - int(rTable[rIdx].loc.i*sin(ang) + rTable[rIdx].loc.j*cos(ang));
00653 if (acc.coordsOk(a0, b0))
00654 {
00655 float val = acc.getVal(a0, b0);
00656 val += weight;
00657 acc.setVal(a0, b0, val);
00658 }
00659 }
00660 }
00661 }
00662 }
00663 }
00664 }
00665 }
00666 }
00667
00668 Image<PixRGB<byte> > V4::showParticles(const std::vector<GeonState>& particles)
00669 {
00670 Image<float> probImg(320,240, ZEROS);
00671 Image<PixRGB<byte> > particlesImg(probImg.getDims(),ZEROS);
00672 for(uint i=0; i<particles.size(); i++)
00673 {
00674 Point2D<int> loc = (Point2D<int>)itsCamera.project(particles[i].pos);
00675 if (particlesImg.coordsOk(loc) &&
00676 particles[i].weight > probImg.getVal(loc) )
00677 {
00678 PixRGB<byte> col;
00679 if (particles[i].geonType == SQUARE)
00680 col = PixRGB<byte>(0, 255, 0);
00681 else
00682 col = PixRGB<byte>(255, 0, 0);
00683 probImg.setVal(loc, particles[i].weight);
00684
00685 particlesImg.setVal(loc, col);
00686 }
00687 }
00688 inplaceNormalize(probImg, 0.0F, 255.0F);
00689
00690 particlesImg *= probImg;
00691
00692 return particlesImg;
00693 }
00694
00695 void V4::proposeParticles(std::vector<GeonState>& particles, const double Neff)
00696 {
00697
00698 LINFO("Propose Particles");
00699
00700
00701
00702
00703
00704
00705
00706 float probThresh = 1.0e-10;
00707
00708
00709 uint particlesAboveProb = 0;
00710 for(uint i=0; i<particles.size(); i++)
00711 {
00712 if (particles[i].prob > probThresh)
00713 {
00714 particles[i].pos.x += randomDoubleFromNormal(1.0);
00715 particles[i].pos.y += randomDoubleFromNormal(1.0);
00716 particles[i].pos.z = itsObjectsDist + randomDoubleFromNormal(0.05);
00717 particles[i].rot += randomDoubleFromNormal(1)*M_PI/180;
00718 particles[i].weight = 1.0/(float)particles.size();
00719 particlesAboveProb++;
00720 }
00721 }
00722
00723
00724
00725
00726 if (particlesAboveProb < particles.size())
00727 {
00728 LINFO("GHT ");
00729 std::vector<GHTAcc> acc;
00730 GHT(acc, itsGeons[TRIANGLE]);
00731 GHT(acc, itsGeons[SQUARE]);
00732 GHT(acc, itsGeons[CIRCLE]);
00733 LINFO("GHT Done ");
00734
00735 if (acc.size() == 0)
00736 return;
00737
00738 normalizeAcc(acc);
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748 std::priority_queue <GHTAcc> pAcc;
00749 for(uint i=0; i<acc.size(); i++)
00750 pAcc.push(acc[i]);
00751
00752
00753 for(uint i=0; i<particles.size(); i++)
00754 {
00755 if (particles[i].prob <= probThresh)
00756 {
00757
00758 if (pAcc.empty())
00759 break;
00760 GHTAcc p = pAcc.top(); pAcc.pop();
00761
00762 Point3D<float> iPoint = itsCamera.inverseProjection(Point2D<float>(p.pos), itsObjectsDist);
00763 particles[i].pos.x = iPoint.x + randomDoubleFromNormal(1);
00764 particles[i].pos.y = iPoint.y + randomDoubleFromNormal(1);
00765 particles[i].pos.z = itsObjectsDist + randomDoubleFromNormal(0.05);
00766 particles[i].rot = (p.ang + randomDoubleFromNormal(1))*M_PI/180;
00767 particles[i].geonType = p.geonType;
00768 particles[i].weight = 1.0/(float)particles.size();
00769 particles[i].prob = 1.0e-50;
00770 }
00771 }
00772 }
00773 }
00774
00775 void V4::normalizeAcc(std::vector<GHTAcc>& acc)
00776 {
00777
00778 double sum = 0;
00779 for(uint i=0; i<acc.size(); i++)
00780 sum += acc[i].sum;
00781
00782 for(uint i=0; i<acc.size(); i++)
00783 acc[i].sum /= sum;
00784 }
00785
00786 void V4::resampleParticles2(std::vector<GeonState>& particles)
00787 {
00788 std::vector<GeonState> newParticles;
00789
00790 while(newParticles.size() < particles.size())
00791 {
00792
00793 int maxP = 0; double maxVal = particles[maxP].weight;
00794 for(uint j=1; j<particles.size(); j++)
00795 {
00796 if (particles[j].weight > maxVal)
00797 {
00798 maxP = j;
00799 maxVal = particles[j].weight;
00800 }
00801 }
00802
00803 if (maxVal > 0)
00804 {
00805 for(int np=0; np<10; np++)
00806 {
00807
00808 GeonState p = particles[maxP];
00809 p.weight = 1.0/double(particles.size());
00810 newParticles.push_back(p);
00811 }
00812
00813
00814 float sigmaX = 0.1, sigmaY = 0.1;
00815 float fac = 0.5f / (M_PI * sigmaX * sigmaY);
00816 float vx = -0.5f / (sigmaX * sigmaX);
00817 float vy = -0.5f / (sigmaY * sigmaY);
00818
00819 for(uint j=0; j<particles.size(); j++)
00820 {
00821 float x = particles[j].pos.x;
00822 float y = particles[j].pos.y;
00823
00824 float vydy2 = y - particles[maxP].pos.y; vydy2 *= vydy2 * vy;
00825 float dx2 = x - particles[maxP].pos.x; dx2 *= dx2;
00826 particles[j].weight -= particles[j].weight * fac*expf(vx * dx2 + vydy2);
00827 if (particles[j].weight < 0)
00828 particles[j].weight = 0;
00829
00830 }
00831 particles[maxP].weight = 0;
00832 } else {
00833 GeonState p = particles[0];
00834 p.weight = 1.0/double(particles.size());
00835 newParticles.push_back(p);
00836 }
00837
00838 }
00839
00840 particles = newParticles;
00841
00842 }
00843
00844 void V4::resampleParticles(std::vector<GeonState>& geonParticles)
00845 {
00846 LINFO("Resample");
00847
00848 std::vector<GeonState> newParticles;
00849
00850
00851 std::vector<double> CDF;
00852 CDF.resize(geonParticles.size());
00853
00854 CDF.at(0) = geonParticles.at(0).weight;
00855 for(uint i=1; i<CDF.size(); i++)
00856 CDF.at(i) = CDF.at(i-1) + geonParticles.at(i).weight;
00857
00858 uint i = 0;
00859 double u = randomDouble()* 1.0/double(geonParticles.size());
00860
00861 for(uint j=0; j < geonParticles.size(); j++)
00862 {
00863 while(u > CDF.at(i))
00864 i++;
00865
00866 GeonState p = geonParticles.at(i);
00867 p.weight = 1.0/double(geonParticles.size());
00868 newParticles.push_back(p);
00869
00870 u += 1.0/double(geonParticles.size());
00871 }
00872
00873 geonParticles = newParticles;
00874
00875 }
00876
00877 std::vector<Point2D<int> > V4::getImageGeonOutline(GeonState& geon)
00878 {
00879
00880 GeonOutline cameraOutline = itsGeons[geon.geonType];
00881
00882
00883 for(uint i=0; i<itsGeons[geon.geonType].outline.size(); i++)
00884 {
00885 float x = itsGeons[geon.geonType].outline[i].x;
00886 float y = itsGeons[geon.geonType].outline[i].y;
00887 float z = itsGeons[geon.geonType].outline[i].z;
00888 cameraOutline.outline[i].x = (cos(geon.rot)*x - sin(geon.rot)*y) + geon.pos.x;
00889 cameraOutline.outline[i].y = (sin(geon.rot)*x + cos(geon.rot)*y) + geon.pos.y;
00890 cameraOutline.outline[i].z = z + geon.pos.z;
00891 }
00892
00893
00894 std::vector<Point2D<int> > outline;
00895 for(uint i=0; i<cameraOutline.outline.size(); i++)
00896 {
00897 Point2D<float> loc = itsCamera.project(cameraOutline.outline[i]);
00898 outline.push_back(Point2D<int>(loc));
00899 }
00900
00901 return outline;
00902
00903 }
00904
00905
00906 void V4::getOutlineLikelihood(GeonState& geon)
00907 {
00908
00909
00910 std::vector<Point2D<int> > geonOutline = getImageGeonOutline(geon);
00911
00912 double totalProb = 1;
00913 for(uint i=0; i<geonOutline.size(); i++)
00914 {
00915 Point2D<int> pLoc1 = geonOutline[i];
00916 Point2D<int> pLoc2 = geonOutline[(i+1)%geonOutline.size()];
00917 double prob = getLineProbability(pLoc1, pLoc2);
00918 totalProb *= prob;
00919 }
00920 geon.prob = totalProb;
00921 }
00922
00923
00924 void V4::getGeonLikelihood(GeonState& geon)
00925 {
00926 double totalProb = 1;
00927 Point2D<int> loc = (Point2D<int>)itsCamera.project(geon.pos);
00928 float rot = geon.rot + M_PI;
00929 GeonOutline geonOutline = itsGeons[geon.geonType];
00930
00931
00932
00933 for(uint rIdx = 0; rIdx < geonOutline.rTable.size(); rIdx++)
00934 {
00935 float ang = rot;
00936 float a0 = loc.i - (geonOutline.rTable[rIdx].loc.i*cos(ang) - geonOutline.rTable[rIdx].loc.j*sin(ang));
00937 float b0 = loc.j - (geonOutline.rTable[rIdx].loc.i*sin(ang) + geonOutline.rTable[rIdx].loc.j*cos(ang));
00938
00939 V4d::NAFState nafState;
00940 nafState.pos = itsCamera.inverseProjection(Point2D<float>(a0,b0), itsObjectsDist);
00941 nafState.rot = rot + geonOutline.rTable[rIdx].rot + M_PI;
00942 nafState.featureType = geonOutline.rTable[rIdx].featureType;
00943 nafState.prob = -1;
00944
00945 while (nafState.rot < 0)
00946 nafState.rot += M_PI*2;
00947 while(nafState.rot > M_PI*2)
00948 nafState.rot -= M_PI*2;
00949
00950
00951 int nearPart = 0;
00952 float partDist = 1.0e100;
00953 for(uint i=0; i<itsNAFParticles.size(); i++)
00954 {
00955 if (itsNAFParticles[i].prob > 0)
00956 {
00957 float distance = nafState.distance(itsNAFParticles[i]);
00958 if (distance < partDist)
00959 {
00960 partDist = distance;
00961 nearPart = i;
00962 }
00963 }
00964 }
00965
00966 float sig = 0.75F;
00967
00968
00969 float prob = (1.0F/(sig*sqrt(2*M_PI))*exp(-0.5*squareOf(partDist)/squareOf(sig)));
00970 totalProb *= prob;
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987 }
00988
00989
00990
00991
00992
00993 geon.prob = totalProb;
00994
00995
00996 }
00997
00998
00999 double V4::getLineProbability(const Point2D<int>& p1, const Point2D<int>& p2)
01000 {
01001
01002 int dx = p2.i - p1.i, ax = abs(dx) << 1, sx = signOf(dx);
01003 int dy = p2.j - p1.j, ay = abs(dy) << 1, sy = signOf(dy);
01004 int x = p1.i, y = p1.j;
01005
01006 const int w = 320;
01007
01008 double prob = 1;
01009
01010 int wSize = 1;
01011 if (ax > ay)
01012 {
01013 int d = ay - (ax >> 1);
01014 for (;;)
01015 {
01016
01017 float maxProb = 1.0e-20;
01018 for(int yy = y-wSize; yy < y+wSize; yy++)
01019 for(int xx = x-wSize; xx < x+wSize; xx++)
01020 {
01021 int key = xx + w * yy;
01022 if (key > 0)
01023 {
01024 dense_hash_map<int, V1::EdgeState>::const_iterator iter = itsHashedEdgesState.find(key);
01025 if (iter != itsHashedEdgesState.end())
01026 {
01027 if (iter->second.prob > maxProb)
01028 maxProb = iter->second.prob;
01029 }
01030 }
01031 }
01032
01033 prob *= maxProb;
01034
01035 if (x == p2.i) return prob;
01036 if (d >= 0) { y += sy; d -= ax; }
01037 x += sx; d += ay;
01038 }
01039 } else {
01040 int d = ax - (ay >> 1);
01041 for (;;)
01042 {
01043 float maxProb = 1.0e-20;
01044 for(int yy = y-wSize; yy < y+wSize; yy++)
01045 for(int xx = x-wSize; xx < x+wSize; xx++)
01046 {
01047 int key = xx + w * yy;
01048 if (key > 0)
01049 {
01050 dense_hash_map<int, V1::EdgeState>::const_iterator iter = itsHashedEdgesState.find(key);
01051 if (iter != itsHashedEdgesState.end())
01052 {
01053 if (iter->second.prob > maxProb)
01054 maxProb = iter->second.prob;
01055 }
01056 }
01057 }
01058 prob *= maxProb;
01059
01060 if (y == p2.j) return prob;
01061
01062 if (d >= 0) { x += sx; d -= ay; }
01063 y += sy; d += ax;
01064 }
01065 }
01066
01067 return prob;
01068
01069
01070 }
01071
01072 Layout<PixRGB<byte> > V4::getDebugImage()
01073 {
01074 Layout<PixRGB<byte> > outDisp;
01075
01076
01077 Image<float> perc(320,240, ZEROS);
01078
01079
01080 dense_hash_map<int, V1::EdgeState>::const_iterator iter;
01081 for(iter = itsHashedEdgesState.begin(); iter != itsHashedEdgesState.end(); iter++)
01082 perc.setVal(iter->second.pos, iter->second.prob);
01083
01084 inplaceNormalize(perc, 0.0F, 255.0F);
01085
01086 Image<PixRGB<byte> > geonDisp = toRGB(Image<byte>(perc));
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104 for(uint p=0; p<itsGeonsParticles.size(); p++)
01105 {
01106
01107
01108
01109 if (itsGeonsParticles[p].prob > 0)
01110 {
01111 float normProb = 255.0;
01112 PixRGB<byte> col;
01113 if (itsGeonsParticles[p].geonType == TRIANGLE)
01114 col = PixRGB<byte>(0,int(normProb),0);
01115 else if (itsGeonsParticles[p].geonType == SQUARE)
01116 col = PixRGB<byte>(int(normProb),0,0);
01117 else
01118 col = PixRGB<byte>(0,0,int(normProb));
01119
01120 if (itsGeonsParticles[p].geonType == CIRCLE)
01121 {
01122 Point2D<float> loc = itsCamera.project(itsGeonsParticles[p].pos);
01123 drawCircle(geonDisp, Point2D<int>(loc), 20, col);
01124 } else {
01125 std::vector<Point2D<int> > outline = getImageGeonOutline(itsGeonsParticles[p]);
01126 for(uint i=0; i<outline.size(); i++)
01127 drawLine(geonDisp, outline[i], outline[(i+1)%outline.size()], col, 1);
01128 }
01129 }
01130 }
01131
01132
01133
01134 Image<PixRGB<byte> > particlesImg = showParticles(itsGeonsParticles);
01135
01136 char msg[255];
01137 sprintf(msg, "V4");
01138 writeText(geonDisp, Point2D<int>(0,0), msg, PixRGB<byte>(255,255,255), PixRGB<byte>(0,0,0));
01139
01140 outDisp = hcat(geonDisp, particlesImg);
01141
01142 return outDisp;
01143
01144 }
01145
01146
01147
01148
01149
01150
01151
01152 #endif
01153