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 TensorVoting_C_DEFINED
00039 #define TensorVoting_C_DEFINED
00040
00041 #include "plugins/SceneUnderstanding/TensorVoting.H"
00042
00043 #include "Image/DrawOps.H"
00044 #include "Image/MathOps.H"
00045
00046 #include "Image/Kernels.H"
00047 #include "Image/FilterOps.H"
00048 #include "Image/Transforms.H"
00049 #include "Image/fancynorm.H"
00050 #include "Image/Convolutions.H"
00051 #include "Simulation/SimEventQueue.H"
00052 #include "GUI/DebugWin.H"
00053
00054 #include <math.h>
00055 #include <fcntl.h>
00056 #include <limits>
00057 #include <string>
00058
00059
00060 TensorVoting::TensorVoting() :
00061 itsSigma(2)
00062 {
00063 createTensorFields(itsSigma);
00064
00065 }
00066
00067 void TensorVoting::createTensorFields(float sigma)
00068 {
00069
00070 itsBallField = createBallTensorField(sigma);
00071
00072 itsStickFields.clear();
00073 itsStickFields.resize(180);
00074
00075 for(int i=0; i<180; i++)
00076 {
00077 float u = cos(i*M_PI/180);
00078 float v = sin(i*M_PI/180);
00079 TensorField stick = createStickTensorField(u, v, sigma);
00080 itsStickFields[i] = stick;
00081 }
00082
00083 }
00084
00085
00086 void TensorVoting::generateImage()
00087 {
00088
00089 inputImg = Image<float>(241, 521, ZEROS);
00090 for(uint i=0; i<inputImg.size(); i++)
00091 inputImg[i] = -1;
00092 inputImg.setVal(21,266,0.000000);
00093 inputImg.setVal(23,303,6.709837);
00094 inputImg.setVal(23,306,0.000000);
00095 inputImg.setVal(27,334,14.036243);
00096 inputImg.setVal(32,356,14.036243);
00097 inputImg.setVal(37,372,15.945396);
00098 inputImg.setVal(48,399,24.443954);
00099 inputImg.setVal(57,418,24.443954);
00100 inputImg.setVal(64,427,32.005383);
00101 inputImg.setVal(76,443,39.805573);
00102 inputImg.setVal(89,456,53.130100);
00103 inputImg.setVal(109,470,49.398705);
00104 inputImg.setVal(131,478,73.300758);
00105 inputImg.setVal(140,478,90.000000);
00106 inputImg.setVal(173,485,60.945396);
00107 inputImg.setVal(185,493,57.994617);
00108 inputImg.setVal(199,503,50.194427);
00109 inputImg.setVal(218,516,75.963753);
00110 inputImg.setVal(231,520,63.434948);
00111 inputImg.setVal(236,517,233.130096);
00112 inputImg.setVal(240,496,206.565048);
00113 inputImg.setVal(223,481,251.565048);
00114 inputImg.setVal(213,475,233.130096);
00115 inputImg.setVal(186,450,219.805573);
00116 inputImg.setVal(182,439,200.556046);
00117 inputImg.setVal(174,418,203.962494);
00118 inputImg.setVal(167,405,206.565048);
00119 inputImg.setVal(152,373,203.962494);
00120 inputImg.setVal(143,348,197.525574);
00121 inputImg.setVal(136,328,197.525574);
00122 inputImg.setVal(133,309,187.594650);
00123 inputImg.setVal(131,303,180.000000);
00124 inputImg.setVal(129,279,180.000000);
00125 inputImg.setVal(130,258,180.000000);
00126 inputImg.setVal(131,244,180.000000);
00127 inputImg.setVal(134,216,171.869904);
00128 inputImg.setVal(136,203,165.963760);
00129 inputImg.setVal(144,173,163.300751);
00130 inputImg.setVal(152,151,159.443954);
00131 inputImg.setVal(161,131,156.037506);
00132 inputImg.setVal(172,109,151.699249);
00133 inputImg.setVal(175,101,158.198593);
00134 inputImg.setVal(185,72,164.744888);
00135 inputImg.setVal(187,59,168.690063);
00136 inputImg.setVal(189,46,180.000000);
00137 inputImg.setVal(177,18,243.434952);
00138 inputImg.setVal(168,15,270.000000);
00139 inputImg.setVal(140,19,291.801422);
00140 inputImg.setVal(122,27,300.963745);
00141 inputImg.setVal(102,44,320.194427);
00142 inputImg.setVal(89,61,323.130096);
00143 inputImg.setVal(80,74,333.434937);
00144 inputImg.setVal(65,103,335.224854);
00145 inputImg.setVal(60,114,338.198578);
00146 inputImg.setVal(50,138,338.198578);
00147 inputImg.setVal(42,160,340.016907);
00148 inputImg.setVal(38,173,345.963745);
00149 inputImg.setVal(33,196,345.963745);
00150 inputImg.setVal(28,216,348.690063);
00151 inputImg.setVal(23,248,353.290161);
00152 inputImg.setVal(23,250,0.000000);
00153
00154
00155 }
00156
00157
00158 TensorVoting::~TensorVoting()
00159 {
00160 }
00161
00162
00163 TensorField TensorVoting::transImage(Image<float>& img)
00164 {
00165
00166 TensorField tensorField(img.getDims(), ZEROS);
00167
00168 for(int j=0; j<img.getHeight(); j++)
00169 for(int i=0; i<img.getWidth(); i++)
00170 {
00171 float val = img.getVal(i,j);
00172 if (val >= 0)
00173 {
00174 double x = cos((img.getVal(i)*M_PI/180) + (90*M_PI)/180);
00175 double y = sin((img.getVal(i)*M_PI/180) + (90*M_PI)/180);
00176
00177 tensorField.t1.setVal(img.getWidth()+1-i, j, x*x);
00178 tensorField.t2.setVal(img.getWidth()+1-i, j, x*y);
00179 tensorField.t3.setVal(img.getWidth()+1-i, j, x*y);
00180 tensorField.t4.setVal(img.getWidth()+1-i, j, y*y);
00181 }
00182 }
00183
00184 return tensorField;
00185 }
00186
00187 TensorField TensorVoting::createStickTensorField(float u, float v, float sigma)
00188 {
00189
00190
00191
00192 double ws = floor( ceil(sqrt(-log(0.01)*sigma*sigma)*2) / 2 )*2 + 1;
00193 double wHalf = (ws-1)/2;
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208 Image<float> theta((int)ws, (int)ws, ZEROS);
00209 Image<float> DF((int)ws, (int)ws, ZEROS);
00210 double norm = sqrt(u*u + v*v);
00211 double uNorm = u/norm;
00212 double vNorm = v/norm;
00213 for(int j=0; j<ws; j++)
00214 for(int i=0; i<ws; i++)
00215 {
00216 double Zj = j-wHalf;
00217 double Zi = wHalf-i;
00218 double x = vNorm*Zi + uNorm*Zj;
00219 double y = uNorm*Zi - vNorm*Zj ;
00220 double th = atan2(y,x);
00221 theta.setVal(i,j, th);
00222
00223
00224 th = fabs(th);
00225 if (th > M_PI/2)
00226 th = M_PI - th;
00227 th = 4*th;
00228
00229 double l = sqrt(x*x + y*y);
00230
00231 double s = 0;
00232 if (l != 0 && th != 0)
00233 s = (th*l)/sin(th);
00234 else if (l==0 || th == 0)
00235 s = l;
00236
00237 double k=0;
00238 if (l != 0)
00239 k = 2*sin(th)/l;
00240
00241 double c= (-16*log2(0.1)*(sigma-1))/(M_PI*M_PI);
00242 double df = exp(-((s*s+c*(k*k))/(sigma*sigma)));
00243 if (th <= M_PI/2)
00244 DF.setVal(i,j,df);
00245 }
00246
00247
00248 TensorField stickField(theta.getDims(), NO_INIT);
00249 double bTheta = atan2(v,u);
00250 for(int j=0; j<theta.getHeight(); j++)
00251 for(int i=0; i<theta.getWidth(); i++)
00252 {
00253 double th = theta.getVal(i,j);
00254 double b1 = -sin(2*th + bTheta);
00255 double b2 = cos(2*th + bTheta);
00256
00257 double att = DF.getVal(i,j);
00258 stickField.t1.setVal(i, j, b1*b1*att);
00259 stickField.t2.setVal(i, j, b1*b2*att);
00260 stickField.t3.setVal(i, j, b1*b2*att);
00261 stickField.t4.setVal(i, j, b2*b2*att);
00262 }
00263
00264 return stickField;
00265 }
00266
00267 TensorField TensorVoting::createBallTensorField(float sigma)
00268 {
00269
00270
00271 double wsize = ceil(sqrt(-log(0.01)*sigma*sigma)*2);
00272 wsize = floor(wsize/2)*2+1;
00273
00274 TensorField ballField(Dims((int)wsize, (int)wsize), ZEROS);
00275 for(float theta=0; theta < 2*M_PI; theta += (2*M_PI)/36)
00276 {
00277 float u = cos(theta); float v = sin(theta);
00278
00279 TensorField stickField = createStickTensorField(u,v,sigma);
00280 ballField += stickField;
00281 }
00282
00283
00284 ballField /= 36;
00285
00286 EigenSpace eigen = getTensorEigen(ballField);
00287
00288 return ballField;
00289
00290 }
00291
00292
00293 void TensorVoting::getBallVotes(Image<float>& img,
00294 TensorField& tensorField, float sigma)
00295 {
00296
00297
00298
00299 TensorField ballField = itsBallField;
00300
00301
00302 for(int j=0; j<img.getHeight(); j++)
00303 for(int i=0; i<img.getWidth(); i++)
00304 {
00305 float val=img.getVal(i,j);
00306
00307 if (val > 0)
00308 {
00309
00310 for(int y=0; y<ballField.t1.getHeight(); y++)
00311 for(int x=0; x<ballField.t1.getWidth(); x++)
00312 {
00313 int ii = i+x - (ballField.t1.getWidth()/2);
00314 int jj = j+y - (ballField.t1.getHeight()/2);
00315
00316 if (tensorField.t1.coordsOk(ii,jj))
00317 {
00318 tensorField.t1.setVal(ii, jj,
00319 tensorField.t1.getVal(ii,jj) +
00320 ballField.t1.getVal(x,y)*val);
00321
00322 tensorField.t2.setVal(ii, jj,
00323 tensorField.t2.getVal(ii,jj) +
00324 ballField.t2.getVal(x,y)*val);
00325
00326 tensorField.t3.setVal(ii, jj,
00327 tensorField.t3.getVal(ii,jj) +
00328 ballField.t3.getVal(x,y)*val);
00329
00330 tensorField.t4.setVal(ii, jj,
00331 tensorField.t4.getVal(ii,jj) +
00332 ballField.t4.getVal(x,y)*val);
00333 }
00334
00335 }
00336 }
00337 }
00338 }
00339
00340 TensorField TensorVoting::getStickVotes(const TensorField& tensorField,
00341 float sigma)
00342 {
00343
00344
00345
00346 EigenSpace eigen = getTensorEigen(tensorField);
00347
00348 TensorField voteField = tensorField;
00349
00350
00351 for(int j=0; j<eigen.l1.getHeight(); j++)
00352 for(int i=0; i<eigen.l1.getWidth(); i++)
00353 {
00354
00355
00356
00357 float val=eigen.l1.getVal(i,j) - eigen.l2.getVal(i,j);
00358 if (val > 0)
00359 {
00360
00361 float u = eigen.e1[1].getVal(i,j);
00362 float v = eigen.e1[0].getVal(i,j);
00363
00364
00365 int angIdx = (int)round(atan(-u/v)*180/M_PI);
00366 if (angIdx < 0) angIdx += 180;
00367
00368
00369 TensorField stickField = itsStickFields.at(angIdx);
00370
00371
00372 for(int y=0; y<stickField.t1.getHeight(); y++)
00373 for(int x=0; x<stickField.t1.getWidth(); x++)
00374 {
00375 int ii = i+x - (stickField.t1.getWidth()/2);
00376 int jj = j+y - (stickField.t1.getHeight()/2);
00377
00378 if (voteField.t1.coordsOk(ii,jj))
00379 {
00380 voteField.t1.setVal(ii, jj,
00381 voteField.t1.getVal(ii,jj) +
00382 stickField.t1.getVal(x,y)*val);
00383 voteField.t2.setVal(ii, jj,
00384 voteField.t2.getVal(ii,jj) +
00385 stickField.t2.getVal(x,y)*val);
00386 voteField.t3.setVal(ii, jj,
00387 voteField.t3.getVal(ii,jj) +
00388 stickField.t3.getVal(x,y)*val);
00389 voteField.t4.setVal(ii, jj,
00390 voteField.t4.getVal(ii,jj) +
00391 stickField.t4.getVal(x,y)*val);
00392 }
00393 }
00394 }
00395 }
00396
00397 return voteField;
00398
00399 }
00400
00401 TensorField TensorVoting::getStickVotes2(const TensorField& tensorField,
00402 float sigma)
00403 {
00404
00405 EigenSpace eigen = getTensorEigen(tensorField);
00406
00407 TensorField voteField(tensorField.t1.getDims(), ZEROS);
00408
00409
00410 for(int j=0; j<eigen.l1.getHeight(); j++)
00411 for(int i=0; i<eigen.l1.getWidth(); i++)
00412 {
00413
00414
00415
00416 float val=eigen.l1.getVal(i,j) - eigen.l2.getVal(i,j);
00417 if (val > 0)
00418 {
00419
00420 float u = eigen.e1[1].getVal(i,j);
00421 float v = eigen.e1[0].getVal(i,j);
00422
00423
00424 int angIdx = (int)round(atan(-u/v)*180/M_PI);
00425 if (angIdx < 0) angIdx += 180;
00426
00427
00428 TensorField stickField = itsStickFields.at(angIdx);
00429
00430
00431 val=1;
00432 for(int y=0; y<stickField.t1.getHeight(); y++)
00433 for(int x=0; x<stickField.t1.getWidth(); x++)
00434 {
00435 int ii = i+x - (stickField.t1.getWidth()/2);
00436 int jj = j+y - (stickField.t1.getHeight()/2);
00437
00438 if (voteField.t1.coordsOk(ii,jj))
00439 {
00440 voteField.t1.setVal(ii, jj,
00441 voteField.t1.getVal(ii,jj) +
00442 stickField.t1.getVal(x,y)*val);
00443 voteField.t2.setVal(ii, jj,
00444 voteField.t2.getVal(ii,jj) +
00445 stickField.t2.getVal(x,y)*val);
00446 voteField.t3.setVal(ii, jj,
00447 voteField.t3.getVal(ii,jj) +
00448 stickField.t3.getVal(x,y)*val);
00449 voteField.t4.setVal(ii, jj,
00450 voteField.t4.getVal(ii,jj) +
00451 stickField.t4.getVal(x,y)*val);
00452 }
00453 }
00454 }
00455 }
00456
00457 return voteField;
00458
00459 }
00460
00461 TensorField TensorVoting::calcSparseField(Image<float>& img)
00462 {
00463
00464 TensorField tensorField(img.getDims(), ZEROS);
00465
00466 for(uint i=0; i<img.size(); i++)
00467 {
00468 if (img[i] > 0)
00469 {
00470 tensorField.t1.setVal(i, 1);
00471 tensorField.t2.setVal(i, 0);
00472 tensorField.t3.setVal(i, 0);
00473 tensorField.t4.setVal(i, 1);
00474 }
00475 }
00476
00477 return tensorField;
00478
00479 }
00480
00481 TensorField TensorVoting::calcRefinedField(TensorField& tensorField,
00482 Image<float>& img,
00483 float sigma)
00484 {
00485
00486 TensorField ballVoteField = tensorField;
00487 getBallVotes(img, ballVoteField, sigma);
00488
00489
00490
00491 for(uint i=0; i<img.size(); i++)
00492 if (img[i] == 0)
00493 {
00494 ballVoteField.t1.setVal(i, 0);
00495 ballVoteField.t2.setVal(i, 0);
00496 ballVoteField.t3.setVal(i, 0);
00497 ballVoteField.t4.setVal(i, 0);
00498 }
00499
00500 return (tensorField+ballVoteField);
00501
00502 }
00503
00504 TensorField TensorVoting::findFeatures(TensorField& tensorField, float sigma)
00505 {
00506
00507 EigenSpace eigen = getTensorEigen(tensorField);
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519 TensorField sparseTf = calcSparseField(eigen.l1);
00520
00521 LINFO("Refined field");
00522 TensorField refinedTf = calcRefinedField(sparseTf, eigen.l1, sigma);
00523
00524
00525
00526
00527
00528 eigen = getTensorEigen(refinedTf);
00529
00530 eigen.l2.clear();
00531 TensorField zeroTf = getTensor(eigen);
00532
00533 LINFO("Stick Votes");
00534 tensorField = getStickVotes(zeroTf, sigma);
00535 LINFO("Done");
00536
00537 return tensorField;
00538
00539 }
00540
00541
00542 void TensorVoting::evolve()
00543 {
00544 SHOWIMG(inputImg);
00545 TensorField tensorField = transImage(inputImg);
00546
00547
00548 tensorField = findFeatures(tensorField, itsSigma);
00549
00550
00551 EigenSpace eigen = getTensorEigen(tensorField);
00552 Image<float> features = eigen.l1-eigen.l2;
00553 SHOWIMG(features);
00554
00555
00556 }
00557
00558 TensorField TensorVoting::evolve(const Image<PixRGB<byte> >& img)
00559 {
00560
00561 Image<float> lum = luminance(img);
00562 SHOWIMG(lum);
00563 TensorField tensorField = getTensor(lum);
00564
00565
00566
00567 Image<float> mag = getTensorMag(tensorField);
00568 float min, max;
00569 getMinMax(mag, min,max);
00570
00571 for(uint i=0; i<mag.size(); i++)
00572 if (mag[i] < max*0.10)
00573 tensorField.setVal(i,0);
00574
00575 tensorField = getStickVotes2(tensorField, itsSigma);
00576
00577 return tensorField;
00578
00579 }
00580
00581 TensorField TensorVoting::evolve(const TensorField& tf, bool performNonMaxSurp)
00582 {
00583 TensorField tensorField = tf;
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596 itsTensorField = getStickVotes2(tensorField, itsSigma);
00597
00598 if (performNonMaxSurp)
00599 nonMaxSurp(itsTensorField);
00600
00601
00602 return itsTensorField;
00603
00604 }
00605
00606 Image<float> TensorVoting::getTokensMag(bool normalize)
00607 {
00608 EigenSpace eigen = getTensorEigen(itsTensorField);
00609 Image<float> tokens = eigen.l1-eigen.l2;
00610
00611 if (normalize)
00612 inplaceNormalize(tokens, 0.0F, 255.0F);
00613
00614 return tokens;
00615
00616 }
00617
00618
00619
00620
00621
00622
00623
00624
00625 #endif
00626