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