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 V2_H_DEFINED
00039 #define V2_H_DEFINED
00040
00041
00042
00043 #include "Image/Image.H"
00044 #include "Image/ImageSet.H"
00045 #include "Image/Pixels.H"
00046 #include "Image/Layout.H"
00047 #include "Image/TensorOps.H"
00048 #include "plugins/SceneUnderstanding/V1.H"
00049 #include "plugins/SceneUnderstanding/TensorVoting.H"
00050 #include "Simulation/SimEvents.H"
00051 #include "Simulation/SimModule.H"
00052 #include "Util/WorkThreadServer.H"
00053 #include <float.h>
00054
00055
00056
00057 #include <limits>
00058 #include <vector>
00059 #include <string>
00060 #include <stack>
00061 #include <list>
00062
00063 #define NOTDEF -1000.0
00064 #define BIG_NUMBER 1.0e+300
00065 #define M_3_2_PI 4.71238898038
00066 #define M_2__PI 6.28318530718
00067 #define NOTUSED 0
00068 #define USED 1
00069 #define NOTINI 2
00070
00071 #define MY_ROUND(f) ( (float) floor( (double) (f) + 0.5 ) )
00072
00073 struct NFAInfo
00074 {
00075 short int ori;
00076 short int xLoc;
00077 short int yLoc;
00078 short int length;
00079 short int pts;
00080 short int alg;
00081 };
00082
00083 struct NumEntries
00084 {
00085 size_t num;
00086 short int pts;
00087 NumEntries() : num(0), pts(0) {}
00088
00089 };
00090
00091
00092 typedef std::map<short int,
00093 std::map<short int,
00094 std::map<short int,
00095 std::map<short int,
00096 std::map<short int,
00097 NumEntries > > > > > NFAPDFMap;
00098
00099
00100
00101 class Rect
00102 {
00103
00104 public:
00105
00106 Rect(const Point2D<int>& center, Dims& d, float ori) :
00107 itsCenter(center),
00108 itsSize(d),
00109 itsOri(ori)
00110 {
00111 float distX = itsSize.w()/2;
00112 float distY = itsSize.h()/2;
00113 float radius = sqrt((distX*distX) + (distY*distY));
00114
00115 float thetaO = atan(distX/distY);
00116 float thetaN1 = thetaO + itsOri;
00117 float thetaN2 = itsOri - thetaO;
00118 float Xnew1 = radius*sin(thetaN1);
00119 float Ynew1 = radius*cos(thetaN1);
00120 float Xnew2 = radius*sin(thetaN2);
00121 float Ynew2 = radius*cos(thetaN2);
00122
00123 itsP1 = Point2D<int>(itsCenter.i+Xnew1, itsCenter.j+Ynew1);
00124 itsP2 = Point2D<int>(itsCenter.i+Xnew2, itsCenter.j+Ynew2);
00125 itsP3 = Point2D<int>(itsCenter.i-Xnew1, itsCenter.j-Ynew1);
00126 itsP4 = Point2D<int>(itsCenter.i-Xnew2, itsCenter.j-Ynew2);
00127
00128 itsPolygon.clear();
00129 itsPolygon.push_back(itsP1); itsPolygon.push_back(itsP2);
00130 itsPolygon.push_back(itsP3); itsPolygon.push_back(itsP4);
00131 }
00132
00133 void initIter()
00134 {
00135 itsEdgeCount = itsPolygon.size();
00136 itsNum = itsPolygon.size();
00137 itsMinY = itsPolygon[0].j;
00138 itsStartV1 = 0;
00139 for(uint c= 1; c < itsPolygon.size(); c++)
00140 {
00141 if (itsPolygon[c].j < itsMinY)
00142 {
00143 itsMinY = itsPolygon[c].j;
00144 itsStartV1 = c;
00145 }
00146 }
00147 itsStartV2 = itsStartV1;
00148 itsEndV1 = itsStartV1 - 1;
00149 if(itsEndV1 < 0) itsEndV1 = (itsNum-1);
00150
00151 itsEndV2 = itsStartV2 + 1;
00152 if (itsEndV2 >= itsNum) itsEndV2 = 0;
00153 itsMinY = itsPolygon[itsStartV1].j;
00154
00155 int x1 = itsPolygon[itsStartV1].i; int y1 = itsPolygon[itsStartV1].j;
00156 int x2 = itsPolygon[itsEndV1].i; int y2 = itsPolygon[itsEndV1].j;
00157
00158 itsDx1 = ((x2 - x1) << 8) / (y2 - y1 + 1);
00159 itsCount1 = y2-y1;
00160 itsXVal1 = x1 << 8;
00161
00162 int x11 = itsPolygon[itsStartV2].i; int y11 = itsPolygon[itsStartV2].j;
00163 int x22 = itsPolygon[itsEndV2].i; int y22 = itsPolygon[itsEndV2].j;
00164
00165 itsDx2 = ((x22 - x11) << 8) / (y22 - y11 + 1);
00166 itsCount2 = y22-y11;
00167 itsXVal2 = x11 << 8;
00168 }
00169
00170 bool iterEnd()
00171 {
00172 if (itsEdgeCount > 1)
00173 return false;
00174 else
00175 return true;
00176 }
00177
00178 void incIter(int& x1, int& x2, int& y)
00179 {
00180 if (itsEdgeCount > 1)
00181 {
00182 while( itsEdgeCount > 1 && (itsCount1 == 0 || itsCount2 == 0) )
00183 {
00184 if (itsCount1 == 0)
00185 {
00186 itsEdgeCount--;
00187 itsStartV1 = itsEndV1;
00188 itsEndV1--;
00189 if (itsEndV1 < 0) itsEndV1 = itsNum-1;
00190
00191 itsMinY = itsPolygon[itsStartV1].j;
00192 int x1 = itsPolygon[itsStartV1].i, y1 = itsPolygon[itsStartV1].j;
00193 int x2 = itsPolygon[itsEndV1].i, y2 = itsPolygon[itsEndV1].j;
00194 itsDx1 = ((x2 - x1) << 8) / (abs(y2 - y1) + 1);
00195 itsCount1 = y2-y1;
00196 itsXVal1 = x1 << 8;
00197 }
00198 if (itsCount2 == 0)
00199 {
00200 itsEdgeCount--;
00201 itsStartV2 = itsEndV2;
00202 itsEndV2++;
00203 if(itsEndV2 >= itsNum) itsEndV2 = 0;
00204 itsMinY = itsPolygon[itsStartV2].j;
00205 int x11 = itsPolygon[itsStartV2].i, y11 = itsPolygon[itsStartV2].j;
00206 int x22 = itsPolygon[itsEndV2].i, y22 = itsPolygon[itsEndV2].j;
00207 itsDx2 = ((x22 - x11) << 8) / (abs(y22 - y11) + 1);
00208 itsCount2 = y22-y11;
00209 itsXVal2 = x11 << 8;
00210 }
00211 }
00212 if ( (itsCount1 > 0) && (itsCount2 > 0) )
00213 {
00214 x1 = itsXVal1 >> 8;
00215 x2 = itsXVal2 >> 8;
00216 y = itsMinY;
00217
00218 itsXVal1 += itsDx1; itsXVal2 += itsDx2;
00219 itsCount1--; itsCount2--;
00220 itsMinY++;
00221 }
00222 }
00223
00224 }
00225
00226 std::vector<Point2D<int> > getPolygon() { return itsPolygon; }
00227
00228
00229
00230 private:
00231 Point2D<int> itsCenter;
00232 Dims itsSize;
00233 float itsOri;
00234
00235 Point2D<int> itsP1;
00236 Point2D<int> itsP2;
00237 Point2D<int> itsP3;
00238 Point2D<int> itsP4;
00239
00240
00241 int itsEdgeCount;
00242 int itsNum;
00243 int itsMinY;
00244 int itsStartV1;
00245 int itsStartV2;
00246 int itsEndV1;
00247 int itsEndV2;
00248
00249 int itsDx1;
00250 int itsCount1;
00251 int itsXVal1;
00252
00253 int itsDx2;
00254 int itsCount2;
00255 int itsXVal2;
00256
00257 std::vector<Point2D<int> > itsPolygon;
00258 };
00259
00260 class V2 : public SimModule
00261 {
00262 public:
00263
00264 struct CornerState
00265 {
00266 Point2D<float> pos;
00267 float ori;
00268 float ang;
00269 float var;
00270 float prob;
00271
00272 int lineSeg1;
00273 int lineSeg2;
00274
00275 Point2D<float> endPoint1;
00276 Point2D<float> endPoint2;
00277
00278
00279 CornerState() {}
00280 CornerState(Point2D<float> p, float o, float a) :
00281 pos(p), ori(o), ang(a)
00282 {}
00283
00284 bool operator<(const CornerState& cornerState) const
00285 {
00286 return prob < cornerState.prob;
00287 }
00288
00289 };
00290
00291 struct SymmetryState
00292 {
00293 int lineSeg1;
00294 int lineSeg2;
00295 Point2D<float> center;
00296 float ang;
00297 float length;
00298 };
00299
00300
00301
00302 struct coorlist
00303 {
00304 int x,y;
00305 struct coorlist * next;
00306 };
00307
00308
00309 struct point {int x,y;};
00310
00311
00312 struct rect
00313 {
00314 float x1,y1,x2,y2;
00315 float width;
00316 float x,y;
00317 float theta;
00318 float dx,dy;
00319 float prec;
00320 double p;
00321 float sum;
00322 };
00323
00324
00325
00326
00327
00328 typedef struct
00329 {
00330 float vx[4];
00331 float vy[4];
00332 float ys,ye;
00333 int x,y;
00334 } rect_iter;
00335
00336
00337 struct LineSegment
00338 {
00339 Point2D<float> p1;
00340 Point2D<float> p2;
00341 float width;
00342 float length;
00343 float ori;
00344 int color;
00345 Point2D<float> center;
00346 std::vector<float> side1Color;
00347 std::vector<float> side2Color;
00348 float prob;
00349
00350 float strength;
00351
00352 LineSegment(Point2D<float> inP1, Point2D<float> inP2) :
00353 p1(inP1),
00354 p2(inP2)
00355 {}
00356
00357 LineSegment() {}
00358
00359 double distance(const LineSegment &line)
00360 {
00361 return center.distance(line.center);
00362 }
00363
00364 double colorDist(const LineSegment &line)
00365 {
00366 float distColor1 = std::numeric_limits<float>::max();
00367 if (side1Color.size() == 3 && line.side1Color.size() == 3)
00368 distColor1 = sqrt( squareOf(side1Color[0] - line.side1Color[0]) +
00369 squareOf(side1Color[1] - line.side1Color[1]) +
00370 squareOf(side1Color[2] - line.side1Color[2]));
00371
00372 float distColor2 = std::numeric_limits<float>::max();
00373 if (side2Color.size() == 3 && line.side2Color.size() == 3)
00374 distColor2 = sqrt( squareOf(side2Color[0] - line.side2Color[0]) +
00375 squareOf(side2Color[1] - line.side2Color[1]) +
00376 squareOf(side2Color[2] - line.side2Color[2]));
00377
00378 return std::min(distColor2, distColor1);
00379 }
00380
00381
00382 LineSegment& operator=(const LineSegment& line)
00383 {
00384
00385 p1 = line.p1;
00386 p2 = line.p2;
00387 width = line.width;
00388 length = line.length;
00389 ori = line.ori;
00390 center = line.center;
00391 side1Color = line.side1Color;
00392 side2Color = line.side2Color;
00393
00394 return *this;
00395
00396 }
00397
00398 };
00399
00400 struct ContourState
00401 {
00402 std::vector<LineSegment> lines;
00403 };
00404
00405
00406
00407 V2(OptionManager& mgr, const std::string& descrName = "V2",
00408 const std::string& tagName = "V2");
00409
00410
00411 ~V2();
00412
00413 void init(Dims numCells);
00414
00415 void evolve(Image<PixRGB<byte> >& img);
00416 void evolve(Image<float>& img);
00417 void evolve(TensorField& tensorField);
00418 void evolve(SimEventQueue& q);
00419 void evolveLines();
00420 void evolveContours();
00421 void evolve2();
00422
00423 Layout<PixRGB<byte> > getDebugImage();
00424
00425 void findLines(const Image<float> &mag, const Image<float>& ori,
00426 Image<float>& retMag, Image<float>& retOri);
00427
00428 int findMostProbableLine(const LineSegment& line, float &prob);
00429 std::vector<LineSegment> proposeLineSegments(ImageSet<float> &LGNInput);
00430 std::vector<LineSegment> proposeLineSegments(V1::EdgesState& edgesState);
00431
00432 void trainNFA(V1::EdgesState& edgesState);
00433
00434 std::vector<ContourState> proposeContours(std::vector<LineSegment>& lines);
00435
00436
00437 std::vector<LineSegment> findNerestLines(std::list<LineSegment>& lines,
00438 std::stack<Point2D<float> >& endPoints);
00439
00440
00441 void cornerSymetryDetection(std::vector<LineSegment>& lines);
00442
00443 void evolveBorderOwner();
00444 std::vector<V2::ContourState> proposeContoursBO(std::vector<LineSegment>& lines);
00445
00446
00447 rect getRect(const Point2D<int> p1, const Point2D<int> p2,const int width);
00448
00449
00450 protected:
00451
00452 SIMCALLBACK_DECLARE(V2, SimEventV1Output);
00453
00454
00455 SIMCALLBACK_DECLARE(V2, SimEventSaveOutput);
00456
00457
00458 SIMCALLBACK_DECLARE(V2, SimEventUserInput);
00459
00460
00461 OModelParam<bool> itsShowDebug;
00462
00463
00464 OModelParam<bool> itsTrainNFA;
00465 OModelParam<std::string> itsTrainNFAFile;
00466
00467
00468 std::vector<LineSegment> itsLines;
00469 std::vector<ContourState> itsContours;
00470
00471
00472 public:
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487 Image<float> ll_angle(Image<float>& in, float threshold,
00488 std::vector<Point2D<int> > &list_p, void ** mem_p,
00489 Image<float>& modgrad, int n_bins, int max_grad );
00490 Image<float> ll_angle(const TensorField& tensorField, float threshold,
00491 std::vector<Point2D<int> > &list_p,
00492 Image<float>& modgrad, int n_bins, int max_grad );
00493
00494 #define RELATIVE_ERROR_FACTOR 100.0
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 static int double_equal(double a, double b)
00508 {
00509 double abs_diff,aa,bb,abs_max;
00510
00511
00512 if( a == b ) return true;
00513
00514 abs_diff = fabs(a-b);
00515 aa = fabs(a);
00516 bb = fabs(b);
00517 abs_max = aa > bb ? aa : bb;
00518
00519
00520
00521
00522
00523
00524 if( abs_max < DBL_MIN ) abs_max = DBL_MIN;
00525
00526
00527 return (abs_diff / abs_max) <= (RELATIVE_ERROR_FACTOR * DBL_EPSILON);
00528 }
00529
00530
00531
00532
00533
00534
00535 bool isaligned(Point2D<int> loc,const Image<float>& angles,
00536 float theta, float prec);
00537 float angle_diff(float a, float b);
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 double log_gamma_lanczos(double x);
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582 double log_gamma_windschitl(double x);
00583
00584
00585
00586
00587
00588
00589
00590 #define log_gamma(x) ((x)>15.0?log_gamma_windschitl(x):log_gamma_lanczos(x))
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603 #define TABSIZE 100000
00604 double nfa(int n, int k, double p, double logNT);
00605 void rect_copy(struct rect * in, struct rect * out);
00606 float inter_low(float x, float x1, float y1, float x2, float y2);
00607 float inter_hi(float x, float x1, float y1, float x2, float y2);
00608
00609 void ri_del(rect_iter * iter);
00610 int ri_end(rect_iter * i);
00611 void ri_inc(rect_iter * i);
00612 rect_iter * ri_ini(struct rect * r);
00613
00614 int ri_end(rect_iter& itr);
00615 void ri_inc(rect_iter& itr);
00616 void ri_ini(struct rect * r, rect_iter& iter);
00617
00618
00619 double rect_nfa(struct rect * rec, Image<float>& angles, double logNT);
00620 float get_theta( struct point * reg, int reg_size, float x, float y,
00621 Image<float>& modgrad, float reg_angle, float prec,
00622 float * elongation );
00623 float region2rect( struct point * reg, int reg_size,
00624 Image<float>& modgrad, float reg_angle,
00625 float prec, double p, struct rect * rec,
00626 float* sum_l, float* sum_w, int sum_offset, int sum_res);
00627 void region_grow(Point2D<int> loc, Image<float>& angles, struct point * reg,
00628 int * reg_size, float * reg_angle, Image<byte>& used,
00629 float prec, int radius,
00630 Image<float> modgrad, double p, int min_reg_size );
00631
00632 double rect_improve( struct rect * rec, Image<float>& angles,
00633 double logNT, double eps );
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652 std::vector<LineSegment> lineSegmentDetection(Image<float>& img,
00653 float q = 2.0, float d = 8.0, double eps = 0.0,
00654 int n_bins = 16256, int max_grad = 260100,
00655 float scale = 1.0, float sigma_scale = 0.6 );
00656
00657 std::vector<LineSegment> lineSegmentDetection(const TensorField& tensorField,
00658 float q = 2.0, float d = 20, double eps = 0.0,
00659 int n_bins = 16256, int max_grad = 260100);
00660
00661 private:
00662 ImageSet<float> itsLGNInput;
00663 std::vector<CornerState> itsCornersState;
00664 std::vector<SymmetryState> itsSymmetries;
00665 std::vector<TensorVoting> itsTensorFields;
00666 Image<float> itsEdges;
00667 Image<float> itsCornersProposal;
00668 V1::EdgesState itsV1EdgesState;
00669 bool itsLSDVerbose;
00670 TensorVoting itsLumTV;
00671 TensorVoting itsRGTV;
00672 TensorVoting itsBYTV;
00673 TensorField itsMaxTF;
00674 int itsFrameNum;
00675 std::string itsStoredFrames;
00676 float itsQuantError;
00677 float itsAngleTolerance;
00678 float itsEPS;
00679
00680 rutz::shared_ptr<WorkThreadServer> itsThreadServer;
00681 std::vector<NFAPDFMap> itsPDF;
00682 std::vector<Point2D<int> > itsLocations;
00683
00684 #ifdef HAVE_OPENCV
00685
00686 #endif
00687
00688 };
00689
00690
00691 class SimEventV2Output : public SimEvent
00692 {
00693 public:
00694 SimEventV2Output(SimModule* src,
00695 std::vector<V2::LineSegment>& lines,
00696 std::vector<V2::CornerState>& corners,
00697 Image<float>& cornersProposals,
00698 Image<float>& edges,
00699 std::vector<TensorVoting>& tensorFields,
00700 Dims dims) :
00701 SimEvent(src), itsLines(lines), itsCorners(corners),
00702 itsCornersProposals(cornersProposals), itsEdges(edges),
00703 itsTensorFields(tensorFields),
00704 itsDims(dims)
00705 {}
00706
00707 SimEventV2Output(SimModule* src,
00708 std::vector<V2::LineSegment>& lines, Dims dims) :
00709 SimEvent(src), itsLines(lines),
00710 itsCorners(std::vector<V2::CornerState>()),
00711 itsCornersProposals(Image<float>()),
00712 itsEdges(Image<float>()),
00713 itsDims(dims)
00714 {}
00715
00716 virtual ~SimEventV2Output(){}
00717 std::vector<V2::LineSegment> getLines() { return itsLines; }
00718 std::vector<V2::CornerState> getCorners() { return itsCorners; }
00719 Image<float> getCornersProposals() { return itsCornersProposals; }
00720 Image<float> getEdges() { return itsEdges; }
00721 std::vector<TensorVoting> getTensorFields() { return itsTensorFields; }
00722 Dims getDims() { return itsDims; }
00723
00724 private:
00725 const std::vector<V2::LineSegment>& itsLines;
00726 const std::vector<V2::CornerState>& itsCorners;
00727 const Image<float>& itsCornersProposals;
00728 const Image<float>& itsEdges;
00729 const std::vector<TensorVoting> itsTensorFields;
00730 const Dims itsDims;
00731
00732 };
00733
00734
00735
00736
00737
00738
00739
00740 #endif //