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