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 #undef USE_TBB
00033
00034 #include <iostream>
00035 #include <cstdlib>
00036 #include <cstdio>
00037 #include <vector>
00038 #ifdef USE_TBB
00039 #include <tbb/tbb.h>
00040 #endif // USE_TBB
00041
00042 #include "pyra/tpimageutil.h"
00043
00044 #include "belief.h"
00045 #include "largest.h"
00046 #include "cudasegment.h"
00047 #include "fgbgsegment.h"
00048 #include "timercpu.h"
00049
00050 FgBgSegment::FgBgSegment(int w, int h, int r, float b,
00051 float w_size, float b_size)
00052 : withSurface(true)
00053 , withColors(true)
00054 , withDisparities(true)
00055 , withColorHoles(true)
00056 , uniform(false)
00057 , verbose(0)
00058 , ground(*this, w, h)
00059 , surface(*this, w, h)
00060 , hue(w, h)
00061 , saturation(w, h)
00062 , grey(w, h)
00063 , width(w)
00064 , height(h)
00065 , drange(r)
00066 , gradWeight(b)
00067 , windowSize(w_size)
00068 , ballSize(b_size)
00069 , gpuopt(true)
00070 {
00071 #ifdef USE_CUDA
00072 cudaSegment = new CudaSegment(w, h);
00073 #endif // USE_CUDA
00074 }
00075
00076 FgBgSegment::~FgBgSegment()
00077 {
00078 for (unsigned int i=0;i<figures.size();i++)
00079 delete figures[i];
00080 #ifdef USE_CUDA
00081 delete cudaSegment;
00082 #endif // USE_CUDA
00083 }
00084
00085 void FgBgSegment::UseGPU(bool gpuopt_)
00086 {
00087 gpuopt = gpuopt_;
00088 }
00089
00090 FgBgSegment::ColorModel::ColorModel(FgBgSegment &segm_) :
00091 segm(segm_), prior(NULL)
00092 {
00093 for (int i=0;i<hist_size*hist_size;i++)
00094 histogram[i] = 0.0f;
00095 }
00096
00097 FgBgSegment::ColorModel::ColorModel(const ColorModel &model) :
00098 segm(model.segm), prior(NULL)
00099 {
00100
00101 for (int i=0;i<hist_size*hist_size;i++) {
00102 histogram[i] = model.histogram[i];
00103 colorcost[i] = model.colorcost[i];
00104 }
00105 }
00106
00107 FgBgSegment::ColorModel &FgBgSegment::ColorModel::operator=(const ColorModel &model)
00108 {
00109
00110 for (int i=0;i<hist_size*hist_size;i++) {
00111 histogram[i] = model.histogram[i];
00112 colorcost[i] = model.colorcost[i];
00113 }
00114 }
00115
00116 FgBgSegment::ColorModel::~ColorModel()
00117 {
00118
00119 }
00120
00121 FgBgSegment::FlatSurface::FlatSurface(FgBgSegment &segm,
00122 int width, int height)
00123 : ColorModel(segm)
00124 , alpha(0.0f)
00125 , beta(0.0f)
00126 , disp(1000.0f)
00127 , spread_d(1.0f)
00128 , probabilities(width, height)
00129 {
00130 const int numFigures = segm.figures.size();
00131 Fill(probabilities, 1.0f/((float)numFigures+2.0f));
00132
00133 }
00134
00135 FgBgSegment::Foreground::Foreground(FgBgSegment &segm,
00136 int width, int height)
00137 : ColorModel(segm)
00138 , window_size(0.20f)
00139 , ball_size(0.20f)
00140 , combined(false)
00141 , probabilities(width, height)
00142 {
00143
00144 const int numFigures = segm.figures.size();
00145 Fill(probabilities, 1.0f/((float)numFigures+2.0f));
00146
00147 }
00148
00149 FgBgSegment::Background::Background(FgBgSegment &segm,
00150 int width, int height)
00151 : ColorModel(segm)
00152 , spread_d(16.0f)
00153 , probabilities(width, height)
00154 {
00155 const int numFigures = segm.figures.size();
00156 Fill(probabilities, 1.0f/((float)numFigures+2.0f));
00157
00158 }
00159
00160
00161
00162 void FgBgSegment::FlatSurface::Initialize()
00163 {
00164 float *dimd = segm.disparities->GetData();
00165 int drange = segm.drange;
00166 int width = segm.width;
00167 int height = segm.height;
00168
00169
00170 min_x = width;
00171 max_x = 0;
00172 min_y = height;
00173 max_y = 0;
00174
00175 float minbeta = 0.08;
00176
00177 int *hist = new int[height*drange];
00178 int *totals = new int[height];
00179 for (int y=0;y<height;y++) {
00180 int *histy = &hist[y*drange];
00181 for (int i=0;i<drange;i++)
00182 histy[i] = 0;
00183 for (int x=0;x<width;x++) {
00184 int d = (int)dimd[y*width + x];
00185 if (d>=0 && d<drange)
00186 histy[d] ++;
00187 }
00188 for (int i=0;i<drange-2;i++)
00189 histy[i] = histy[i] + 2*histy[i+1] + histy[i+2];
00190 for (int i=drange-1;i>1;i--)
00191 histy[i] = histy[i] + 2*histy[i-1] + histy[i-2];
00192 totals[y] = 0;
00193 for (int i=0;i<drange;i++)
00194 totals[y] += histy[i];
00195 }
00196
00197 float maxwei = 0.0f;
00198 alpha = 0.0f;
00199 beta = 0.0f;
00200 disp = drange/2;
00201 for (int l=0;l<1000;l++) {
00202 int idx1 = rand()%height;
00203 int idx2 = rand()%height;
00204 while (idx1==idx2)
00205 idx2 = rand()%height;
00206 if (!totals[idx1] || !totals[idx2])
00207 continue;
00208 int cnt1 = rand()%totals[idx1];
00209 int cnt2 = rand()%totals[idx2];
00210 int disp1 = 0, disp2 = 0;
00211 for (int sum1=0;sum1<cnt1;disp1++)
00212 sum1 += hist[idx1*drange+disp1];
00213 for (int sum2=0;sum2<cnt2;disp2++)
00214 sum2 += hist[idx2*drange+disp2];
00215 disp1--;
00216 disp2--;
00217 float dgra = (float)(disp2 - disp1) / (idx2 - idx1);
00218 float dzer = disp2 - dgra*idx2;
00219 float sumwei = 0.0f;
00220 for (int y=0;y<height;y++) {
00221 for (int dd=-3;dd<=3;dd++) {
00222 int d = (int)(dgra*y + dzer + 0.5f) + dd;
00223 if (d<0 || d>=drange)
00224 continue;
00225 float er = d - (dgra*y + dzer);
00226 sumwei += hist[y*drange + d] / (4.0f + er*er);
00227 }
00228 }
00229 if (sumwei>maxwei && dgra>minbeta) {
00230 maxwei = sumwei;
00231 beta = dgra;
00232 disp = dzer;
00233 }
00234 }
00235
00236
00237 for (int l=0;l<3;l++) {
00238 float syy = 0.0, sy1 = 0.0f, s11 = 0.0f;
00239 float sdy = 0.0, sd1 = 0.0f;
00240 for (int y=0;y<height;y++) {
00241 for (int dd=-3;dd<=3;dd++) {
00242 int d = (int)(beta*y + disp + 0.5f) + dd;
00243 if (d<0 || d>=drange)
00244 continue;
00245 float er = d - (beta*y + disp);
00246 float w = hist[y*drange + d] / (4.0f + er*er);
00247 syy += w*y*y;
00248 sy1 += w*y;
00249 s11 += w;
00250 sdy += w*d*y;
00251 sd1 += w*d;
00252 }
00253 }
00254 float det = syy*s11 - sy1*sy1;
00255 beta = s11*sdy - sy1*sd1;
00256 disp = syy*sd1 - sy1*sdy;
00257 if (det!=0.0f) {
00258 beta /= det;
00259 disp /= det;
00260 }
00261
00262 }
00263 disp += 0.5f;
00264
00265 for (int l=0;l<3;l++) {
00266 float sxx = 0.0, sx1 = 0.0f, s11 = 0.0f;
00267 float sdx = 0.0, sd1 = 0.0f;
00268 for (int y=0;y<height;y++) {
00269 for (int x=0;x<width;x++) {
00270 if (dimd[y*width+x]>0.0f) {
00271 float d = dimd[y*width+x] - beta*y;
00272 float er = d - (alpha*x + disp);
00273 float w = 1.0f / (1.0f + er*er);
00274 sxx += w*x*x;
00275 sx1 += w*x;
00276 s11 += w;
00277 sdx += w*d*x;
00278 sd1 += w*d;
00279 }
00280 }
00281 }
00282 float det = sxx*s11 - sx1*sx1;
00283 alpha = s11*sdx - sx1*sd1;
00284 disp = sxx*sd1 - sx1*sdx;
00285 if (det!=0.0f) {
00286 alpha /= det;
00287 disp /= det;
00288 }
00289 }
00290 int num = 0;
00291 float vard = 0.0f;
00292 for (int y=0;y<height;y++) {
00293 for (int x=0;x<width;x++) {
00294 int i = y*width + x;
00295 float d = dimd[i];
00296 if (d>=0.0f && d<drange) {
00297 float er = alpha*x + beta*y + disp - d;
00298 if (er*er<4*spread_d) {
00299
00300 if(y>max_y)
00301 max_y = y;;
00302 if(y<min_y)
00303 min_y = y;
00304
00305 if(x>max_x)
00306 max_x = x;
00307 if(x<min_x)
00308 min_x = x;
00309
00310 vard += er*er;
00311 num++;
00312 }
00313 }
00314 }
00315 }
00316 spread_d = (num ? vard/num : 1e-3);
00317 delete [] hist;
00318 delete [] totals;
00319 if (segm.verbose)
00320 std::cout << "### Flat surface: " << alpha << " " << beta << " " << disp << " " << spread_d << std::endl;
00321 }
00322
00323 void FgBgSegment::Foreground::Initialize(int startx, int starty)
00324 {
00325
00326
00327 float *dimd = segm.disparities->GetData();
00328 int drange = segm.drange;
00329 int width = segm.width;
00330 int height = segm.height;
00331
00332 int *hist1 = new int[drange];
00333 int *hist2 = new int[drange];
00334 for (int i=0;i<drange;i++)
00335 hist1[i] = hist2[i] = 0;
00336 int size = (int)(window_size*height);
00337 int miny = std::max(starty - size/2, 0);
00338 int maxy = std::min(starty + size/2, height);
00339 int minx = std::max(startx - size/2, 0);
00340 int maxx = std::min(startx + size/2, width);
00341 for (int y=miny;y<maxy;y++) {
00342 for (int x=minx;x<maxx;x++) {
00343 int i = y*width + x;
00344 if (dimd[i]>0.0f && dimd[i]<drange)
00345 hist1[(int)dimd[i]]++;
00346 }
00347 }
00348 for (int i=2;i<drange-2;i++)
00349 hist2[i] = (hist1[i-2] + hist1[i+2]) + 4*(hist1[i-1] + hist1[i+1]) + 6*hist1[i];
00350 for (int i=2;i<drange-2;i++)
00351 hist1[i] = (hist2[i-2] + hist2[i+2]) + 4*(hist2[i-1] + hist2[i+1]) + 6*hist2[i];
00352 int maxhist = 0;
00353 int d = 0;
00354 for (int i=2;i<drange-2;i++) {
00355 if (hist1[i]>maxhist) {
00356 maxhist = hist1[i];
00357 d = i;
00358 }
00359 }
00360 int meand = d;
00361 if (hist1[d+1]<hist1[d] && hist1[d-1]<hist1[d])
00362 meand += 0.5f*(hist1[d+1] - hist1[d-1]) / (2.0f*hist1[d] - hist1[d+1] - hist1[d-1]);
00363
00364 int maxd = d+1;
00365 while (maxd<drange-1 && hist1[maxd]<hist1[maxd-1])
00366 maxd++;
00367 int mind = d-1;
00368 while (mind>0 && hist1[mind]<hist1[mind+1])
00369 mind--;
00370 float d2 = 0.0f;
00371 int di = 0;
00372 for (int i=mind;i<=maxd;i++) {
00373 d2 += hist1[i]*(i-meand)*(i-meand);
00374 di += hist1[i];
00375 }
00376 float vard = d2/di + 1.0f;
00377 float stdd = sqrt(vard);
00378 std::cout << "meand: " << meand << " vard: " << vard << std::endl;
00379 delete [] hist1;
00380 delete [] hist2;
00381
00382 Image<uint8_t> region(width, height);
00383 uint8_t *regd = region.GetData();
00384 #if 1
00385 segm.MakeSegmentImage(region);
00386 for (int y=0;y<height;y++) {
00387 for (int x=0;x<width;x++) {
00388 int i = y*width + x;
00389 if (!regd[i]) {
00390 int dx = x - startx;
00391 int dy = y - starty;
00392 if (segm.withDisparities) {
00393 if ((dx*dx + dy*dy)>(height*height*ball_size*ball_size) || dimd[i]<(meand-stdd) || dimd[i]>(meand+stdd))
00394 regd[i] = 1;
00395 } else {
00396 if ((dx*dx + dy*dy)>(height*height*ball_size*ball_size))
00397 regd[i] = 1;
00398 }
00399 }
00400 }
00401 }
00402 #else
00403 for (int y=0;y<height;y++) {
00404 for (int x=0;x<width;x++) {
00405 int i = y*width + x;
00406 regd[i] = 1;
00407 if (segm.withDisparities) {
00408 int dx = x - startx;
00409 int dy = y - starty;
00410 if ((dx*dx + dy*dy)<(height*height*ball_size*ball_size)) {
00411 if (dimd[i]>0.0f && dimd[i]<drange) {
00412 float er = segm.surface.alpha*x + segm.surface.beta*y + segm.surface.disp - dimd[i];
00413 if (er*er>2*segm.surface.spread_d && dimd[i]>(meand-stdd) && dimd[i]<(meand+stdd))
00414 regd[i] = 0;
00415 }
00416 }
00417 } else {
00418 int dx = x - startx;
00419 int dy = y - starty;
00420 if ((dx*dx + dy*dy)<(height*height*ball_size*ball_size))
00421 regd[i] = 0;
00422 }
00423 }
00424 }
00425 #endif
00426
00427 int num = 0;
00428 if (combined) {
00429 Matrix3 var3d;
00430 Vector3 pos3d;
00431 float var00 = 0.0f, var01 = 0.0f, var02 = 0.0f;
00432 float var11 = 0.0f, var12 = 0.0f, var22 = 0.0f;
00433 float pos0 = 0.0f, pos1 = 0.0f, pos2 = 0.0f;
00434 for (int y=0;y<height;y++) {
00435 for (int x=0;x<width;x++) {
00436 int i = y*width + x;
00437 if (regd[i]==0) {
00438 float d = dimd[i];
00439 var00 += x*x;
00440 var01 += x*y;
00441 var02 += x*d;
00442 var11 += y*y;
00443 var12 += y*d;
00444 var22 += d*d;
00445 pos0 += x;
00446 pos1 += y;
00447 pos2 += d;
00448 num++;
00449 }
00450 }
00451 }
00452 if (num>0) {
00453 var3d(0,0) = var00;
00454 var3d(0,1) = var01;
00455 var3d(0,2) = var02;
00456 var3d(1,1) = var11;
00457 var3d(1,2) = var12;
00458 var3d(2,2) = var22;
00459 pos3d(0) = pos0;
00460 pos3d(1) = pos1;
00461 pos3d(2) = pos2;
00462 var3d *= (num>0.0f ? 1.0/num : 1.0f);
00463 pos3d *= (num>0.0f ? 1.0/num : 1.0f);
00464 var3d(0,0) -= pos3d(0)*pos3d(0);
00465 var3d(0,1) -= pos3d(0)*pos3d(1);
00466 var3d(0,2) -= pos3d(0)*pos3d(2);
00467 var3d(1,1) -= pos3d(1)*pos3d(1);
00468 var3d(1,2) -= pos3d(1)*pos3d(2);
00469 var3d(2,2) -= pos3d(2)*pos3d(2);
00470 var3d(1,0) = var3d(0,1);
00471 var3d(2,0) = var3d(0,2);
00472 var3d(2,1) = var3d(1,2);
00473 position3d = pos3d;
00474 spread3d = var3d;
00475 }
00476 } else {
00477 Matrix2 var_p;
00478 Vector2 position;
00479 float disp = 0.0f;
00480 float var_d = 0.0f;
00481 float var00 = 0.0f, var01 = 0.0f, var11 = 0.0f;
00482 float pos0 = 0.0f, pos1 = 0.0f;
00483 for (int y=0;y<height;y++) {
00484 for (int x=0;x<width;x++) {
00485 int i = y*width + x;
00486 if (regd[i]==0) {
00487 var00 += x*x;
00488 var01 += x*y;
00489 var11 += y*y;
00490 pos0 += x;
00491 pos1 += y;
00492 disp += dimd[i];
00493 var_d += dimd[i]*dimd[i];
00494 num++;
00495 }
00496 }
00497 }
00498 if (num>0) {
00499 double inum = (num>0.0 ? 1.0/num : 1.0f);
00500 var_p(0,0) = var00;
00501 var_p(0,1) = var01;
00502 var_p(1,1) = var11;
00503 position(0) = pos0;
00504 position(1) = pos1;
00505 var_p *= inum;
00506 position *= inum;
00507 var_p(0,0) -= position(0)*position(0);
00508 var_p(0,1) -= position(0)*position(1);
00509 var_p(1,1) -= position(1)*position(1);
00510 var_p(1,0) = var_p(0,1);
00511 var_d *= inum;
00512 disp *= inum;
00513 var_d -= disp*disp;
00514 position3d(0) = position(0);
00515 position3d(1) = position(1);
00516 position3d(2) = disp;
00517 spread3d.identity();
00518 spread3d(0,0) = var_p(0,0);
00519 spread3d(0,1) = var_p(0,1);
00520 spread3d(1,0) = var_p(1,0);
00521 spread3d(1,1) = var_p(1,1);
00522 spread3d(2,2) = var_d;
00523 }
00524 }
00525 if (segm.verbose) {
00526 std::cout << "### Foreground position3d: " << position3d << " " << num << std::endl;
00527 std::cout << "### Foreground spread3d: " << spread3d << std::endl;
00528 }
00529 }
00530
00531 void FgBgSegment::Foreground::SetInitParams( float l_window_size,
00532 float l_ball_size)
00533 {
00534 window_size = l_window_size;
00535 ball_size = l_ball_size;
00536 }
00537
00538
00539 void FgBgSegment::Background::Initialize()
00540 {
00541 const int numFigures = segm.figures.size();
00542 float *dimd = segm.disparities->GetData();
00543 int drange = segm.drange;
00544 int width = segm.width;
00545 int height = segm.height;
00546 float mean = 0.0f;
00547 float vari = 0.0f;
00548 int num = 0;
00549 float ivar[numFigures][6];
00550 for (int f=0;f<numFigures;f++) {
00551 Matrix3 invs = segm.figures[f]->spread3d;
00552 invs = invs.invert();
00553 ivar[f][0] = invs(0,0), ivar[f][1] = invs(0,1), ivar[f][2] = invs(1,1);
00554 ivar[f][3] = invs(0,2), ivar[f][4] = invs(1,2), ivar[f][5] = invs(2,2);
00555 }
00556 for (int y=0;y<height;y++) {
00557 for (int x=0;x<width;x++) {
00558 int i = y*width + x;
00559 if (dimd[i]>0.0f && dimd[i]<drange) {
00560 float d = dimd[i];
00561 bool used = false;
00562 for (int f=0;f<numFigures;f++) {
00563 float er_x = x - segm.figures[f]->position3d(0);
00564 float er_y = y - segm.figures[f]->position3d(1);
00565 float er_d = d - segm.figures[f]->position3d(2);
00566 float er_f = er_x*er_x*ivar[f][0] + 2*er_x*er_y*ivar[f][1] + er_y*er_y*ivar[f][2];
00567 er_f += er_d*(2*er_x*ivar[f][3] + 2*er_y*ivar[f][4] + er_d*ivar[f][5]);
00568 used |= (er_f<16.0f);
00569 }
00570 float diff = (segm.surface.alpha*x + segm.surface.beta*y + segm.surface.disp - dimd[i]);
00571 float er_s = diff*diff/segm.surface.spread_d;
00572 used |= (er_s<16.0f);
00573 if (!used) {
00574 mean += d;
00575 vari += d*d;
00576 num++;
00577 }
00578 }
00579 }
00580 }
00581 if (num>0) {
00582 mean /= num;
00583 vari /= num;
00584 disp = mean;
00585 spread_d = vari - mean*mean;
00586 } else {
00587 disp = drange/2;
00588 spread_d = disp*disp/4.0f;
00589 }
00590 if (segm.verbose)
00591 std::cout << "### Clutter spread: " << disp << " " << spread_d << std::endl;
00592 }
00593
00594 void FgBgSegment::InitSegmentation()
00595 {
00596 const int numFigures = figures.size();
00597 float *dimd = disparities->GetData();
00598 float *reg_g = ground.probabilities.GetData();
00599 float *reg_s = surface.probabilities.GetData();
00600
00601
00602
00603
00604 Fill(ground.probabilities, 1.0f/((float)numFigures+2.0f));
00605 Fill(surface.probabilities, 1.0f/((float)numFigures+2.0f));
00606
00607 float er_g = 2.0f*log((float)width*height*drange);
00608 float const_s = log(surface.spread_d) + 2.0f*log((float)width*height);
00609 float *reg_f[numFigures], const_f[numFigures], prob_f[numFigures];
00610 float ivar[numFigures][6];
00611 for (int f=0;f<numFigures;f++) {
00612
00613
00614 Fill(figures[f]->probabilities, 1.0f/((float)numFigures+2.0f));
00615
00616 reg_f[f] = figures[f]->probabilities.GetData();
00617 const_f[f] = log(figures[f]->spread3d.determinant());
00618 Matrix3 invs = figures[f]->spread3d;
00619 invs = invs.invert();
00620 ivar[f][0] = invs(0,0), ivar[f][1] = invs(0,1), ivar[f][2] = invs(1,1);
00621 ivar[f][3] = invs(0,2), ivar[f][4] = invs(1,2), ivar[f][5] = invs(2,2);
00622 }
00623 for (int y=0;y<height;y++) {
00624 for (int x=0;x<width;x++) {
00625 int i = y*width + x;
00626 float d = dimd[i];
00627 if (d>0.0f && d<drange) {
00628 float prob_g = (withSurface ? exp(-0.5f*er_g) : eps);
00629 float diff = d - (surface.alpha*x + surface.beta*y + surface.disp);
00630 float er_s = diff*diff/surface.spread_d;
00631 er_s += const_s;
00632 float prob_s = exp(-0.5f*er_s);
00633 float sumprob = prob_g + prob_s;
00634 for (int f=0;f<numFigures;f++) {
00635 float difx = x - figures[f]->position3d(0);
00636 float dify = y - figures[f]->position3d(1);
00637 float difd = d - figures[f]->position3d(2);
00638 float er_f = difx*difx*ivar[f][0] + 2*difx*dify*ivar[f][1] + dify*dify*ivar[f][2];
00639 er_f += difd*(2*difx*ivar[f][3] + 2*dify*ivar[f][4] + difd*ivar[f][5]);
00640 er_f += const_f[f];
00641 prob_f[f] = exp(-0.5f*er_f);
00642 sumprob += prob_f[f];
00643 }
00644 reg_g[i] = prob_g / sumprob;
00645 reg_s[i] = prob_s / sumprob;
00646 for (int f=0;f<numFigures;f++)
00647 reg_f[f][i] = prob_f[f] / sumprob;
00648 }
00649 }
00650 }
00651 }
00652
00653
00654
00655 void FgBgSegment::FlatSurface::Update()
00656 {
00657 float *dimd = segm.disparities->GetData();
00658 int drange = segm.drange;
00659 int width = segm.width;
00660 int height = segm.height;
00661
00662 min_x = width;
00663 max_x = 0;
00664 min_y = height;
00665 max_y = 0;
00666 float *reg_s = probabilities.GetData();
00667 float xx00 = 0.0f, xx01 = 0.0f, xx02 = 0.0f;
00668 float xx11 = 0.0f, xx12 = 0.0f, xx22 = 0.0f;
00669 float xd0 = 0.0f, xd1 = 0.0f, xd2 = 0.0f;
00670 for (int y=0;y<height;y++) {
00671 for (int x=0;x<width;x++) {
00672 int i = y*width + x;
00673 float d = dimd[i];
00674 if (d>0.0f && d<drange) {
00675 float w = reg_s[i];
00676 xx00 += x*x*w;
00677 xx01 += x*y*w;
00678 xx02 += x*w;
00679 xx11 += y*y*w;
00680 xx12 += y*w;
00681 xx22 += w;
00682 xd0 += x*d*w;
00683 xd1 += y*d*w;
00684 xd2 += d*w;
00685 }
00686 }
00687 }
00688 Matrix3 xx;
00689 Vector3 xd;
00690 xx(0,0) = xx00;
00691 xx(0,1) = xx01;
00692 xx(0,2) = xx02;
00693 xx(1,1) = xx11;
00694 xx(1,2) = xx12;
00695 xx(2,2) = xx22;
00696 xx(1,0) = xx(0,1);
00697 xx(2,0) = xx(0,2);
00698 xx(2,1) = xx(1,2);
00699 xd(0) = xd0;
00700 xd(1) = xd1;
00701 xd(2) = xd2;
00702 float num = xx(2,2);
00703 xx *= (num>0.0f ? 1.0/num : 1.0f);
00704 xd *= (num>0.0f ? 1.0/num : 1.0f);
00705 xx(0,0) += spread_d*weight_a;
00706 xx(1,1) += spread_d*weight_b;
00707 xx(2,2) += spread_d*weight_d;
00708 xd(0) += alpha * spread_d*weight_a;
00709 xd(1) += beta * spread_d*weight_b;
00710 xd(2) += disp * spread_d*weight_d;
00711 xx(0,0) += eps;
00712 xx(1,1) += eps;
00713 xx(2,2) += eps;
00714 Vector3 p = xx.invert()*xd;
00715 float sumer = 0.0f;
00716 num = 0.0f;
00717 for (int y=0;y<height;y++) {
00718 for (int x=0;x<width;x++) {
00719 int i = y*width + x;
00720 float d = dimd[i];
00721 if (d>0.0f && d<drange) {
00722 float er = alpha*x + beta*y + disp - d;
00723 float w = reg_s[i];
00724 sumer += w*er*er;
00725 num += w;
00726
00727 if (er*er<4*spread_d) {
00728 if(y>max_y)
00729 max_y = y;;
00730 if(y<min_y)
00731 min_y = y;
00732
00733 if(x>max_x)
00734 max_x = x;
00735 if(x<min_x)
00736 min_x = x;
00737 }
00738
00739 }
00740 }
00741 }
00742 alpha = p(0);
00743 beta = p(1);
00744 disp = p(2);
00745 spread_d = ((num>0.0f ? sumer/num : 1.0f) + strength*spread_d) / (1 + strength);
00746
00747
00748 if (segm.verbose)
00749 std::cout << "### Flat surface: " << alpha << " " << beta << " " << disp << " " << spread_d << std::endl;
00750 }
00751
00752 void FgBgSegment::Foreground::Update()
00753 {
00754 float *dimd = segm.disparities->GetData();
00755 int drange = segm.drange;
00756 int width = segm.width;
00757 int height = segm.height;
00758 float *reg_f = probabilities.GetData();
00759 double num = 0.0f;
00760 if (combined) {
00761 Matrix3 var3d;
00762 Vector3 pos3d;
00763 var3d = 0.0;
00764 pos3d = 0.0;
00765 for (int y=0;y<height;y++) {
00766 for (int x=0;x<width;x++) {
00767 int i = y*width + x;
00768 if (dimd[i]>0.0f && dimd[i]<drange) {
00769 float w = reg_f[i];
00770 float d = dimd[i];
00771 var3d(0,0) += x*x*w;
00772 var3d(0,1) += x*y*w;
00773 var3d(0,2) += x*d*w;
00774 var3d(1,1) += y*y*w;
00775 var3d(1,2) += y*d*w;
00776 var3d(2,2) += d*d*w;
00777 pos3d(0) += x*w;
00778 pos3d(1) += y*w;
00779 pos3d(2) += d*w;
00780 num += w;
00781 }
00782 }
00783 }
00784 if (num>0.0f) {
00785 double inum = (num>0.0f ? 1.0f/num : 1.0f);
00786 var3d *= inum;
00787 pos3d *= inum;
00788 var3d(0,0) -= pos3d(0)*pos3d(0);
00789 var3d(0,1) -= pos3d(0)*pos3d(1);
00790 var3d(0,2) -= pos3d(0)*pos3d(2);
00791 var3d(1,1) -= pos3d(1)*pos3d(1);
00792 var3d(1,2) -= pos3d(1)*pos3d(2);
00793 var3d(2,2) -= pos3d(2)*pos3d(2);
00794 var3d(1,0) = var3d(0,1);
00795 var3d(2,0) = var3d(0,2);
00796 var3d(2,1) = var3d(1,2);
00797 Matrix3 weight;
00798 weight = 0.0;
00799 weight(0,0) = weight_p;
00800 weight(1,1) = weight_p;
00801 weight(2,2) = weight_d;
00802 Matrix3 scale = spread3d*weight;
00803 scale(0,0) += 1.0;
00804 scale(1,1) += 1.0;
00805 scale(2,2) += 1.0;
00806 pos3d += spread3d*(weight*position3d);
00807 pos3d = scale.invert()*pos3d;
00808 var3d += spread3d*strength;
00809 var3d *= 1.0/(1.0 + strength) ;
00810 position3d = pos3d;
00811 spread3d = var3d;
00812 }
00813 } else {
00814 Matrix2 var_p;
00815 Vector2 position;
00816 double disp = 0.0;
00817 double var_d = 1.0;
00818 var_p = 0.0;
00819 position = 0.0;
00820 for (int y=0;y<height;y++) {
00821 for (int x=0;x<width;x++) {
00822 int i = y*width + x;
00823 if (dimd[i]>0.0f && dimd[i]<drange) {
00824 float w = reg_f[i];
00825 var_p(0,0) += x*x*w;
00826 var_p(0,1) += x*y*w;
00827 var_p(1,1) += y*y*w;
00828 position(0) += x*w;
00829 position(1) += y*w;
00830 disp += dimd[i]*w;
00831 var_d += dimd[i]*dimd[i]*w;
00832 num += w;
00833 }
00834 }
00835 }
00836 if (num>0.0f) {
00837 double inum = (num>0.0 ? 1.0/num : 1.0);
00838 var_p *= inum;
00839 position *= inum;
00840 var_p(0,0) -= position(0)*position(0);
00841 var_p(0,1) -= position(0)*position(1);
00842 var_p(1,1) -= position(1)*position(1);
00843 var_p(1,0) = var_p(0,1);
00844 Matrix2 spread_p = spread3d.submatrix(0,0);
00845 Vector2 figure_p;
00846 figure_p(0) = position3d(0);
00847 figure_p(1) = position3d(1);
00848 Matrix2 scale_p = spread_p*weight_p;
00849 scale_p(0,0) += 1.0;
00850 scale_p(1,1) += 1.0;
00851 position += ((spread_p*figure_p)*weight_p);
00852 position = scale_p.invert()*position;
00853 var_p += spread_p*strength;
00854 var_p *= 1.0/(1.0 + strength);
00855 double spread_d = spread3d(2,2);
00856 double figure_d = position3d(2);
00857 var_d *= inum;
00858 disp *= inum;
00859 var_d -= disp*disp;
00860 var_d += 1.00;
00861 disp += spread_d*weight_d*figure_d;
00862 disp /= (1.0 + spread_d*weight_d);
00863 var_d += strength*spread_d;
00864 var_d /= (1.0 + strength);
00865 position3d(0) = position(0);
00866 position3d(1) = position(1);
00867 position3d(2) = disp;
00868 spread3d.identity();
00869 spread3d(0,0) = var_p(0,0);
00870 spread3d(0,1) = var_p(0,1);
00871 spread3d(1,0) = var_p(1,0);
00872 spread3d(1,1) = var_p(1,1);
00873 spread3d(2,2) = var_d;
00874 }
00875 }
00876 if (segm.verbose) {
00877 std::cout << "### Foreground position3d: " << position3d << " " << num << std::endl;
00878 std::cout << "### Foreground spread3d: " << spread3d << std::endl;
00879 }
00880 }
00881
00882 void FgBgSegment::Background::Update()
00883 {
00884 float *reg_g = probabilities.GetData();
00885 float *dimd = segm.disparities->GetData();
00886 int drange = segm.drange;
00887 int width = segm.width;
00888 int height = segm.height;
00889 float mean = 0.0f;
00890 float vari = 0.0f;
00891 float num = 0.0f;
00892 for (int y=0;y<height;y++) {
00893 for (int x=0;x<width;x++) {
00894 int i = y*width + x;
00895 if (dimd[i]>0.0f && dimd[i]<drange) {
00896 float w = reg_g[i];
00897 mean += dimd[i]*w;
00898 vari += dimd[i]*dimd[i]*w;
00899 num += w;
00900 }
00901 }
00902 }
00903 if (num>0) {
00904 mean /= num;
00905 vari /= num;
00906 vari -= mean*mean;
00907 mean += spread_d*weight_d*disp;
00908 mean /= (1.0f + spread_d*weight_d);
00909 vari += strength*spread_d;
00910 vari /= (1.0f + strength);
00911 disp = mean;
00912 spread_d = vari;
00913 }
00914 if (segm.verbose)
00915 std::cout << "### Clutter spread: " << disp << " " << spread_d << std::endl;
00916 }
00917
00918 float FgBgSegment::ColorModel::CreateHistogram( Image<float> &probabilities,
00919 bool allPoints)
00920 {
00921 int count = 0;
00922
00923 float *reg_g = probabilities.GetData();
00924 float *dimd = segm.disparities->GetData();
00925 int drange = segm.drange;
00926 int width = segm.width;
00927 int height = segm.height;
00928 uint8_t *himd = segm.hue.GetData();
00929 uint8_t *simd = segm.saturation.GetData();
00930 uint8_t *gimd = segm.grey.GetData();
00931 float hist[hist_size*hist_size];
00932 float grey[hist_size];
00933
00934 for (int i=0;i<hist_size*hist_size;i++)
00935 hist[i] = 0.0f;
00936
00937 for (int i=0;i<hist_size;i++)
00938 grey[i] = 0.0f;
00939
00940 float sumProb = 0.0f;
00941 for (int i=0;i<width*height;i++) {
00942 float prob = reg_g[i];
00943 sumProb += prob;
00944 if (allPoints || (dimd[i]>0.0f && dimd[i]<drange)) {
00945 if(!segm.withColorHoles || (dimd[i]>0.0f && dimd[i]<drange)){
00946 int ix = hist_size*himd[i]/256;
00947 int iy = hist_size*simd[i]/256;
00948 int idx = iy*hist_size + ix;
00949 hist[idx] += prob;
00950 } else if(!segm.uniform){
00951 ROS_ASSERT(!(dimd[i]>0.0f && dimd[i]<drange));
00952 int g = hist_size*gimd[i]/256;
00953 grey[g] += prob;
00954 count ++;
00955 }
00956 }
00957 }
00958
00959 ROS_DEBUG("%d pixels with invalid colour information in histogram creation", count);
00960
00961 float *phist = NULL;
00962 if (prior!=NULL)
00963 phist = prior->histogram;
00964
00965 SmoothAndNormalizeHist( hist, phist, hist_size*hist_size,
00966 histogram, colorcost);
00967 if(!segm.uniform) {
00968 if (prior!=NULL)
00969 phist = prior->greyhist;
00970 else
00971 phist = NULL;
00972 SmoothAndNormalizeHist( grey, phist, hist_size, greyhist, greycost);
00973 }
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999 return sumProb;
01000 }
01001
01002 void FgBgSegment::ColorModel::SmoothAndNormalizeHist( float const* hist,
01003 float const* phist,
01004 int size,
01005 float* const histogram,
01006 float* const cost)
01007 {
01008
01009 float fac_old = 1.0f / ColorModel::weight;
01010 float fac_pri = 4.0f*fac_old;
01011 float num = 0.0f;
01012 for (int i=0;i<size;i++)
01013 num += hist[i];
01014 float inum = (num>0.0f ? 1.0/num : 1.0);
01015 if (phist!=NULL) {
01016
01017
01018 for (int i=0;i<size;i++)
01019 histogram[i] = (hist[i]*inum + fac_old*histogram[i]
01020 + fac_pri*phist[i])/(1.0f + fac_old + fac_pri);
01021 } else {
01022 for (int i=0;i<size;i++)
01023 histogram[i] = (hist[i]*inum
01024 + fac_old*histogram[i])/(1.0f + fac_old);
01025 }
01026
01027 NormalizeHist(histogram, cost, size);
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039 }
01040
01041 void FgBgSegment::ColorModel::NormalizeHist( float* const histogram,
01042 float* const cost,
01043 int size)
01044 {
01045 float num = 0.0f;
01046 for (int i=0;i<size;i++)
01047 num += histogram[i];
01048 float inum = (num>0.0f ? 1.0/num : 1.0);
01049 for (int i=0;i<size;i++) {
01050 histogram[i] *= inum;
01051 cost[i] = -2.0f*log(std::max(histogram[i], eps/(float)size));
01052 }
01053 }
01054
01055 void FgBgSegment::ColorModel::CreateHistogram(Image<uint8_t> &mask,
01056 bool allPoints)
01057 {
01058 int count = 0;
01059
01060 uint8_t *masd = mask.GetData();
01061 float *dimd = segm.disparities->GetData();
01062 uint8_t *himd = segm.hue.GetData();
01063 uint8_t *simd = segm.saturation.GetData();
01064 uint8_t *gimd = segm.grey.GetData();
01065 int width = segm.width;
01066 int height = segm.height;
01067
01068 for (int i=0;i<hist_size*hist_size;i++)
01069 histogram[i] = 0.0f;
01070
01071 if(!segm.uniform)
01072 for (int i=0;i<hist_size;i++)
01073 greyhist[i] = 0.0f;
01074
01075 int num = 0;
01076 for (int i=0;i<width*height;i++) {
01077 if (masd[i]>0) {
01078 if (allPoints || (dimd[i]>0.0f && dimd[i]<segm.drange)) {
01079 if(!segm.withColorHoles ||
01080 (dimd[i]>0.0f && dimd[i]<segm.drange)){
01081 int ix = hist_size*himd[i]/256;
01082 int iy = hist_size*simd[i]/256;
01083 int idx = iy*hist_size + ix;
01084 histogram[idx] ++;
01085 num ++;
01086 } else if(!segm.uniform){
01087 ROS_ASSERT(!(dimd[i]>0.0f && dimd[i]<segm.drange));
01088 int g = hist_size*gimd[i]/256;
01089 greyhist[g] ++;
01090 count++;
01091 }
01092 }
01093 }
01094 }
01095
01096 ROS_DEBUG("%d Pixels used for creating the histogram with mask", count);
01097
01098 NormalizeHist(histogram, colorcost, hist_size*hist_size);
01099 if(!segm.uniform)
01100 NormalizeHist(greyhist, greycost, hist_size);
01101
01102
01103
01104
01105
01106
01107
01108 }
01109
01110 void FgBgSegment::CreateHistograms(bool allPoints)
01111 {
01112 ground.CreateHistogram(ground.probabilities, allPoints);
01113 surface.CreateHistogram(surface.probabilities, allPoints);
01114 for (unsigned int f=0;f<figures.size();f++)
01115 figures[f]->CreateHistogram(figures[f]->probabilities, allPoints);
01116 }
01117
01118 void FgBgSegment::SetNewForeground(int startx, int starty,
01119 Image<float> &dimg, int drange_)
01120 {
01121 Foreground *model = new Foreground(*this, width, height);
01122 model->SetInitParams( windowSize, ballSize);
01123 figures.push_back(model);
01124 model->Initialize(startx, starty);
01125 Image<float> probs(width, height);
01126 float *prod = probs.GetData();
01127 float ivar[6];
01128 Matrix3 invs = model->spread3d;
01129 if (invs.determinant()!=0.0)
01130 invs = invs.invert();
01131 ivar[0] = invs(0,0), ivar[1] = invs(0,1), ivar[2] = invs(1,1);
01132 ivar[3] = invs(0,2), ivar[4] = invs(1,2), ivar[5] = invs(2,2);
01133 Image<uint8_t> mask(width, height);
01134 MakeSegmentImage(mask);
01135 uint8_t *masd = mask.GetData();
01136 float *dimd = dimg.GetData();
01137 for (int y=0;y<height;y++) {
01138 for (int x=0;x<width;x++) {
01139 int i = y*width + x;
01140 if (!masd[i]) {
01141 float d = dimd[i];
01142 float er_x = x - model->position3d(0);
01143 float er_y = y - model->position3d(1);
01144 float er_d = d - model->position3d(2);
01145 float er_f = er_x*er_x*ivar[0] + 2*er_x*er_y*ivar[1] + er_y*er_y*ivar[2];
01146 if (dimd[i]>0.0f && dimd[i]<drange_)
01147 er_f += er_d*(2*er_x*ivar[3] + 2*er_y*ivar[4] + er_d*ivar[5]);
01148 prod[y*width + x] = exp(-0.5f*er_f);
01149 } else
01150 prod[y*width + x] = 0.0f;
01151 }
01152 }
01153 model->CreateHistogram(probs, true);
01154 }
01155
01156 void FgBgSegment::SetNewForeground(Image<uint8_t> &mask,
01157 Image<float> &dimg,
01158 int drange_, bool reuseLast)
01159 {
01160 if (!reuseLast)
01161 figures.push_back(new Foreground(*this, width, height));
01162 Foreground &fig = *figures.back();
01163 uint8_t *masd = mask.GetData();
01164 float *dimd = dimg.GetData();
01165 Matrix2 var_p;
01166 Vector2 position;
01167 double disp = 0.0;
01168 double var_d = 1.0;
01169 double num = 0.0, numd = 0.0;
01170 var_p = 0.0;
01171 position = 0.0;
01172 for (int y=0;y<height;y++) {
01173 for (int x=0;x<width;x++) {
01174 int i = y*width + x;
01175 if (masd[i]>0) {
01176 var_p(0,0) += x*x;
01177 var_p(0,1) += x*y;
01178 var_p(1,1) += y*y;
01179 position(0) += x;
01180 position(1) += y;
01181 num += 1.0;
01182 float d = dimd[i];
01183 if (d>0.0 && d<drange_) {
01184 disp += d;
01185 var_d += d*d;
01186 numd += 1.0;
01187 }
01188 }
01189 }
01190 }
01191 if (num>0.0) {
01192 double inum = (num>0.0 ? 1.0/num : 1.0);
01193 var_p *= inum;
01194 position *= inum;
01195 var_p(0,0) -= position(0)*position(0);
01196 var_p(0,1) -= position(0)*position(1);
01197 var_p(1,1) -= position(1)*position(1);
01198 var_p(1,0) = var_p(0,1);
01199 inum = (numd>0.0 ? 1.0/numd : 1.0);
01200 var_d *= inum;
01201 disp *= inum;
01202 var_d -= disp*disp;
01203 fig.position3d(0) = position(0);
01204 fig.position3d(1) = position(1);
01205 fig.position3d(2) = disp;
01206 fig.spread3d.identity();
01207 fig.spread3d(0,0) = var_p(0,0);
01208 fig.spread3d(0,1) = var_p(0,1);
01209 fig.spread3d(1,0) = var_p(1,0);
01210 fig.spread3d(1,1) = var_p(1,1);
01211 fig.spread3d(2,2) = var_d;
01212 }
01213 if (figures.size()<=colorPriors.size()) {
01214 ColorModel &prior = colorPriors[figures.size()-1];
01215 for (int i=0;i<hist_size*hist_size;i++) {
01216 fig.histogram[i] = prior.histogram[i];
01217 fig.colorcost[i] = prior.colorcost[i];
01218 }
01219 fig.prior = &prior;
01220 } else
01221 fig.CreateHistogram(mask, true);
01222 if (verbose){
01223 std::cout << "Figure position: " << fig.position3d << std::endl;
01224 std::cout << "Figure spread: " << std::endl << fig.spread3d << std::endl;
01225 std::cout << "Foregrounds: " << figures.size() << " Priors: " << colorPriors.size() << std::endl;
01226 }
01227 }
01228
01229 template <int numFigures>
01230 void FgBgSegment::PixSegment(FgBgSegment &segm)
01231 {
01232 int width = segm.width;
01233 int height = segm.height;
01234 int drange = segm.drange;
01235 float *dimd = segm.disparities->GetData();
01236 uint8_t *himd = segm.hue.GetData();
01237 uint8_t *simd = segm.saturation.GetData();
01238 uint8_t *gimd = segm.grey.GetData();
01239
01240 Fill(segm.ground.probabilities, 1.0f/((float)numFigures+2.0f));
01241 Fill(segm.surface.probabilities, 1.0f/((float)numFigures+2.0f));
01242
01243
01244
01245
01246 float const_sd = log(segm.surface.spread_d);
01247 float const_sp = 2.0f*log((float)width*height/1);
01248 float const_s0 = -2.0*log(0.45f);
01249 float const_su = -2.0*log(0.40f);
01250 float const_gd = 2.0f*log((float)drange/2);
01251 float const_gp = 2.0f*log((float)width*height/1);
01252 float const_g0 = -2.0*log(0.45f);
01253 float const_gu = -2.0*log(0.40f);
01254
01255 float const_fd[numFigures], const_fp[numFigures];
01256 float const_f0 = -2.0*log(0.10f);
01257 float const_fu = -2.0*log(0.20f);
01258 float ivar[numFigures][6];
01259 for (int f=0;f<numFigures;f++) {
01260
01261
01262 Fill(segm.figures[f]->probabilities, 1.0f/((float)numFigures+2.0f));
01263
01264 const_fd[f] = log(segm.figures[f]->spread3d(2,2));
01265 const_fp[f] = log(segm.figures[f]->spread3d.determinant()) - const_fd[f];
01266 Matrix3 invs = segm.figures[f]->spread3d;
01267 invs = invs.invert();
01268 ivar[f][0] = invs(0,0), ivar[f][1] = invs(0,1), ivar[f][2] = invs(1,1);
01269 ivar[f][3] = invs(0,2), ivar[f][4] = invs(1,2), ivar[f][5] = invs(2,2);
01270 }
01271
01272 BeliefProp<numFigures+2> belief(width, height);
01273 belief.SetGradientCosts(segm.grey, segm.gradWeight);
01274 float **priors = belief.GetPriors();
01275
01276 for (int y=0;y<height;y++) {
01277 for (int x=0;x<width;x++) {
01278 int i = y*width + x;
01279 int ix = hist_size*himd[i]/256;
01280 int iy = hist_size*simd[i]/256;
01281 int idx = iy*hist_size + ix;
01282 for (int f=0;f<numFigures;f++) {
01283 float er_f = const_f0;
01284 float difx = x - segm.figures[f]->position3d(0);
01285 float dify = y - segm.figures[f]->position3d(1);
01286 float difp = difx*difx*ivar[f][0] + 2*difx*dify*ivar[f][1] + dify*dify*ivar[f][2];
01287 er_f += const_fp[f] + (difp<9.0f ? difp : 100.0f);
01288 if (segm.withDisparities) {
01289 float dcostf = const_fu;
01290 if (dimd[i]>0.0f && dimd[i]<drange) {
01291 float difd = dimd[i] - segm.figures[f]->position3d(2);
01292 dcostf = difd*(2*difx*ivar[f][3] + 2*dify*ivar[f][4] + difd*ivar[f][5]) + const_fd[f];
01293 }
01294 er_f += dcostf;
01295 }
01296 if (segm.withColors && !segm.withColorHoles) {
01297 er_f += segm.figures[f]->colorcost[idx];
01298 } else if(segm.withColors && segm.withColorHoles){
01299
01300
01301 if(!(dimd[i]>0.0f && dimd[i]<drange)){
01302 if(segm.uniform){
01303
01304 float norm = numFigures+2.0f;
01305 er_f += -2.0f*log(1.0f/norm);
01306
01307 } else {
01308
01309 int idx = hist_size*gimd[i]/256;
01310 er_f += segm.figures[f]->greycost[idx];
01311
01312 }
01313 } else {
01314 er_f += segm.figures[f]->colorcost[idx];
01315 }
01316 }
01317 priors[2+f][i] = 0.5f*er_f;
01318 }
01319 float er_g = const_g0;
01320 float er_s = const_s0;
01321 er_g += const_gp;
01322 er_s += const_sp;
01323 if (segm.withDisparities) {
01324 float dcosts = const_su;
01325 float dcostg = const_gu;
01326 if (dimd[i]>0.0f && dimd[i]<drange) {
01327 float diff = dimd[i] - (segm.surface.alpha*x
01328 + segm.surface.beta*y
01329 + segm.surface.disp);
01330 dcosts = diff*diff/segm.surface.spread_d + const_sd;
01331 dcostg = const_gd;
01332 }
01333 er_s += dcosts;
01334 er_g += dcostg;
01335 }
01336 if (segm.withColors && !segm.withColorHoles) {
01337 er_g += segm.ground.colorcost[idx];
01338 er_s += segm.surface.colorcost[idx];
01339 } else if(segm.withColors && segm.withColorHoles){
01340
01341
01342 if (!(dimd[i]>0.0f && dimd[i]<drange)){
01343 if(segm.uniform){
01344
01345 float norm = numFigures+2.0f;
01346 er_g += -2.0f*log(1.0f/norm);
01347 er_s += -2.0f*log(1.0f/norm);
01348
01349 } else {
01350
01351 int idx = hist_size*gimd[i]/256;
01352 er_g += segm.ground.greycost[idx];
01353 er_s += segm.surface.greycost[idx];
01354
01355 }
01356
01357 } else {
01358 er_g += segm.ground.colorcost[idx];
01359 er_s += segm.surface.colorcost[idx];
01360 }
01361 }
01362
01363 priors[0][i] = 0.5f*er_g;
01364 priors[1][i] = 0.5f*er_s;
01365 }
01366 }
01367
01368 float **beliefs = belief.GetBeliefs();
01369 TimerCPU timer(2800);
01370
01371 belief.Execute(5, 3);
01372 std::cout << "Belief: " << timer.read() << " ms" << std::endl;
01373
01374 float *reg_g = segm.ground.probabilities.GetData();
01375 float *reg_s = segm.surface.probabilities.GetData();
01376 float *reg_f[numFigures];
01377 float prob_f[numFigures];
01378 for (int f=0;f<numFigures;f++)
01379 reg_f[f] = segm.figures[f]->probabilities.GetData();
01380 for (int i=0;i<width*height;i++) {
01381 float minbelief = (beliefs[0][i]<beliefs[1][i] ? beliefs[0][i] : beliefs[1][i]);
01382 for (int f=0;f<numFigures;f++)
01383 minbelief = (beliefs[2+f][i]<minbelief ? beliefs[2+f][i] : minbelief);
01384 float prob_g = exp(minbelief - beliefs[0][i]) + eps;
01385 float prob_s = exp(minbelief - beliefs[1][i]) + eps;
01386 float sumprob = prob_g + prob_s;
01387 for (int f=0;f<numFigures;f++) {
01388 prob_f[f] = exp(minbelief - beliefs[2+f][i]) + eps;
01389 sumprob += prob_f[f];
01390 }
01391 reg_g[i] = prob_g / sumprob;
01392 reg_s[i] = prob_s / sumprob;
01393 for (int f=0;f<numFigures;f++)
01394 reg_f[f][i] = prob_f[f] / sumprob;
01395 }
01396 if (segm.verbose>1) {
01397 Image<unsigned char> mask(width, height);
01398 segm.MakeSegmentImage(mask);
01399 mask.Store("mask.pgm", true, false);
01400 if (numFigures) {
01401 Image<float>(width, height, reg_g).Store("probsg.pgm", true, false);
01402 Image<float>(width, height, reg_s).Store("probss.pgm", true, false);
01403 Image<float>(width, height, reg_f[0]).Store("probsf1.pgm", true, false);
01404 }
01405 }
01406 }
01407
01408 void FgBgSegment::RGBToHSV(Image<uint8_t> &cimg)
01409 {
01410 uint8_t *srcd = cimg.GetData();
01411 uint8_t *himd = hue.GetData();
01412 uint8_t *simd = saturation.GetData();
01413 uint8_t *vimd = grey.GetData();
01414 for (int i=0;i<width*height;i++) {
01415 short r = srcd[3*i+0];
01416 short g = srcd[3*i+1];
01417 short b = srcd[3*i+2];
01418 int minv = (r<g ? r : g);
01419 minv = (b<minv ? b : minv);
01420 int maxv = (r>g ? r : g);
01421 maxv = (b>maxv ? b : maxv);
01422 int diff = maxv - minv;
01423 int dif6 = diff*6;
01424 if (diff==0)
01425 himd[i] = 0;
01426 else if (maxv==r) {
01427 himd[i] = (1536*diff + 256*(g - b))/dif6 & 255;
01428 } else if (maxv==g)
01429 himd[i] = (512*diff + 256*(b - r))/dif6;
01430 else
01431 himd[i] = (1024*diff + 256*(r - g))/dif6;
01432 if (maxv==0)
01433 simd[i] = 0;
01434 else
01435 simd[i] = 255*(maxv - minv)/maxv;
01436 vimd[i] = maxv;
01437 }
01438 }
01439
01440 void FgBgSegment::GetSurfaceParameters( float &alpha,
01441 float &beta,
01442 float &disp)
01443 {
01444 alpha = surface.alpha;
01445 beta = surface.beta;
01446 disp = surface.disp;
01447
01448 }
01449
01450
01451 void FgBgSegment::GetSurfaceMinMax( float &min_x,
01452 float &min_y,
01453 float &max_x,
01454 float &max_y )
01455 {
01456 min_x = surface.min_x;
01457 min_y = surface.min_y;
01458 max_x = surface.max_x;
01459 max_y = surface.max_y;
01460 }
01461
01462
01463 void FgBgSegment::SetWithColors( bool val)
01464 {
01465 withColors = val;
01466 }
01467
01468 bool FgBgSegment::GetWithColors(){ return withColors; }
01469
01470 void FgBgSegment::SetWithColorHoles( bool val)
01471 {
01472 withColorHoles = val;
01473 }
01474
01475 bool FgBgSegment::GetWithColorHoles(){ return withColorHoles;}
01476
01477 void FgBgSegment::SetUniform( bool val)
01478 {
01479 uniform = val;
01480 }
01481
01482 bool FgBgSegment::GetUniform(){ return uniform;}
01483
01484 void FgBgSegment::SetWithSurface( bool val)
01485 {
01486 withSurface = val;
01487 }
01488
01489 bool FgBgSegment::GetWithSurface(){ return withSurface;}
01490
01491 void FgBgSegment::SetWithDisparities( bool val)
01492 {
01493 withDisparities = val;
01494 }
01495
01496 bool FgBgSegment::GetWithDisparities(){return withDisparities;}
01497
01498 void FgBgSegment::SetGradWeight( float val)
01499 {
01500 gradWeight = val;
01501 }
01502
01503 float FgBgSegment::GetGradWeight() {return gradWeight;}
01504
01505 void FgBgSegment::MakeSegmentImage(Image<uint8_t> &image)
01506 {
01507 const int numFigures = figures.size();
01508 assert(image.GetWidth()==width && image.GetHeight()==height);
01509 float *reg_g = ground.probabilities.GetData();
01510 float *reg_s = surface.probabilities.GetData();
01511 float *reg_f[numFigures];
01512 uint8_t *imgd = image.GetData();
01513 for (int f=0;f<numFigures;f++)
01514 reg_f[f] = figures[f]->probabilities.GetData();
01515 for (int i=0;i<width*height;i++) {
01516 float maxprob = reg_g[i];
01517 uint8_t col = 0;
01518 if (reg_s[i]>maxprob) {
01519 maxprob = reg_s[i];
01520 col = 1;
01521 }
01522 for (int f=0;f<numFigures;f++) {
01523 if (reg_f[f][i]>maxprob) {
01524 maxprob = reg_f[f][i];
01525 col = f + 2;
01526 }
01527 }
01528 imgd[i] = col;
01529 }
01530 }
01531
01532 void FgBgSegment::MakeMaskImage(Image<uint8_t> &image, int val, int obj)
01533 {
01534 const int numFigures = figures.size();
01535 assert(image.GetWidth()==width && image.GetHeight()==height);
01536 float *reg_g = ground.probabilities.GetData();
01537 float *reg_s = surface.probabilities.GetData();
01538 float *reg_f[numFigures];
01539 obj = std::min(numFigures-1, obj);
01540 uint8_t *imgd = image.GetData();
01541 for (int f=0;f<numFigures;f++)
01542 reg_f[f] = figures[f]->probabilities.GetData();
01543 for (int i=0;i<width*height;i++) {
01544 float maxprob = std::max(reg_g[i], reg_s[i]);
01545 for (int f=0;f<numFigures;f++)
01546 maxprob = std::max(maxprob, reg_f[f][i]);
01547 imgd[i] = (reg_f[obj][i]==maxprob ? val : 0);
01548 }
01549 }
01550
01551 void FgBgSegment::MakeBorderImage(Image<uint8_t> &image)
01552 {
01553 Image<uint8_t> segm(width, height);
01554 uint8_t *segd = segm.GetData();
01555 MakeMaskImage(segm, 1);
01556 FillHoles(segm);
01557 KeepLargestSegment(segm, 1, 0, 1000);
01558 uint8_t *imgd = image.GetData();
01559 for (int i=0;i<3*width*height;i++)
01560 imgd[i] = 160*imgd[i]/256;
01561 for (int y=2;y<height-2;y++) {
01562 for (int x=2;x<width-2;x++) {
01563 int p = y*width + x;
01564 int sum = segd[p] + segd[p+1] + segd[p-1] + segd[p+1+width] + segd[p-1+width] +
01565 segd[p+width] + segd[p-width] + segd[p+1-width] + segd[p-1-width] +
01566 segd[p+2*width] + segd[p-2*width] + segd[p+2] + segd[p-2];
01567 if (sum>0 && sum<13)
01568 imgd[3*p+0] = imgd[3*p+1] = imgd[3*p+2] = 255;
01569 }
01570 }
01571 }
01572
01574 class ModelWorker {
01576 FgBgSegment::ColorModel &model;
01578 Image<float> &probs;
01580 float &sumProb;
01581 public:
01583
01587 ModelWorker(FgBgSegment::ColorModel &m,
01588 Image<float> &p, float &s) :
01589 model(m), probs(p), sumProb(s) { }
01591 void operator()() {
01592 model.Update();
01593 sumProb = model.CreateHistogram(probs, true);
01594 }
01596 void runModel() {
01597 model.Update();
01598 sumProb = model.CreateHistogram(probs, true);
01599 }
01600 };
01601
01602
01603 void FgBgSegment::Execute(Image<uint8_t> &image,
01604 Image<float> &disp,
01605 bool initialize, int loops, int startx, int starty)
01606 {
01607 bool cudaopt = gpuopt;
01608 typedef void(*func)(FgBgSegment&);
01609 static const func PixSegment[7] = { &FgBgSegment::PixSegment<0>,
01610 &FgBgSegment::PixSegment<1>,
01611 &FgBgSegment::PixSegment<2>,
01612 &FgBgSegment::PixSegment<3>,
01613 &FgBgSegment::PixSegment<4>,
01614 &FgBgSegment::PixSegment<5>,
01615 &FgBgSegment::PixSegment<6>};
01616 disparities = &disp;
01617 RGBToHSV(image);
01618
01619 for (int i=0;i<loops;i++) {
01620
01621 if (initialize) {
01622 colorPriors.clear();
01623 for (int i=0;i<(int)figures.size();i++) {
01624 colorPriors.push_back(*figures[i]);
01625 delete figures[i];
01626 }
01627 figures.clear();
01628 if (withSurface)
01629 surface.Initialize();
01630 ground.Initialize();
01631 InitSegmentation();
01632 CreateHistograms(false);
01633 }
01634
01635 int nFigures = figures.size();
01636 if (cudaopt)
01637 #ifdef USE_CUDA
01638 cudaSegment->Execute(*this, image, disp, nFigures, i==0);
01639 #else
01640 std::cout << "Cuda not available!"<< std::endl;
01641 #endif //USE_CUDA
01642 else
01643 PixSegment[nFigures](*this);
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664 #ifdef USE_TBB
01665 tbb::task_group g;
01666 #endif // USE_TBB
01667
01668 std::vector<ModelWorker*> workers;
01669 float sumProbs[8];
01670 if (withSurface)
01671 workers.push_back(new ModelWorker(surface,
01672 surface.probabilities,
01673 sumProbs[1]));
01674
01675 for (int i=0;i<nFigures;i++)
01676 workers.push_back(new ModelWorker(*figures[i],
01677 figures[i]->probabilities,
01678 sumProbs[i+2]));
01679
01680 for (int i=0;i<(int)workers.size();i++){
01681 #ifdef USE_TBB
01682 g.run(*workers[i]);
01683 #else
01684 workers[i]->runModel();
01685 #endif // USE_TBB
01686 }
01687
01688 ground.Update();
01689 sumProbs[0] = ground.CreateHistogram(ground.probabilities, true);
01690
01691 #ifdef USE_TBB
01692 g.wait();
01693 #endif // USE_TBB
01694
01695 for (int i=0;i<(int)workers.size();i++)
01696 delete workers[i];
01697
01698 if (verbose>1) {
01699 std::cout << "SumProbs: ";
01700 for (int i=0;i<(int)figures.size()+2;i++)
01701 std::cout << (int)sumProbs[i] << " ";
01702 std::cout << std::endl;
01703 }
01704 initialize = false;
01705 }
01706
01707 if (verbose || true)
01708 std::cout << "Surface spread: " << surface.spread_d << std::endl;
01709
01710 }