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 V4d_C_DEFINED
00039 #define V4d_C_DEFINED
00040
00041 #include "plugins/SceneUnderstanding/V4d.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 "SIFT/FeatureVector.H"
00051 #include "Simulation/SimEventQueue.H"
00052 #include "Neuro/EnvVisualCortex.H"
00053 #include "GUI/DebugWin.H"
00054 #include "Util/CpuTimer.H"
00055 #include "Util/JobServer.H"
00056 #include "Util/JobWithSemaphore.H"
00057 #include <math.h>
00058 #include <fcntl.h>
00059 #include <limits>
00060 #include <string>
00061
00062 const ModelOptionCateg MOC_V4d = {
00063 MOC_SORTPRI_3, "V4d-Related Options" };
00064
00065
00066 const ModelOptionDef OPT_V4dShowDebug =
00067 { MODOPT_ARG(bool), "V4dShowDebug", &MOC_V4d, OPTEXP_CORE,
00068 "Show debug img",
00069 "v4d-debug", '\0', "<true|false>", "false" };
00070
00071 namespace
00072 {
00073 class GHTJob : public JobWithSemaphore
00074 {
00075 public:
00076 GHTJob(V4d* v4d, Image<float>& acc, int angIdx, std::vector<V1::EdgeState>& rTable) :
00077 itsV4d(v4d),
00078 itsAcc(acc),
00079 itsAngIdx(angIdx),
00080 itsRTable(rTable)
00081 {}
00082
00083 virtual ~GHTJob() {}
00084
00085 virtual void run()
00086 {
00087 itsV4d->voteForFeature(itsAcc, itsAngIdx, itsRTable);
00088
00089 this->markFinished();
00090 }
00091
00092 virtual const char* jobType() const { return "GHTJob"; }
00093 V4d* itsV4d;
00094 Image<float>& itsAcc;
00095 int itsAngIdx;
00096 std::vector<V1::EdgeState>& itsRTable;
00097 };
00098
00099 class LikelihoodJob : public JobWithSemaphore
00100 {
00101 public:
00102 LikelihoodJob(V4d* v4d, V4d::NAFState& nafState) :
00103 itsV4d(v4d),
00104 itsNAFState(nafState)
00105 {}
00106
00107 virtual ~LikelihoodJob() {}
00108
00109 virtual void run()
00110 {
00111 itsV4d->getParticleLikelihood(itsNAFState);
00112 this->markFinished();
00113 }
00114
00115 virtual const char* jobType() const { return "LikelihoodJob"; }
00116
00117 V4d* itsV4d;
00118 V4d::NAFState& itsNAFState;
00119
00120
00121 };
00122 }
00123
00124
00125
00126 V4d::V4d(OptionManager& mgr, const std::string& descrName,
00127 const std::string& tagName) :
00128 SimModule(mgr, descrName, tagName),
00129 SIMCALLBACK_INIT(SimEventV2Output),
00130 SIMCALLBACK_INIT(SimEventSaveOutput),
00131 SIMCALLBACK_INIT(SimEventUserInput),
00132 SIMCALLBACK_INIT(SimEventV4BiasOutput),
00133 itsShowDebug(&OPT_V4dShowDebug, this),
00134 itsMaxVal(0),
00135 itsGHTAngStep(1),
00136 itsObjectsDist(370.00)
00137 {
00138
00139 itsThreadServer.reset(new WorkThreadServer("V4d", 100));
00140
00141
00142 itsCamera = Camera(Point3D<float>(0,0,0.0),
00143 Point3D<float>(0, 0,0),
00144 450,
00145 320,
00146 240);
00147
00148
00149 itsNAFeatures.resize(3);
00150
00151
00152 FeatureTemplate rightVertixFeature;
00153 rightVertixFeature.featureType = RIGHT_VERTIX;
00154 rightVertixFeature.outline.push_back(Point3D<float>(11.0,0.0, 0.0));
00155 rightVertixFeature.outline.push_back(Point3D<float>(0.0,0, 0.0));
00156 rightVertixFeature.outline.push_back(Point3D<float>(0.0,11.0, 0.0));
00157
00158 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(0,4), 0));
00159 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(0,5), 0));
00160 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(0,6), 0));
00161 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(0,7), 0));
00162 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(0,8), 0));
00163 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(0,9), 0));
00164 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(0,10), 0));
00165 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(0,11), 0));
00166 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(0,12), 0));
00167 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(4,0), M_PI/2));
00168 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(5,0), M_PI/2));
00169 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(6,0), M_PI/2));
00170 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(7,0), M_PI/2));
00171 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(8,0), M_PI/2));
00172 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(9,0), M_PI/2));
00173 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(10,0), M_PI/2));
00174 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(11,0), M_PI/2));
00175 rightVertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(12,0), M_PI/2));
00176
00177 alignToCenterOfMass(rightVertixFeature);
00178 itsNAFeatures[RIGHT_VERTIX] = rightVertixFeature;
00179
00180 FeatureTemplate vertixFeature;
00181 vertixFeature.featureType = VERTIX;
00182 vertixFeature.outline.push_back(Point3D<float>(0.0,0, 0.0));
00183 vertixFeature.outline.push_back(Point3D<float>(0.0,11.0, 0.0));
00184 vertixFeature.outline.push_back(Point3D<float>(11.0,0.0, 0.0));
00185
00186 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(5,0), M_PI/2));
00187 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(6,0), M_PI/2));
00188 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(7,0), M_PI/2));
00189 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(8,0), M_PI/2));
00190 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(9,0), M_PI/2));
00191 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(10,0), M_PI/2));
00192 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(11,0), M_PI/2));
00193 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(12,0), M_PI/2));
00194 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(13,0), M_PI/2));
00195
00196 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(5,-5), -M_PI/4));
00197 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(6,-6), -M_PI/4));
00198 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(7,-7), -M_PI/4));
00199 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(8,-8), -M_PI/4));
00200 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(9,-9), -M_PI/4));
00201 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(10,-10), -M_PI/4));
00202 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(11,-11), -M_PI/4));
00203 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(12,-12), -M_PI/4));
00204 vertixFeature.edges.push_back(V1::EdgeState(Point2D<int>(13,-13), -M_PI/4));
00205
00206 alignToCenterOfMass(vertixFeature);
00207 itsNAFeatures[VERTIX] = vertixFeature;
00208
00209 FeatureTemplate arcFeature;
00210 arcFeature.featureType = ARC;
00211 arcFeature.outline.push_back(Point3D<float>(0.0,0, 0.0));
00212 arcFeature.outline.push_back(Point3D<float>(5.0,0.0, 0.0));
00213
00214 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(5,0), 1.885212));
00215 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(3,1), 2.082733));
00216 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(4,1), 1.941421));
00217 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(5,1), 1.841154));
00218
00219 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(1,2), 2.076972));
00220 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(2,2), 1.954276));
00221 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(3,2), 1.959018));
00222 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(4,2), 1.903953));
00223 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(5,2), 1.816486));
00224
00225 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(0,3), 2.045129));
00226 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(1,3), 2.006197));
00227 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(2,3), 1.965587));
00228 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(3,3), 1.968628));
00229 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(4,3), 1.873842));
00230 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(5,3), 1.809913));
00231
00232 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(0,4), 1.992570));
00233 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(1,4), 1.990212));
00234 arcFeature.edges.push_back(V1::EdgeState(Point2D<int>(2,4), 2.023316));
00235
00236
00237 alignToCenterOfMass(arcFeature);
00238 itsNAFeatures[ARC] = arcFeature;
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251 buildRTables();
00252 itsFeaturesParticles.resize(1000);
00253 for(uint i=0; i<itsFeaturesParticles.size(); i++)
00254 {
00255 itsFeaturesParticles[i].pos = Point3D<float>(-53.444447,0.000000,370.000000);
00256 itsFeaturesParticles[i].rot = 35*M_PI/180;
00257
00258 itsFeaturesParticles[i].featureType = VERTIX;
00259 itsFeaturesParticles[i].weight = 1.0/double(itsFeaturesParticles.size());
00260 itsFeaturesParticles[i].prob = 0;
00261 }
00262
00263 itsHashedEdgesState.set_empty_key(-1);
00264
00265 itsDebugImg = Image<PixRGB<byte> >(320,240,ZEROS);
00266 }
00267
00268
00269 V4d::~V4d()
00270 {
00271
00272 }
00273
00274
00275
00276 void V4d::alignToCenterOfMass(FeatureTemplate& featureTemplate)
00277 {
00278
00279
00280 float centerX = 0, centerY = 0, centerZ = 0;
00281 for(uint i=0; i<featureTemplate.outline.size(); i++)
00282 {
00283 centerX += featureTemplate.outline[i].x;
00284 centerY += featureTemplate.outline[i].y;
00285 centerZ += featureTemplate.outline[i].z;
00286 }
00287 centerX /= featureTemplate.outline.size();
00288 centerY /= featureTemplate.outline.size();
00289 centerZ /= featureTemplate.outline.size();
00290
00291 for(uint i=0; i<featureTemplate.outline.size(); i++)
00292 featureTemplate.outline[i] -= Point3D<float>(centerX, centerY, centerZ);
00293
00294 }
00295
00296
00297
00298 void V4d::buildRTables()
00299 {
00300 for(uint fid=0; fid<itsNAFeatures.size(); fid++)
00301 {
00302 if (itsNAFeatures[fid].outline.size() > 0)
00303 {
00304 NAFState naFeature;
00305 naFeature.pos = Point3D<float>(0, 0, itsObjectsDist);
00306 naFeature.rot = 0;
00307 naFeature.featureType = (NAF_TYPE)fid;
00308 naFeature.prob = 0;
00309
00310 std::vector<Point2D<int> > outline = getImageOutline(naFeature);
00311 Image<float> tmp(320,240, ZEROS);
00312 for(uint i=0; i<outline.size()-1; i++)
00313 drawLine(tmp, outline[i], outline[i+1], 1.0F, 1);
00314
00315
00316 for(int x=0; x<tmp.getWidth(); x+=1)
00317 for(int y=0; y<tmp.getHeight(); y+=1)
00318 {
00319 if (tmp.getVal(x,y) == 1.0)
00320 {
00321 int rx = x-tmp.getWidth()/2;
00322 int ry = y-tmp.getHeight()/2;
00323
00324 RTableEntry rTableEntry;
00325 rTableEntry.loc = Point2D<int>(rx, ry);
00326 rTableEntry.rot = atan2(ry, rx);
00327 itsNAFeatures[fid].rTable.push_back(rTableEntry);
00328 }
00329 }
00330 }
00331 }
00332 }
00333
00334
00335 void V4d::onSimEventV4BiasOutput(SimEventQueue& q,
00336 rutz::shared_ptr<SimEventV4BiasOutput>& e)
00337 {
00338 itsBias = e->getCells();
00339
00340 }
00341
00342
00343 void V4d::onSimEventV2Output(SimEventQueue& q,
00344 rutz::shared_ptr<SimEventV2Output>& e)
00345 {
00346 std::vector<V1::EdgeState> edgesState;
00347 std::vector<V2::CornerState> cornersState = e->getCorners();
00348 itsEdgesState = edgesState;
00349
00350 LINFO("Build priority queue for corners");
00351
00352 ASSERT(cornersState.size());
00353 for(uint i=0; i<cornersState.size(); i++)
00354 itsCornersState.push(cornersState[i]);
00355
00356
00357
00358
00359 Image<float> tmp(320,240,ZEROS);
00360 itsHashedEdgesState.clear();
00361 for(uint i=0; i<edgesState.size(); i++)
00362 {
00363 int key = edgesState[i].pos.i + 320*edgesState[i].pos.j;
00364 tmp.setVal(edgesState[i].pos, edgesState[i].prob);
00365 itsHashedEdgesState[key] = edgesState[i];
00366 }
00367
00368
00369
00370 evolve();
00371
00372
00373
00374 }
00375
00376
00377 void V4d::onSimEventSaveOutput(SimEventQueue& q, rutz::shared_ptr<SimEventSaveOutput>& e)
00378 {
00379 if (itsShowDebug.getVal())
00380 {
00381
00382
00383 nub::ref<FrameOstream> ofs =
00384 dynamic_cast<const SimModuleSaveInfo&>(e->sinfo()).ofs;
00385 Layout<PixRGB<byte> > disp = getDebugImage();
00386 ofs->writeRgbLayout(disp, "V4d", FrameInfo("V4d", SRC_POS));
00387
00388
00389 }
00390 }
00391
00392
00393 void V4d::onSimEventUserInput(SimEventQueue& q, rutz::shared_ptr<SimEventUserInput>& e)
00394 {
00395
00396 LINFO("Got event %s %ix%i key=%i",
00397 e->getWinName(),
00398 e->getMouseClick().i,
00399 e->getMouseClick().j,
00400 e->getKey());
00401
00402 Image<float> mag(320,240,ZEROS);
00403 Image<float> ori(320,240,ZEROS);
00404
00405 Point2D<int> loc = e->getMouseClick();
00406
00407 if (loc.i > 320)
00408 loc.i -= 320;
00409
00410 for(uint i=0; i<itsEdgesState.size(); i++)
00411 {
00412 mag.setVal(itsEdgesState[i].pos, itsEdgesState[i].prob);
00413 ori.setVal(itsEdgesState[i].pos, itsEdgesState[i].ori);
00414 }
00415
00416
00417
00418
00419
00420
00421
00422 Image<float> magC = crop(mag, loc - 10, Dims(20,20));
00423 Image<float> oriC = crop(ori, loc - 10, Dims(20,20));
00424
00425
00426 for(int y=0; y<oriC.getHeight(); y++)
00427 for(int x=0; x<oriC.getWidth(); x++)
00428 {
00429 if (magC.getVal(x,y) > 0.1)
00430 printf("%i ", (int)(oriC.getVal(x,y)*180/M_PI + 90));
00431 }
00432 printf("\n");
00433
00434 double sumSin = 0, sumCos = 0;
00435 float numElem = 0;
00436 for(uint i=0; i<oriC.size(); i++)
00437 {
00438 if (magC[i] > 0.1)
00439 {
00440 printf("%0.1f ", oriC[i]*180/M_PI+90);
00441 sumSin += sin(oriC[i]+ M_PI/2);
00442 sumCos += cos(oriC[i] + M_PI/2);
00443 numElem++;
00444 }
00445 }
00446 double sum = sqrt( squareOf(sumSin/numElem) + squareOf(sumCos/numElem));
00447 printf("\n");
00448 LINFO("sin %f cos %f Var %f", sumSin, sumCos, sum);
00449
00450
00451 SHOWIMG(magC);
00452 SHOWIMG(oriC);
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485 }
00486
00487
00488 void V4d::evolveSift()
00489 {
00490 Image<float> tmp(320,240,ZEROS);
00491
00492 dense_hash_map<int, V1::EdgeState>::const_iterator iter;
00493 for(iter = itsHashedEdgesState.begin(); iter != itsHashedEdgesState.end(); iter++)
00494 {
00495 V1::EdgeState edgeState = iter->second;
00496
00497 if (edgeState.prob > 0)
00498 {
00499 tmp.setVal(edgeState.pos, edgeState.prob);
00500
00501
00502
00503
00504
00505
00506 }
00507 }
00508 LINFO("Done");
00509 SHOWIMG(tmp);
00510
00511 IplImage* img = img2ipl(tmp);
00512 IplImage* hImg = cvCreateImage( cvSize(img->width, img->height), IPL_DEPTH_32F, 1 );
00513
00514 cvCornerHarris(img, hImg, 5, 5, 0);
00515 SHOWIMG(ipl2float(hImg));
00516
00517
00518 SHOWIMG(ipl2float(hImg));
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529 }
00530
00531 float V4d::createDescriptor(Point2D<int>& loc, Histogram& OV, float mainOri)
00532 {
00533
00534 Image<float> perc(320,240, ZEROS);
00535 Image<float> ori(320,240, ZEROS);
00536 dense_hash_map<int, V1::EdgeState>::const_iterator iter;
00537 for(iter = itsHashedEdgesState.begin(); iter != itsHashedEdgesState.end(); iter++)
00538 {
00539 V1::EdgeState edgeState = iter->second;
00540 perc.setVal(edgeState.pos, edgeState.prob);
00541 ori.setVal(edgeState.pos, edgeState.ori + M_PI/2);
00542 }
00543
00544
00545 float s = 1.5;
00546
00547
00548 const float sigma = 2;
00549
00550 const int xi = int(loc.i + 0.5f);
00551 const int yi = int(loc.j + 0.5f);
00552
00553
00554 const float sinAngle = sin(mainOri), cosAngle = cos(mainOri);
00555
00556
00557 const int radius = int(5.0F * sigma + 0.5F);
00558 const float gausssig = float(radius);
00559 const float gaussfac = - 0.5F / (gausssig * gausssig);
00560
00561
00562
00563
00564
00565
00566
00567 int scale = abs(int(s));
00568 scale = scale > 5 ? 5 : scale;
00569
00570 FeatureVector fv;
00571
00572 Image<float> tmp(radius*2+1, radius*2+1, ZEROS);
00573 for (int ry = -radius; ry <= radius; ry++)
00574 for (int rx = -radius; rx <= radius; rx++)
00575 {
00576
00577 const float newX = rx * cosAngle - ry * sinAngle;
00578 const float newY = rx * sinAngle + ry * cosAngle;
00579
00580
00581 const float orgX = newX + float(xi);
00582 const float orgY = newY + float(yi);
00583
00584
00585 if (perc.coordsOk(orgX, orgY) == false) continue;
00586
00587
00588 tmp.setVal(rx+radius, ry+radius, perc.getValInterp(orgX, orgY));
00589
00590
00591
00592 const float xf = 2.0F + 2.0F * float(rx) / float(radius);
00593 const float yf = 2.0F + 2.0F * float(ry) / float(radius);
00594
00595
00596
00597
00598 const float gaussFactor = expf((newX*newX+newY*newY) * gaussfac);
00599 const float weightedMagnitude =
00600 gaussFactor * perc.getValInterp(orgX, orgY);
00601
00602
00603
00604 float gradAng = ori.getValInterp(orgX, orgY) - mainOri;
00605
00606 gradAng=fmod(gradAng, 2*M_PI);
00607
00608
00609 if (gradAng < 0.0) gradAng+=2*M_PI;
00610 if (gradAng >= M_PI) gradAng-=2*M_PI;
00611
00612 const float orient = (gradAng + M_PI) * 8 / (2 * M_PI);
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622 fv.addValue(xf, yf, orient, weightedMagnitude);
00623
00624
00625 }
00626 SHOWIMG(tmp);
00627
00628
00629 std::vector<byte> oriVec;
00630 fv.toByteKey(oriVec);
00631
00632 SHOWIMG(fv.getFeatureVectorImage(oriVec));
00633
00634 return 0;
00635 }
00636
00637 float V4d::calculateOrientationVector(Point2D<int>& loc, Histogram& OV)
00638 {
00639
00640
00641 Image<float> perc(320,240, ZEROS);
00642 Image<float> ori(320,240, ZEROS);
00643 dense_hash_map<int, V1::EdgeState>::const_iterator iter;
00644 for(iter = itsHashedEdgesState.begin(); iter != itsHashedEdgesState.end(); iter++)
00645 {
00646 V1::EdgeState edgeState = iter->second;
00647 perc.setVal(edgeState.pos, edgeState.prob);
00648 ori.setVal(edgeState.pos, edgeState.ori);
00649 }
00650
00651 int histSize = 36;
00652
00653
00654
00655 const float sigma = 1;
00656
00657 const float sig = 1.5F * sigma, inv2sig2 = - 0.5F / (sig * sig);
00658 const int dimX = perc.getWidth(), dimY = perc.getHeight();
00659
00660 const int xi = int(loc.i + 0.5f);
00661 const int yi = int(loc.j + 0.5f);
00662
00663 const int rad = int(3.0F * sig);
00664 const int rad2 = rad * rad;
00665
00666
00667 int starty = yi - rad; if (starty < 0) starty = 0;
00668 int stopy = yi + rad; if (stopy >= dimY) stopy = dimY-1;
00669
00670
00671 for (int ind_y = starty; ind_y <= stopy; ind_y ++)
00672 {
00673
00674
00675 const int yoff = ind_y - yi;
00676 const int bound = int(sqrtf(float(rad2 - yoff*yoff)) + 0.5F);
00677 int startx = xi - bound; if (startx < 0) startx = 0;
00678 int stopx = xi + bound; if (stopx >= dimX) stopx = dimX-1;
00679
00680 for (int ind_x = startx; ind_x <= stopx; ind_x ++)
00681 {
00682 const float dx = float(ind_x) - loc.i, dy = float(ind_y) - loc.j;
00683 const float distSq = dx * dx + dy * dy;
00684
00685
00686 const float gradVal = perc.getVal(ind_x, ind_y);
00687
00688
00689 const float gaussianWeight = expf(distSq * inv2sig2);
00690
00691
00692
00693 float angle = ori.getVal(ind_x, ind_y) + M_PI;
00694
00695
00696 angle = 0.5F * angle * histSize / M_PI;
00697 while (angle < 0.0F) angle += histSize;
00698 while (angle >= histSize) angle -= histSize;
00699
00700 OV.addValueInterp(angle, gaussianWeight * gradVal);
00701 }
00702 }
00703
00704
00705
00706 for (int i = 0; i < 3; i++) OV.smooth();
00707
00708
00709 float maxPeakValue = OV.findMax();
00710 float peakAngle = 0;
00711 int ai =0;
00712 for (int bin = 0; bin < histSize; bin++)
00713 {
00714
00715 const float midval = OV.getValue(bin);
00716
00717
00718
00719 if (midval < 0.8F * maxPeakValue) continue;
00720
00721
00722 const float leftval = OV.getValue((bin == 0) ? histSize-1 : bin-1);
00723
00724
00725 const float rightval = OV.getValue((bin == histSize-1) ? 0 : bin+1);
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736 const float a = 0.5f * (leftval + rightval) - midval;
00737 const float b = 0.5f * (rightval - leftval);
00738 float realangle = float(bin) - 0.5F * b / a;
00739
00740 realangle *= 2.0F * M_PI / histSize;
00741 realangle -= M_PI;
00742 peakAngle = realangle;
00743 ai++;
00744 LINFO("Ang %i %f", ai, realangle*180/M_PI + 90);
00745 }
00746
00747 return peakAngle;
00748
00749 }
00750
00751
00752 void V4d::evolve()
00753 {
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766 proposeParticles(itsFeaturesParticles, 0.0F);
00767
00768
00769 evaluateParticles(itsFeaturesParticles);
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779 }
00780
00781
00782 float V4d::evaluateParticles(std::vector<NAFState>& particles)
00783 {
00784
00785 LINFO("Evaluate Particles");
00786 CpuTimer timer;
00787 timer.reset();
00788
00789 std::vector<rutz::shared_ptr<LikelihoodJob> > jobs;
00790 for(uint p=0; p<particles.size(); p++)
00791 {
00792
00793
00794 getParticleLikelihood(particles[p]);
00795 }
00796
00797
00798 while(itsThreadServer->size() > 0)
00799 usleep(10000);
00800
00801 timer.mark();
00802 LINFO("Total time %0.2f sec", timer.real_secs());
00803
00804
00805 double sum = 0;
00806 double Neff = 0;
00807 for(uint i=0; i<particles.size(); i++)
00808 sum += particles[i].prob;
00809
00810 for(uint i=0; i<particles.size(); i++)
00811 {
00812 particles[i].weight = particles[i].prob/sum;
00813 Neff += squareOf(particles[i].weight);
00814 }
00815
00816 Neff = 1/Neff;
00817
00818
00819 return Neff;
00820
00821 }
00822
00823 void V4d::GHT(std::vector<V4d::GHTAcc>& accRet, const FeatureTemplate& featureTemplate)
00824 {
00825 ImageSet<float> acc(int(360/itsGHTAngStep), Dims(320,240), ZEROS);
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847 CpuTimer timer;
00848 timer.reset();
00849 std::vector<V1::EdgeState> rTable = featureTemplate.edges;
00850
00851
00852 std::vector<rutz::shared_ptr<GHTJob> > jobs;
00853
00854 for(int angIdx=0; angIdx<int(360/itsGHTAngStep); angIdx++)
00855 {
00856 jobs.push_back(rutz::make_shared(new GHTJob(this, acc[angIdx], angIdx, rTable)));
00857 itsThreadServer->enqueueJob(jobs.back());
00858
00859 }
00860
00861
00862 while(itsThreadServer->size() > 0)
00863 usleep(10000);
00864
00865
00866
00867 timer.mark();
00868 LINFO("Total time %0.2f sec", timer.real_secs());
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882 for(uint i=0; i<acc.size(); i++)
00883 for(int y=0; y<acc[i].getHeight(); y++)
00884 for(int x=0; x<acc[i].getWidth(); x++)
00885 if (acc[i].getVal(x,y) > 0)
00886 {
00887 GHTAcc ghtAcc;
00888 ghtAcc.pos = Point2D<int>(x,y);
00889 ghtAcc.ang = i*itsGHTAngStep;
00890 if (featureTemplate.featureType == VERTIX)
00891 ghtAcc.ang = i*itsGHTAngStep + 45;
00892 ghtAcc.scale = -1;
00893 ghtAcc.featureType = featureTemplate.featureType;
00894 ghtAcc.sum = acc[i].getVal(x,y);
00895 accRet.push_back(ghtAcc);
00896 }
00897 }
00898
00899 float V4d::voteForFeature(Image<float>& acc, int angIdx, std::vector<V1::EdgeState>& rTable)
00900 {
00901 float sum = 0;
00902
00903 for(uint ei = 0; ei < itsEdgesState.size(); ei++)
00904 {
00905 V1::EdgeState& edgeState = itsEdgesState[ei];
00906
00907 if (edgeState.prob > 0)
00908 {
00909 for(uint j=0; j<rTable.size(); j++)
00910 {
00911
00912 float ang = (angIdx*itsGHTAngStep)*M_PI/180;
00913
00914 float diffRot = edgeState.ori - (rTable[j].ori - ang);
00915 diffRot = atan(sin(diffRot)/cos(diffRot));
00916
00917 float stddevRot = 1;
00918 int sizeRot = int(ceil(stddevRot * sqrt(-2.0F * log(exp(-5.0F)))));
00919
00920 if (fabs(diffRot) < sizeRot*M_PI/180)
00921 {
00922 float rRot = exp(-((diffRot*diffRot)/(stddevRot*stddevRot)));
00923
00924
00925
00926
00927 float stddevX = 0.1;
00928 float stddevY = 0.1;
00929 int sizeX = int(ceil(stddevX * sqrt(-2.0F * log(exp(-5.0F)))));
00930 int sizeY = int(ceil(stddevY * sqrt(-2.0F * log(exp(-5.0F)))));
00931
00932
00933 for(int y=edgeState.pos.j-sizeY; y<edgeState.pos.j+sizeY; y++)
00934 {
00935 float diffY = y-edgeState.pos.j;
00936 float ry = exp(-((diffY*diffY)/(stddevY*stddevY)));
00937 for(int x=edgeState.pos.i-sizeX; x<edgeState.pos.i+sizeX; x++)
00938 {
00939 float diffX = x-edgeState.pos.i;
00940 float rx = exp(-((diffX*diffX)/(stddevX*stddevX)));
00941 float weight = rRot*rx*ry;
00942
00943 int a0 = x - int((float)rTable[j].pos.i*cos(ang) - (float)rTable[j].pos.j*sin(ang));
00944 int b0 = y - int((float)rTable[j].pos.i*sin(ang) + (float)rTable[j].pos.j*cos(ang));
00945
00946 if (acc.coordsOk(a0, b0))
00947 {
00948 sum += edgeState.prob + weight;
00949 float val = acc.getVal(a0, b0);
00950 val += weight*edgeState.prob;
00951 acc.setVal(a0, b0, val);
00952 }
00953 }
00954 }
00955 }
00956 }
00957 }
00958 }
00959
00960 return sum;
00961 }
00962
00963 Image<PixRGB<byte> > V4d::showParticles(const std::vector<NAFState>& particles)
00964 {
00965
00966 Image<float> probImg(320,240, ZEROS);
00967 Image<PixRGB<byte> > particlesImg(probImg.getDims(),ZEROS);
00968 for(uint i=0; i<particles.size(); i++)
00969 {
00970 Point2D<int> loc = (Point2D<int>)itsCamera.project(particles[i].pos);
00971 if (particlesImg.coordsOk(loc) &&
00972 particles[i].weight > probImg.getVal(loc) )
00973 {
00974 PixRGB<byte> col;
00975 if (particles[i].featureType == RIGHT_VERTIX)
00976 col = PixRGB<byte>(0, 255, 0);
00977 else if (particles[i].featureType == VERTIX)
00978 col = PixRGB<byte>(255, 0, 0);
00979 else
00980 col = PixRGB<byte>(0, 0, 255);
00981
00982 probImg.setVal(loc, particles[i].weight);
00983
00984 particlesImg.setVal(loc, col);
00985 }
00986 }
00987 inplaceNormalize(probImg, 0.0F, 255.0F);
00988
00989
00990
00991
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
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027 inplaceNormalize(probImg, 0.0F, 255.0F);
01028 particlesImg = toRGB(probImg);
01029
01030
01031
01032 return particlesImg;
01033
01034 }
01035
01036 void V4d::proposeParticles(std::vector<NAFState>& particles, const double Neff)
01037 {
01038
01039 LINFO("Propose Particles");
01040
01041
01042
01043
01044
01045
01046
01047 float probThresh = 0.5;
01048
01049
01050 uint particlesAboveProb = 0;
01051 for(uint i=0; i<particles.size(); i++)
01052 {
01053 if (particles[i].prob > probThresh)
01054 {
01055 particles[i].pos.x += randomDoubleFromNormal(1.0);
01056 particles[i].pos.y += randomDoubleFromNormal(1.0);
01057 particles[i].pos.z = itsObjectsDist + randomDoubleFromNormal(0.05);
01058 particles[i].rot += randomDoubleFromNormal(1)*M_PI/180;
01059 particles[i].weight = 1.0/(float)particles.size();
01060 particlesAboveProb++;
01061 }
01062 }
01063
01064
01065
01066
01067
01068
01069 if (particlesAboveProb < particles.size())
01070 {
01071 LINFO("GHT ");
01072 std::vector<GHTAcc> acc;
01073
01074
01075
01076
01077
01078 Image<float> tmp(320,240,ZEROS);
01079 for(uint i=0; i<itsEdgesState.size(); i++)
01080 tmp.setVal(itsEdgesState[i].pos, itsEdgesState[i].prob);
01081 inplaceNormalize(tmp, 0.0F, 255.0F);
01082
01083
01084 Dims win(15,15);
01085 float hist[360];
01086 for(int i=0; i<360; i++)
01087 hist[i] = 0;
01088 while(!itsCornersState.empty())
01089 {
01090 V2::CornerState cornerState = itsCornersState.top(); itsCornersState.pop();
01091 tmp.setVal((Point2D<int>)cornerState.pos, cornerState.prob);
01092 drawCircle(tmp, (Point2D<int>)cornerState.pos, 6, (float)255.0);
01093 SHOWIMG(tmp);
01094
01095 Image<float> edges(win,ZEROS);
01096 for(int wy=0; wy<win.h(); wy++)
01097 for(int wx=0; wx<win.w(); wx++)
01098 {
01099 int x = (int)cornerState.pos.i + wx - (win.w()/2);
01100 int y = (int)cornerState.pos.j + wy - (win.h()/2);
01101
01102 int key = x + 320 * y;
01103 if (key > 0)
01104 {
01105 dense_hash_map<int, V1::EdgeState>::const_iterator iter = itsHashedEdgesState.find(key);
01106 if (iter != itsHashedEdgesState.end())
01107 {
01108 edges.setVal(wx,wy, iter->second.prob);
01109 int ang = (int)(iter->second.ori*180.0/M_PI);
01110 if (ang < 0) ang += 360;
01111 if (ang > 360) ang -= 360;
01112 hist[ang] += iter->second.prob;
01113
01114 }
01115 }
01116 }
01117 for(int i=1; i<359; i++)
01118 if (hist[i] > 1)
01119 if (hist[i] > hist[i-1] && hist[i] > hist[i+1])
01120 printf("%i %0.1f\n",i, hist[i]);
01121 printf("\n");
01122
01123 SHOWIMG(edges);
01124
01125 }
01126
01127
01128
01129 LINFO("GHT Done ");
01130
01131
01132
01133 CpuTimer timer;
01134 timer.reset();
01135
01136 normalizeAcc(acc);
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152 LINFO("Build priority queue");
01153 std::priority_queue <GHTAcc> pAcc;
01154 for(uint i=0; i<acc.size(); i++)
01155 pAcc.push(acc[i]);
01156
01157 LINFO("Get particules");
01158
01159 for(uint i=0; i<particles.size(); i++)
01160 {
01161 if (particles[i].prob <= probThresh)
01162 {
01163
01164 if (pAcc.empty())
01165 break;
01166 GHTAcc p = pAcc.top(); pAcc.pop();
01167
01168 NAFState nafState;
01169 Point3D<float> iPoint = itsCamera.inverseProjection(Point2D<float>(p.pos), itsObjectsDist);
01170 nafState.pos.x = iPoint.x;
01171 nafState.pos.y = iPoint.y;
01172 nafState.pos.z = itsObjectsDist;
01173 nafState.rot = p.ang*M_PI/180;
01174 nafState.featureType = p.featureType;
01175 nafState.weight = 1.0/(float)particles.size();
01176 nafState.prob = 1.0e-50;
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193 {
01194 particles[i].pos = nafState.pos;
01195 particles[i].rot = nafState.rot;
01196 particles[i].featureType = nafState.featureType;
01197 particles[i].weight = nafState.weight;
01198 particles[i].prob = nafState.prob;
01199 }
01200
01201
01202
01203
01204 }
01205 }
01206 timer.mark();
01207 LINFO("Get particles: Total time %0.2f sec", timer.real_secs());
01208
01209 }
01210 LINFO("Done proposeing");
01211 }
01212
01213 void V4d::mergeBias(std::vector<GHTAcc>& acc)
01214 {
01215 LINFO("Merge bias");
01216 CpuTimer timer;
01217 timer.reset();
01218
01219
01220
01221
01222 ImageSet<float> tmpAcc(360*2, Dims(320,240), ZEROS);
01223
01224 for(uint p=0; p<itsBias.size(); p++)
01225 {
01226 if (itsBias[p].prob > 0)
01227 {
01228 GHTAcc ghtAcc;
01229 Point2D<int> pos = (Point2D<int>)itsCamera.project(itsBias[p].pos);
01230 int ang = int(itsBias[p].rot*180/M_PI);
01231
01232 int fType = 0;
01233 switch(itsBias[p].featureType)
01234 {
01235 case RIGHT_VERTIX: fType = 0; break;
01236 case VERTIX: fType = 1; break;
01237 case ARC: fType = 1; break;
01238 }
01239 if (tmpAcc[fType*360 + ang].coordsOk(pos))
01240 tmpAcc[fType*360 + ang].setVal(pos,itsBias[p].prob);
01241 }
01242 }
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256 for(uint i=0; i<acc.size(); i++)
01257 {
01258 Point2D<int> pos = acc[i].pos;
01259 int rot = acc[i].ang;
01260 float sum = acc[i].sum;
01261
01262 int fType = 0;
01263 switch(acc[i].featureType)
01264 {
01265 case RIGHT_VERTIX: fType = 0; break;
01266 case VERTIX: fType = 1; break;
01267 case ARC: fType = 1; break;
01268 }
01269
01270 if (rot > 360) rot -= 360;
01271 if (rot == 360) rot = 0;
01272
01273 if (tmpAcc[fType*360 + rot].coordsOk(pos))
01274 {
01275 float prior = tmpAcc[fType*360 + rot].getVal(pos);
01276
01277 float post = sum+prior;
01278
01279 tmpAcc[fType*360 + rot].setVal(pos, post);
01280 }
01281 }
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296 acc.clear();
01297 for(uint i=0; i<tmpAcc.size(); i++)
01298 for(int y=0; y<tmpAcc[i].getHeight(); y++)
01299 for(int x=0; x<tmpAcc[i].getWidth(); x++)
01300 if (tmpAcc[i].getVal(x,y) > 0)
01301 {
01302 GHTAcc ghtAcc;
01303 ghtAcc.pos = Point2D<int>(x,y);
01304
01305 if (i > 360)
01306 {
01307 ghtAcc.featureType = VERTIX;
01308 ghtAcc.ang =(i - 360);
01309 }
01310 else
01311 {
01312 ghtAcc.featureType = RIGHT_VERTIX;
01313 ghtAcc.ang = i;
01314 }
01315 ghtAcc.scale = -1;
01316 ghtAcc.sum = tmpAcc[i].getVal(x,y);
01317 acc.push_back(ghtAcc);
01318 }
01319
01320 normalizeAcc(acc);
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334 timer.mark();
01335 LINFO("Merge bias: Total time %0.2f sec", timer.real_secs());
01336
01337 }
01338
01339 void V4d::findAngMerge(std::vector<GHTAcc>& acc, const NAFState& biasNafState, std::vector<GHTAcc> tmpAcc)
01340 {
01341
01342 int nearPart = 0;
01343 float partDist = 1.0e100;
01344 for(uint i=0; i<acc.size(); i++)
01345 {
01346 NAFState nafState;
01347 nafState.pos = itsCamera.inverseProjection(Point2D<float>(acc[i].pos), itsObjectsDist);
01348 nafState.rot = acc[i].ang*M_PI/180;
01349 nafState.featureType = acc[i].featureType;
01350
01351 float distance = nafState.distance(biasNafState);
01352 if (distance < partDist)
01353 {
01354 partDist = distance;
01355 nearPart = i;
01356 }
01357 }
01358
01359
01360 if (partDist < 10)
01361 acc[nearPart].sum += (0.1 + biasNafState.prob);
01362 else
01363 {
01364 GHTAcc ghtAcc;
01365 ghtAcc.pos = (Point2D<int>)itsCamera.project(biasNafState.pos);
01366 ghtAcc.ang = int(biasNafState.rot*180/M_PI);
01367 ghtAcc.featureType = biasNafState.featureType;
01368 ghtAcc.scale = -1;
01369 ghtAcc.sum = 0.1 + biasNafState.prob;
01370
01371 tmpAcc.push_back(ghtAcc);
01372 }
01373
01374 }
01375
01376 void V4d::harrisDetector(std::vector<V4d::GHTAcc>& accRet, const FeatureTemplate& featureTemplate)
01377 {
01378 Image<float> tmp(320,240,ZEROS);
01379 dense_hash_map<int, V1::EdgeState>::const_iterator iter;
01380 for(iter = itsHashedEdgesState.begin(); iter != itsHashedEdgesState.end(); iter++)
01381 {
01382 V1::EdgeState edgeState = iter->second;
01383 tmp.setVal(edgeState.pos, edgeState.prob);
01384 }
01385
01386 IplImage* img = img2ipl(tmp);
01387 IplImage* hImg = cvCreateImage( cvSize(img->width, img->height), IPL_DEPTH_32F, 1 );
01388
01389 cvCornerHarris(img, hImg, 5, 5, 0);
01390 SHOWIMG(ipl2float(hImg));
01391
01392 Image<float> acc = ipl2float(hImg);
01393
01394 inplaceNormalize(acc, 0.0F, 1.0F);
01395 for(int y=0; y<acc.getHeight(); y++)
01396 for(int x=0; x<acc.getWidth(); x++)
01397 if (acc.getVal(x,y) > 0)
01398 {
01399 GHTAcc ghtAcc;
01400 ghtAcc.pos = Point2D<int>(x,y);
01401 ghtAcc.ang = 0;
01402
01403
01404
01405 ghtAcc.scale = -1;
01406 ghtAcc.featureType = featureTemplate.featureType;
01407 ghtAcc.sum = acc.getVal(x,y);
01408 accRet.push_back(ghtAcc);
01409 }
01410
01411 }
01412 void V4d::proposeParticlesHarris(std::vector<NAFState>& particles, const double Neff)
01413 {
01414
01415 LINFO("Propose Particles");
01416 float probThresh = 0.5;
01417
01418
01419 uint particlesAboveProb = 0;
01420 for(uint i=0; i<particles.size(); i++)
01421 {
01422 if (particles[i].prob > probThresh)
01423 {
01424 particles[i].pos.x += randomDoubleFromNormal(1.0);
01425 particles[i].pos.y += randomDoubleFromNormal(1.0);
01426 particles[i].pos.z = itsObjectsDist + randomDoubleFromNormal(0.05);
01427 particles[i].rot += randomDoubleFromNormal(1)*M_PI/180;
01428 particles[i].weight = 1.0/(float)particles.size();
01429 particlesAboveProb++;
01430 }
01431 }
01432
01433
01434
01435
01436 if (particlesAboveProb < particles.size())
01437 {
01438 std::vector<GHTAcc> acc;
01439 harrisDetector(acc, itsNAFeatures[RIGHT_VERTIX]);
01440
01441 for(uint i=0; i<particles.size(); i++)
01442 {
01443 if (particles[i].prob <= probThresh)
01444 {
01445
01446 float maxVal = acc[0].sum; int maxIdx = 0;
01447 for(uint j=0; j<acc.size(); j++)
01448 {
01449 if (acc[j].sum > maxVal)
01450 {
01451 maxVal = acc[j].sum;
01452 maxIdx = j;
01453 }
01454 }
01455
01456
01457 GHTAcc p = acc.at(maxIdx);
01458
01459 Point3D<float> iPoint = itsCamera.inverseProjection(Point2D<float>(p.pos), itsObjectsDist);
01460 particles[i].pos.x = iPoint.x;
01461 particles[i].pos.y = iPoint.y;
01462 particles[i].pos.z = itsObjectsDist;
01463 particles[i].rot = ((p.ang + 180) + randomDoubleFromNormal(5))*M_PI/180;
01464 particles[i].featureType = p.featureType;
01465 particles[i].weight = 1.0/(float)particles.size();
01466 particles[i].prob = 1.0e-50;
01467 acc[maxIdx].sum = 0;
01468 }
01469 }
01470 }
01471 }
01472
01473 void V4d::normalizeAcc(std::vector<GHTAcc>& acc)
01474 {
01475
01476 double sum = 0;
01477 for(uint i=0; i<acc.size(); i++)
01478 sum += acc[i].sum;
01479
01480 for(uint i=0; i<acc.size(); i++)
01481 acc[i].sum /= sum;
01482 }
01483
01484 void V4d::resampleParticles2(std::vector<NAFState>& particles)
01485 {
01486 std::vector<NAFState> newParticles;
01487
01488 while(newParticles.size() < particles.size())
01489 {
01490
01491 int maxP = 0; double maxVal = particles[maxP].weight;
01492 for(uint j=1; j<particles.size(); j++)
01493 {
01494 if (particles[j].weight > maxVal)
01495 {
01496 maxP = j;
01497 maxVal = particles[j].weight;
01498 }
01499 }
01500
01501 if (maxVal > 0)
01502 {
01503 for(int np=0; np<10; np++)
01504 {
01505
01506 NAFState p = particles[maxP];
01507 p.weight = 1.0/double(particles.size());
01508 newParticles.push_back(p);
01509 }
01510
01511
01512 float sigmaX = 0.1, sigmaY = 0.1;
01513 float fac = 0.5f / (M_PI * sigmaX * sigmaY);
01514 float vx = -0.5f / (sigmaX * sigmaX);
01515 float vy = -0.5f / (sigmaY * sigmaY);
01516
01517 for(uint j=0; j<particles.size(); j++)
01518 {
01519 float x = particles[j].pos.x;
01520 float y = particles[j].pos.y;
01521
01522 float vydy2 = y - particles[maxP].pos.y; vydy2 *= vydy2 * vy;
01523 float dx2 = x - particles[maxP].pos.x; dx2 *= dx2;
01524 particles[j].weight -= particles[j].weight * fac*expf(vx * dx2 + vydy2);
01525 if (particles[j].weight < 0)
01526 particles[j].weight = 0;
01527
01528 }
01529 particles[maxP].weight = 0;
01530 } else {
01531 NAFState p = particles[0];
01532 p.weight = 1.0/double(particles.size());
01533 newParticles.push_back(p);
01534 }
01535
01536 }
01537
01538 particles = newParticles;
01539
01540 }
01541
01542
01543 void V4d::resampleParticles(std::vector<NAFState>& particles)
01544 {
01545
01546 LINFO("Resample particles");
01547 std::vector<NAFState> newParticles;
01548
01549 if(particles.size() == 0)
01550 return;
01551
01552
01553 uint i = 0;
01554 double c = particles.at(0).weight;
01555 double U = randomDouble()* 1.0/double(particles.size());
01556
01557 for(uint j=0; j < particles.size(); j++)
01558 {
01559
01560 while(U > c)
01561 {
01562 i++;
01563 c += particles.at(i).weight;
01564 }
01565
01566 NAFState p = particles.at(i);
01567 p.weight = 1.0/double(particles.size());
01568 newParticles.push_back(p);
01569
01570 U += 1.0/double(particles.size());
01571 }
01572
01573 particles = newParticles;
01574
01575 }
01576
01577 std::vector<Point2D<int> > V4d::getImageOutline(NAFState& nafState)
01578 {
01579
01580 FeatureTemplate featureCameraOutline = itsNAFeatures[nafState.featureType];
01581
01582
01583 for(uint i=0; i<featureCameraOutline.outline.size(); i++)
01584 {
01585 float x = featureCameraOutline.outline[i].x;
01586 float y = featureCameraOutline.outline[i].y;
01587 float z = featureCameraOutline.outline[i].z;
01588 featureCameraOutline.outline[i].x = (cos(nafState.rot)*x - sin(nafState.rot)*y) + nafState.pos.x;
01589 featureCameraOutline.outline[i].y = (sin(nafState.rot)*x + cos(nafState.rot)*y) + nafState.pos.y;
01590 featureCameraOutline.outline[i].z = z + nafState.pos.z;
01591 }
01592
01593
01594 std::vector<Point2D<int> > outline;
01595 for(uint i=0; i<featureCameraOutline.outline.size(); i++)
01596 {
01597 Point2D<float> loc = itsCamera.project(featureCameraOutline.outline[i]);
01598 outline.push_back(Point2D<int>(loc));
01599 }
01600
01601 return outline;
01602
01603 }
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654 void V4d::getParticleLikelihood(NAFState& particle)
01655 {
01656 while(particle.rot > M_PI*2)
01657 particle.rot =- M_PI*2;
01658
01659 while(particle.rot < 0)
01660 particle.rot =+ M_PI*2;
01661
01662 FeatureTemplate featureTemplate = itsNAFeatures[particle.featureType];
01663
01664
01665 Image<float> tmp(320,240,ZEROS);
01666 double totalProb = 1;
01667
01668 Point2D<float> featureLoc = itsCamera.project(particle.pos);
01669 float featureRot = particle.rot;
01670
01671
01672 if (particle.featureType == VERTIX)
01673 featureRot -= M_PI/4;
01674 int badValues = 0;
01675 for(uint i=0; i<featureTemplate.edges.size(); i++)
01676 {
01677
01678 V1::EdgeState featureEdgeState = featureTemplate.edges[i];
01679
01680 int x = featureEdgeState.pos.i;
01681 int y = featureEdgeState.pos.j;
01682
01683
01684 featureEdgeState.pos.i = (int)(featureLoc.i + (float)x*cos(featureRot) - (float)y*sin(featureRot));
01685 featureEdgeState.pos.j = (int)(featureLoc.j + (float)x*sin(featureRot) + (float)y*cos(featureRot));
01686
01687 featureEdgeState.ori = featureEdgeState.ori - featureRot + M_PI/2;
01688
01689 int nearEdge = 0;
01690
01691
01692 double edgeDist = 1.0e100;
01693 for(uint i = 0; i < itsEdgesState.size(); i++)
01694 {
01695 if (itsEdgesState[i].prob > 0)
01696 {
01697
01698 float distance = 1.0e100;
01699 if (itsEdgesState[i].pos == featureEdgeState.pos)
01700
01701 {
01702 double dRot = itsEdgesState[i].ori + M_PI/2 - featureEdgeState.ori;
01703 dRot = atan(sin(dRot)/cos(dRot))*180/M_PI;
01704 distance = dRot;
01705 }
01706
01707
01708
01709
01710
01711
01712
01713 if (distance < edgeDist)
01714 {
01715 nearEdge = i;
01716 edgeDist = distance;
01717 }
01718 }
01719 }
01720
01721 if (edgeDist == 1.0e100)
01722 badValues++;
01723 else
01724 if (badValues < 3)
01725 {
01726
01727 float sig = 10.75F;
01728 float prob = (1.0F/(sig*sqrt(2*M_PI))*exp(-0.5*squareOf(edgeDist)/squareOf(sig)));
01729 totalProb *= prob;
01730 } else {
01731 totalProb = 0;
01732 }
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745 }
01746
01747
01748 particle.prob = totalProb;
01749
01750
01751
01752
01753
01754
01755
01756
01757 if (itsBias.size() > 0)
01758 {
01759 int nearPart = 0;
01760 float partDist = itsBias[nearPart].distance(particle);
01761
01762 for(uint p=1; p<itsBias.size(); p++)
01763 {
01764 float distance = itsBias[p].distance(particle);
01765 if (distance < partDist)
01766 {
01767 partDist = distance;
01768 nearPart = p;
01769 }
01770 }
01771
01772
01773 if (partDist < 10)
01774 particle.prob += (0.1 + itsBias[nearPart].prob);
01775 if (particle.prob > 1)
01776 particle.prob = 1;
01777 }
01778 }
01779
01780
01781 double V4d::getLineProbability(const Point2D<int>& p1, const Point2D<int>& p2)
01782 {
01783
01784 int dx = p2.i - p1.i, ax = abs(dx) << 1, sx = signOf(dx);
01785 int dy = p2.j - p1.j, ay = abs(dy) << 1, sy = signOf(dy);
01786 int x = p1.i, y = p1.j;
01787
01788 const int w = 320;
01789
01790 double prob = 1;
01791
01792 int wSize = 1;
01793 if (ax > ay)
01794 {
01795 int d = ay - (ax >> 1);
01796 for (;;)
01797 {
01798
01799 float maxProb = 0;
01800 for(int yy = y-wSize; yy < y+wSize; yy++)
01801 for(int xx = x-wSize; xx < x+wSize; xx++)
01802 {
01803 int key = xx + w * yy;
01804 if (key > 0)
01805 {
01806 dense_hash_map<int, V1::EdgeState>::const_iterator iter = itsHashedEdgesState.find(key);
01807 if (iter != itsHashedEdgesState.end())
01808 {
01809 if (iter->second.prob > maxProb)
01810 maxProb = iter->second.prob;
01811 }
01812 }
01813 }
01814 prob *= maxProb;
01815
01816 if (x == p2.i) return prob;
01817 if (d >= 0) { y += sy; d -= ax; }
01818 x += sx; d += ay;
01819 }
01820 } else {
01821 int d = ax - (ay >> 1);
01822 for (;;)
01823 {
01824 float maxProb = 0;
01825 for(int yy = y-wSize; yy < y+wSize; yy++)
01826 for(int xx = x-wSize; xx < x+wSize; xx++)
01827 {
01828 int key = xx + w * yy;
01829 if (key > 0)
01830 {
01831 dense_hash_map<int, V1::EdgeState>::const_iterator iter = itsHashedEdgesState.find(key);
01832 if (iter != itsHashedEdgesState.end())
01833 {
01834 if (iter->second.prob > maxProb)
01835 maxProb = iter->second.prob;
01836 }
01837 }
01838 }
01839 prob *= maxProb;
01840 if (y == p2.j) return prob;
01841
01842 if (d >= 0) { x += sx; d -= ay; }
01843 y += sy; d += ax;
01844 }
01845 }
01846
01847 return prob;
01848
01849
01850 }
01851
01852 Layout<PixRGB<byte> > V4d::getDebugImage()
01853 {
01854 Layout<PixRGB<byte> > outDisp;
01855
01856
01857 Image<float> perc(320,240, ZEROS);
01858
01859
01860 for(uint i=0; i<itsEdgesState.size(); i++)
01861 perc.setVal(itsEdgesState[i].pos, itsEdgesState[i].prob);
01862
01863 inplaceNormalize(perc, 0.0F, 255.0F);
01864
01865 Image<PixRGB<byte> > NAFDisp = toRGB(Image<byte>(perc));
01866
01867
01868 float minVal = itsFeaturesParticles[0].prob;
01869 float maxVal = itsFeaturesParticles[0].prob;
01870 for(uint p=0; p<itsFeaturesParticles.size(); p++)
01871 {
01872 if (itsFeaturesParticles[p].prob < minVal)
01873 minVal = itsFeaturesParticles[p].prob;
01874 if (itsFeaturesParticles[p].prob > maxVal)
01875 maxVal = itsFeaturesParticles[p].prob;
01876 }
01877
01878 float scale = maxVal - minVal;
01879 float nScale = (255.0F - 0.0F)/scale;
01880 for(uint p=0; p<itsFeaturesParticles.size(); p++)
01881 {
01882
01883 float normProb = 0.0F + ((itsFeaturesParticles[p].prob - minVal) * nScale);
01884
01885 if (itsFeaturesParticles[p].prob > 0)
01886 {
01887 normProb = 255.0;
01888 PixRGB<byte> col;
01889 if (itsFeaturesParticles[p].featureType == RIGHT_VERTIX)
01890 col = PixRGB<byte>(0,int(normProb),0);
01891 else if (itsFeaturesParticles[p].featureType == VERTIX)
01892 col = PixRGB<byte>(int(normProb),0, 0);
01893 else
01894 col = PixRGB<byte>(0,0,int(normProb));
01895
01896 std::vector<Point2D<int> > outline = getImageOutline(itsFeaturesParticles[p]);
01897 for(uint i=0; i<outline.size()-1; i++)
01898 drawLine(NAFDisp, outline[i], outline[i+1], col, 1);
01899 }
01900 }
01901
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917 Image<PixRGB<byte> > particlesImg = showParticles(itsFeaturesParticles);
01918
01919 outDisp = hcat(NAFDisp, particlesImg);
01920
01921 return outDisp;
01922
01923 }
01924
01925
01926
01927
01928
01929
01930
01931 #endif
01932