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 LineGrouping_C_DEFINED
00039 #define LineGrouping_C_DEFINED
00040
00041 #include "plugins/SceneUnderstanding/LineGrouping.H"
00042 #include "Image/DrawOps.H"
00043 #include "Image/MathOps.H"
00044 #include "Image/Kernels.H"
00045 #include "Image/FilterOps.H"
00046 #include "Image/Transforms.H"
00047 #include "Image/fancynorm.H"
00048 #include "Image/Convolutions.H"
00049 #include "Image/MatrixOps.H"
00050 #include "Simulation/SimEventQueue.H"
00051 #include "GUI/DebugWin.H"
00052 #include <math.h>
00053 #include <fcntl.h>
00054 #include <limits>
00055 #include <string>
00056 #include <stack>
00057
00058 const ModelOptionCateg MOC_LineGrouping = {
00059 MOC_SORTPRI_3, "LineGrouping-Related Options" };
00060
00061
00062 const ModelOptionDef OPT_LineGroupingShowDebug =
00063 { MODOPT_ARG(bool), "LineGroupingShowDebug", &MOC_LineGrouping, OPTEXP_CORE,
00064 "Show debug img",
00065 "linegrouping-debug", '\0', "<true|false>", "false" };
00066
00067
00068 SIMMODULEINSTFUNC(LineGrouping);
00069
00070 std::vector<Point2D<double> > getVel(const std::vector<Point2D<int> >& lines)
00071 {
00072 std::vector<Point2D<double> > vel;
00073
00074 for(uint i=0; i<lines.size()-1; i++)
00075 {
00076 Point2D<int> dPos = lines[i+1]-lines[i];
00077 double mag = sqrt((dPos.i*dPos.i) + (dPos.j*dPos.j))/4;
00078 for(int j=0; j<int(mag+0.5); j++)
00079 vel.push_back(Point2D<double>(dPos/mag));
00080 }
00081
00082 return vel;
00083
00084 }
00085
00086 int quantize(float x, float y, float z)
00087 {
00088 int val = 0;
00089
00090
00091 double rho = sqrt(x*x+y*y+z*z);
00092
00093 if (rho>3.0)
00094 val = 3<<3;
00095 else if (rho > 2.0)
00096 val = 2<<3;
00097 else if (rho>1.0)
00098 val = 1<<3;
00099 else
00100 val = 0;
00101
00102 if (x>y) val |= 1<<2;
00103 if (y>z) val |= 1<<1;
00104 if (z>x) val |= 1;
00105
00106 return val;
00107 }
00108
00109
00110
00111
00112 LineGrouping::LineGrouping(OptionManager& mgr, const std::string& descrName,
00113 const std::string& tagName) :
00114 SimModule(mgr, descrName, tagName),
00115 SIMCALLBACK_INIT(SimEventV2Output),
00116 SIMCALLBACK_INIT(SimEventSaveOutput),
00117 SIMCALLBACK_INIT(SimEventUserInput),
00118 itsShowDebug(&OPT_LineGroupingShowDebug, this)
00119
00120 {
00121
00122 std::vector<uint> states;
00123 for(uint i=0; i<5; i++)
00124 states.push_back(i);
00125
00126 std::vector<uint> posibleObservations;
00127 for(uint i=0; i<32; i++)
00128 posibleObservations.push_back(i);
00129
00130 itsHMM = HMM<uint>(states, posibleObservations, "Applelogo");
00131
00132 std::vector<Point2D<int> > lines;
00133 lines.push_back(Point2D<int>(7, 71));
00134 lines.push_back(Point2D<int>(17, 88));
00135 lines.push_back(Point2D<int>(19, 90));
00136 lines.push_back(Point2D<int>(27, 95));
00137 lines.push_back(Point2D<int>(29, 95));
00138 lines.push_back(Point2D<int>(38, 91));
00139 lines.push_back(Point2D<int>(39, 91));
00140 lines.push_back(Point2D<int>(55, 95));
00141 lines.push_back(Point2D<int>(56, 95));
00142 lines.push_back(Point2D<int>(61, 93));
00143 lines.push_back(Point2D<int>(62, 93));
00144 lines.push_back(Point2D<int>(74, 73));
00145 lines.push_back(Point2D<int>(74, 72));
00146 lines.push_back(Point2D<int>(65, 62));
00147 lines.push_back(Point2D<int>(65, 61));
00148 lines.push_back(Point2D<int>(63, 57));
00149 lines.push_back(Point2D<int>(63, 56));
00150 lines.push_back(Point2D<int>(65, 42));
00151 lines.push_back(Point2D<int>(66, 42));
00152 lines.push_back(Point2D<int>(71, 36));
00153 lines.push_back(Point2D<int>(70, 35));
00154 lines.push_back(Point2D<int>(68, 33));
00155 lines.push_back(Point2D<int>(67, 32));
00156 lines.push_back(Point2D<int>(53, 29));
00157 lines.push_back(Point2D<int>(52, 30));
00158 lines.push_back(Point2D<int>(45, 32));
00159 lines.push_back(Point2D<int>(44, 27));
00160 lines.push_back(Point2D<int>(56, 15));
00161 lines.push_back(Point2D<int>(56, 14));
00162 lines.push_back(Point2D<int>(57, 7));
00163 lines.push_back(Point2D<int>(56, 6));
00164 lines.push_back(Point2D<int>(53, 7));
00165 lines.push_back(Point2D<int>(52, 7));
00166 lines.push_back(Point2D<int>(40, 19));
00167 lines.push_back(Point2D<int>(40, 20));
00168 lines.push_back(Point2D<int>(42, 26));
00169 lines.push_back(Point2D<int>(44, 33));
00170 lines.push_back(Point2D<int>(25, 29));
00171 lines.push_back(Point2D<int>(24, 29));
00172 lines.push_back(Point2D<int>(17, 31));
00173 lines.push_back(Point2D<int>(15, 32));
00174 lines.push_back(Point2D<int>(6, 43));
00175 lines.push_back(Point2D<int>(5, 45));
00176 lines.push_back(Point2D<int>(5, 64));
00177 lines.push_back(Point2D<int>(6, 65));
00178 lines.push_back(Point2D<int>(7, 70));
00179
00180
00181 for(uint i=0; i<lines.size(); i++)
00182 lines[i] *= 2;
00183
00184
00185
00186 itsHMM.setStateTransition(0, 0, 0.5);
00187 itsHMM.setStateTransition(0, 1, 0.5);
00188 itsHMM.setStateTransition(1, 1, 0.5);
00189 itsHMM.setStateTransition(1, 2, 0.5);
00190 itsHMM.setStateTransition(2, 2, 0.5);
00191 itsHMM.setStateTransition(2, 3, 0.5);
00192 itsHMM.setStateTransition(3, 3, 0.5);
00193 itsHMM.setStateTransition(3, 4, 0.5);
00194 itsHMM.setStateTransition(4, 4, 1);
00195
00196
00197 itsHMM.setCurrentState(0, 1);
00198
00199 std::vector<Point2D<double> > vel = getVel(lines);
00200
00201 std::vector< std::vector<uint> > observations;
00202 for(size_t j=0; j<vel.size(); j++)
00203 {
00204 std::vector<uint> observation;
00205 printf("InputValue ");
00206 for(size_t i=0; i<vel.size(); i++)
00207 {
00208 uint value = quantize(vel[(i+j)%vel.size()].i,
00209 vel[(i+j)%vel.size()].j, 0);
00210 printf("%i ", value);
00211 observation.push_back(value);
00212 }
00213 printf("\n");
00214 observations.push_back(observation);
00215 }
00216 LINFO("Train");
00217 itsHMM.train(observations, 50);
00218 LINFO("Done");
00219
00220 }
00221
00222
00223 LineGrouping::~LineGrouping()
00224 {
00225 }
00226
00227
00228 void LineGrouping::onSimEventUserInput(SimEventQueue& q, rutz::shared_ptr<SimEventUserInput>& e)
00229 {
00230
00231 LINFO("Got event --%s-- %ix%i key=%i",
00232 e->getWinName(),
00233 e->getMouseClick().i,
00234 e->getMouseClick().j,
00235 e->getKey());
00236
00237 if (strcmp(e->getWinName(), "LineGrouping"))
00238 return;
00239
00240 switch(e->getKey())
00241 {
00242 case 111:
00243 break;
00244 case 116:
00245 break;
00246 case 113:
00247 break;
00248 case 114:
00249 break;
00250 case 21:
00251 break;
00252 case 20:
00253 break;
00254 case 38:
00255 break;
00256 case 52:
00257 break;
00258 case 39:
00259 break;
00260 case 53:
00261 break;
00262 case 40:
00263 break;
00264 case 54:
00265 break;
00266 case 10:
00267 break;
00268 case 24:
00269 break;
00270 case 11:
00271 break;
00272 case 25:
00273 break;
00274 case 12:
00275 break;
00276 case 26:
00277 break;
00278 case 13:
00279 break;
00280 case 27:
00281 break;
00282 case 14:
00283 break;
00284 case 28:
00285 break;
00286 case 15:
00287 break;
00288 case 29:
00289 break;
00290 }
00291
00292
00293 evolve(q);
00294
00295 }
00296
00297
00298
00299 void LineGrouping::onSimEventV2Output(SimEventQueue& q, rutz::shared_ptr<SimEventV2Output>& e)
00300 {
00301
00302
00303
00304
00305
00306 itsLines = e->getLines();
00307 itsInputDims = e->getDims();
00308
00309 evolve(q);
00310
00311 }
00312
00313
00314 void LineGrouping::onSimEventSaveOutput(SimEventQueue& q, rutz::shared_ptr<SimEventSaveOutput>& e)
00315 {
00316 if (itsShowDebug.getVal())
00317 {
00318
00319
00320 nub::ref<FrameOstream> ofs =
00321 dynamic_cast<const SimModuleSaveInfo&>(e->sinfo()).ofs;
00322 Layout<PixRGB<byte> > disp = getDebugImage(q);
00323 if (disp.initialized())
00324 ofs->writeRgbLayout(disp, "LineGrouping", FrameInfo("LineGrouping", SRC_POS));
00325 }
00326 }
00327
00328
00329
00330 void LineGrouping::evolve(SimEventQueue& q)
00331 {
00332
00333 Image<PixRGB<byte> > linesMask(itsInputDims, ZEROS);
00334
00335 Image<std::vector<uint> > linesIndices(itsInputDims, NO_INIT);
00336 for(uint i=0; i<itsLines.size(); i++)
00337 {
00338 V2::LineSegment& ls = itsLines[i];
00339
00340 Point2D<int> p1 = Point2D<int>(ls.p1);
00341 Point2D<int> p2 = Point2D<int>(ls.p2);
00342 linesIndices[p1].push_back(i);
00343 linesIndices[p2].push_back(i);
00344 drawLine(linesMask, p1, p2, PixRGB<byte>(50,50,50));
00345 }
00346
00347
00348
00349 std::vector<uint> lineColour(itsLines.size(), 0);
00350
00351 while(1)
00352 {
00353
00354 std::stack<LineInfo> linesStack;
00355 std::vector<LineInfo> linesGroup;
00356 std::vector<uint> linesGroupLevel;
00357 std::list<uint> linesGroupList;
00358
00359
00360 uint idx = 2;
00361 linesStack.push(LineInfo(idx));
00362
00363
00364 while(!linesStack.empty())
00365 {
00366
00367 LineInfo lineInfo = linesStack.top();
00368 linesGroup.push_back(lineInfo);
00369 linesStack.pop();
00370
00371
00372 lineColour[lineInfo.idx] = 1;
00373
00374 LINFO("Following line %d cost %f", lineInfo.idx, lineInfo.cost);
00375 Point2D<int> p1 = (Point2D<int>)itsLines[lineInfo.idx].p1;
00376 Point2D<int> p2 = (Point2D<int>)itsLines[lineInfo.idx].p2;
00377 drawLine(linesMask, p1, p2, PixRGB<byte>(0,255,0));
00378
00379 int radius = 5;
00380 std::vector<LineInfo> lines;
00381
00382
00383 lines = getLocalLines(p1, radius, lineColour, linesIndices);
00384 std::vector<LineInfo> p2Lines = getLocalLines(p2, radius, lineColour, linesIndices);
00385 lines.insert(lines.end(), p2Lines.begin(), p2Lines.end());
00386
00387 setTopDownCost(lines, linesGroup);
00388
00389
00390
00391
00392
00393 std::sort(lines.begin(), lines.end(), LineInfoCmp());
00394
00395
00396
00397 for(uint i=0; i<lines.size(); i++)
00398 {
00399 LineInfo line = lines[i];
00400 linesStack.push(line);
00401
00402
00403 Point2D<int> p1 = (Point2D<int>)itsLines[line.idx].p1;
00404 Point2D<int> p2 = (Point2D<int>)itsLines[line.idx].p2;
00405
00406 LINFO("Found line %i at X %i y %i cost %f", line.idx, p1.i, p1.j, line.cost);
00407 drawLine(linesMask, p1, p2, PixRGB<byte>(255,0,0));
00408 SHOWIMG(linesMask);
00409 }
00410
00411 LINFO("Lines added %zu", lines.size());
00412 if (lines.size() == 0)
00413 {
00414
00415 SHOWIMG(linesMask);
00416 LINFO("Showing Stack");
00417 Image<PixRGB<byte> > tmp(itsInputDims, NO_INIT);
00418 for(uint i=0; i<itsLines.size(); i++)
00419 {
00420 V2::LineSegment& ls = itsLines[i];
00421 Point2D<int> p1 = Point2D<int>(ls.p1);
00422 Point2D<int> p2 = Point2D<int>(ls.p2);
00423 drawLine(tmp, p1, p2, PixRGB<byte>(50,50,50));
00424 }
00425
00426 for(uint i=0; i<linesGroup.size(); i++)
00427 {
00428 LINFO("Stack %i %i %f", i, linesGroup[i].idx, linesGroup[i].cost);
00429 V2::LineSegment& ls = itsLines[linesGroup[i].idx];
00430 Point2D<int> p1 = Point2D<int>(ls.p1);
00431 Point2D<int> p2 = Point2D<int>(ls.p2);
00432 drawLine(tmp, p1, p2, PixRGB<byte>(0,255,0));
00433 }
00434 linesGroup.pop_back();
00435
00436 SHOWIMG(tmp);
00437 }
00438
00439
00440
00441 }
00442 LINFO("Done");
00443 getchar();
00444 }
00445 }
00446
00447
00448 void LineGrouping::setTopDownCost(std::vector<LineInfo>& newLines,const std::vector<LineInfo>& contour)
00449 {
00450
00451
00452 std::vector<Point2D<int> > locations;
00453
00454 V2::LineSegment& ls = itsLines[contour[0].idx];
00455 Point2D<int> p1 = Point2D<int>(ls.p1);
00456 Point2D<int> p2 = Point2D<int>(ls.p2);
00457 locations.push_back(p1);
00458 locations.push_back(p2);
00459
00460 for(uint i=1; i<contour.size(); i++)
00461 {
00462 V2::LineSegment& ls = itsLines[contour[i].idx];
00463 Point2D<int> p1 = Point2D<int>(ls.p1);
00464 Point2D<int> p2 = Point2D<int>(ls.p2);
00465
00466 if (p2.distance(p1) > p2.distance(p2))
00467 locations.push_back(p1);
00468 else
00469 locations.push_back(p2);
00470 }
00471
00472
00473 Point2D<int> lastLoc = locations[locations.size()-2];
00474
00475 for(uint i=0; i<newLines.size(); i++)
00476 {
00477
00478 std::vector<Point2D<int> > newLocations = locations;
00479 V2::LineSegment& ls = itsLines[newLines[i].idx];
00480 Point2D<int> p1 = Point2D<int>(ls.p1);
00481 Point2D<int> p2 = Point2D<int>(ls.p2);
00482
00483 if (lastLoc.distance(p1) > lastLoc.distance(p2))
00484 newLocations.push_back(p1);
00485 else
00486 newLocations.push_back(p2);
00487
00488
00489 std::vector<Point2D<double> > vel = getVel(newLocations);
00490 std::vector<uint> observations;
00491 for(size_t j=0; j<vel.size(); j++)
00492 {
00493 uint value = quantize(vel[j].i, vel[j].j, 0);
00494 observations.push_back(value);
00495 }
00496
00497
00498 if (vel.size() > 10)
00499 {
00500 double prob = itsHMM.forward(observations);
00501 newLines[i].cost = prob;
00502 LINFO("Checking line %i idx %i cost %f", i, newLines[i].idx, prob);
00503 } else {
00504 LINFO("Follow bottom up line %i idx %i cost %f", i, newLines[i].idx, newLines[i].cost);
00505 }
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 }
00521
00522 }
00523
00524
00525
00526
00527 std::vector<LineGrouping::LineInfo> LineGrouping::getLocalLines(const Point2D<int> loc,
00528 const int radius,
00529 std::vector<uint>& lineColour,
00530 const Image<std::vector<uint> >& linesIndices)
00531 {
00532 std::vector<LineInfo> lines;
00533
00534 for(int x=loc.i-radius; x<=loc.i+radius; x++)
00535 for(int y=loc.j-radius; y<=loc.j+radius; y++)
00536 {
00537 Point2D<int> lineLoc =Point2D<int>(x,y);
00538
00539 if (linesIndices.coordsOk(lineLoc) &&
00540 linesIndices.getVal(lineLoc).size() > 0)
00541 {
00542 for(uint j=0; j<linesIndices[lineLoc].size(); j++)
00543 {
00544 uint idx = linesIndices[lineLoc][j];
00545 if (!lineColour[idx])
00546 {
00547 lineColour[idx] = 1;
00548 double cost = loc.distance(lineLoc);
00549 lines.push_back(LineInfo(idx,cost));
00550 }
00551 }
00552 }
00553 }
00554 return lines;
00555 }
00556
00557
00558 std::vector<V2::LineSegment> LineGrouping::getAndRemoveLinesNearLoc(Image<std::vector<uint> >& linesIndices,
00559 const Point2D<int> loc, const int radius)
00560 {
00561 std::vector<V2::LineSegment> lines;
00562
00563 for(int x=loc.i-radius; x<=loc.i+radius; x++)
00564 for(int y=loc.j-radius; y<=loc.j+radius; y++)
00565 {
00566 Point2D<int> lineLoc =Point2D<int>(x,y);
00567 if (linesIndices.coordsOk(lineLoc) &&
00568 linesIndices.getVal(lineLoc).size() > 0)
00569 {
00570 for(uint j=0; j<linesIndices[lineLoc].size(); j++)
00571 {
00572 uint idx = linesIndices[lineLoc][j];
00573 lines.push_back(itsLines[idx]);
00574 }
00575 linesIndices[lineLoc].clear();
00576 }
00577 }
00578
00579 return lines;
00580
00581 }
00582
00583 Layout<PixRGB<byte> > LineGrouping::getDebugImage(SimEventQueue& q)
00584 {
00585 Layout<PixRGB<byte> > outDisp;
00586
00587 Image<PixRGB<byte> > inputImg(itsInputDims,ZEROS);
00588 for(uint i=0; i<itsLines.size(); i++)
00589 {
00590 V2::LineSegment& ls = itsLines[i];
00591 drawLine(inputImg, Point2D<int>(ls.p1), Point2D<int>(ls.p2), PixRGB<byte>(255,0,0));
00592 }
00593
00594
00595 outDisp = inputImg;
00596
00597 return outDisp;
00598
00599 }
00600
00601
00602
00603
00604
00605
00606
00607
00608 #endif
00609