Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
MixtureOfGaussians.cpp
1 /*
2 This file is part of the BIAS library (Basic ImageAlgorithmS).
3 
4 Copyright (C) 2003-2009 (see file CONTACT for details)
5 Multimediale Systeme der Informationsverarbeitung
6 Institut fuer Informatik
7 Christian-Albrechts-Universitaet Kiel
8 
9 
10 BIAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14 
15 BIAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with BIAS; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24 
25 
26 
27 #include "Image/MixtureOfGaussians.hh"
28 #include <Base/Image/ImageConvert.hh>
29 #include <Base/ImageUtils/ImageDraw.hh>
30 #include <Base/Image/ROI.hh>
31 #include <bias_config.h>
32 #include <Base/Image/ImageIO.hh>
33 #include <Base/Common/FileHandling.hh>
34 #include <Filter/Erosion.hh>
35 #include <Base/Debug/TimeMeasure.hh>
36 
37 using namespace BIAS;
38 using namespace std;
39 // public
40 
41 template <class StorageType>
43 MixtureOfGaussians(const unsigned int numDistributions,
44  const unsigned int sizeWindow,
45  const float updateFactor,
46  const MoGColorModel colorModel) {
47  dDistributions_ = numDistributions;
48  dWindow_ = sizeWindow /2;
49  bInited_ = false;
50  fUpdateFactor_ = updateFactor;
51  dMaxWeight_ = 50;
52  dMinWeight_ = 20;
53  fError_ = 2.9f * 2.9f;
54  dFrameCounter_ = 0;
55  bSmooth_ = false;
56  colorModel_ = colorModel;
57  blobDetector_.SetMinSize(1000);
58  bAllowNewDistributionCreation_ = true;
59  bCleanUp_ = false;
60  bInverseCleanup_ = false;
61  blobDetectorRan_ = false;
62  //we are working on z
63  maxDepth_ = 1.0;
64 #ifdef BIAS_HAVE_PTHREADS
65  guardimagemutex = new pthread_mutex_t;
66  pthread_mutex_init(guardimagemutex, NULL);
67 #endif
68 }
69 
70 template <class StorageType>
73  colorModel_ = model;
74 }
75 
76 template <class StorageType>
78 SetSmoothing(bool smooth) {
79  bSmooth_ = smooth;
80  if (smooth)
81  blobDetector_.SetGaussSigma(1.0);
82  else
83  blobDetector_.SetGaussSigma(0.0);
84 }
85 
86 template <class StorageType>
88 InitWeights(const int maxWeight,
89  const int minWeight,
90  const float errorMargin) {
91  dMaxWeight_ = maxWeight;
92  dMinWeight_ = minWeight;
93  fError_ = errorMargin * errorMargin;
94  return 0;
95 }
96 
97 template <class StorageType>
100 #ifdef BIAS_HAVE_PTHREADS
101  delete guardimagemutex;
102 #endif
103 }
104 
105 template <class StorageType>
108 
109  TimeMeasure timer;
110 
111  blobDetectorRan_ = false;
112  if (!bInited_) {
113  channels_ = in.GetChannelCount();
114  width_ = in.GetWidth();
115  height_ = in.GetHeight();
116  }
117  in.GetROI()->GetCorners(roiULx_, roiULy_, roiLRx_, roiLRy_);
118  blobDetector_.SetROI(BIAS::Vector2<unsigned>(roiULx_,roiULy_),
119  BIAS::Vector2<unsigned>(roiLRx_,roiLRy_));
120  if( bSmooth_ ){
122  gs.SetSigma(2.0);
123  gs.SetHalfWinSize(3);
124  //gs.SetSize(5);
125  gs.Filter(in,in);
126  }
127 
128  //create a normalized image with float
129  CreateNormalizedImage_(in, workImage_);
130 
131 #ifdef BIAS_HAVE_PTHREADS
132  pthread_mutex_lock(guardimagemutex);
133 #endif
134  if (!bInited_) {
135  timer.Start();
136  Init_();
137  timer.Stop();
138  //cout<<" MoG Init_ took:"; timer.PrintRealTime();
139  timer.Reset();
140  }
141  else {
142  timer.Start();
143  Update_();
144  timer.Stop();
145  //cout<<" MoG Update_ took:"; timer.PrintRealTime();
146  timer.Reset();
147  }
148 
149 
150  timer.Start();
151  if (dFrameCounter_ > dMinWeight_) {
152  //inverse cleanup, delete pixel
153  if (bInverseCleanup_) {
154  Image<unsigned char> white;
155  white.Init(differenceSave_.GetWidth(), differenceSave_.GetHeight(), differenceSave_.GetChannelCount());
156  white.FillImageWithConstValue((unsigned char)255);
157  differenceSave_ = white - differenceSave_;
158  blobDetector_.SetEraseBelowMinSize(true);
159  if(!blobDetectorRan_){
160  blobDetector_.Detect(differenceSave_, corners_);
161  blobDetectorRan_ = true;
162  }
163  differenceSave_ = white - differenceSave_;
164  }
165 
166  //clean up pixel below specified minimum size
167  if (bCleanUp_) {
168  blobDetector_.SetEraseBelowMinSize(true);
169  if(!blobDetectorRan_){
170  blobDetector_.Detect(differenceSave_, corners_);
171  blobDetectorRan_ = true;
172  }
173  }
174 
175  //erode 3 pixel if requested
176  if (bErosion_) {
178  erosion.Erode3Fast(differenceSave_, difference_);
179  erosion.Erode3Fast(difference_, differenceSave_);
180  }
181  }
182 
183 
184 #ifdef BIAS_HAVE_PTHREADS
185  pthread_mutex_unlock(guardimagemutex);
186 #endif
187  dFrameCounter_++;
188 #if 0
189  if (dFrameCounter_ > 250 && dFrameCounter_ < 300) {
191  ImageIO::Save("mog-normalized-"+FileHandling::LeadingZeroString(dFrameCounter_,3)+".mip", workImage_);
192  ImageIO::Save("mog-weight-"+FileHandling::LeadingZeroString(dFrameCounter_,3)+".mip", weight_);
193  ImageIO::Save("mog-cov-"+FileHandling::LeadingZeroString(dFrameCounter_,3)+".mip", cov_);
194  ImageIO::Save("mog-guess-"+FileHandling::LeadingZeroString(dFrameCounter_,3)+".mip", guess_);
195  }
196  }
197 #endif
198  timer.Stop();
199  //cout<<" MoG Cleanup_ took:"; timer.PrintRealTime();
200  timer.Reset();
201 
202  return 0;
203 }
204 
205 template <class StorageType>
208  normalized = workImage_;
209  return 0;
210 }
211 
212 template <class StorageType>
215  weight = weight_;
216  return 0;
217 }
218 
219 template <class StorageType>
222  if (weight.IsEmpty()) {
223  weight.Init(width_,height_,channels_,ImageBase::ST_float,false);
224  }
225  weight.FillImageWithConstValue(0.0);
226  float **idaRet = weight.GetImageDataArray();
227  float **idaWeight = weight_.GetImageDataArray();
228  float val;
229  for (unsigned int y=0;y<height_;y++) {
230  for (unsigned int x=0;x<width_*channels_;x++) {
231  for (unsigned int i=0;i<dCurDistributions_;i++) {
232  val = idaWeight[y][x*dDistributions_+i];
233  if (val > idaRet[y][x])
234  idaRet[y][x] = val; //assign biggest weight of all distributions to weight output image
235  }
236  }
237  }
238  return 0;
239 }
240 
241 template <class StorageType>
244 #ifdef BIAS_HAVE_PTHREADS
245  pthread_mutex_lock(guardimagemutex);
246 #endif
247  match = matchValueImage_;
248 #ifdef BIAS_HAVE_PTHREADS
249  pthread_mutex_unlock(guardimagemutex);
250 #endif
251 
252  return 0;
253 }
254 
255 template <class StorageType>
258  // BIAS::Image<float> tmp(cov_);
259  // tmp.ScaleShiftBetween(0,255);
260 #ifdef BIAS_HAVE_PTHREADS
261  pthread_mutex_lock(guardimagemutex);
262 #endif
263  diff = differenceSave_;
264 #ifdef BIAS_HAVE_PTHREADS
265  pthread_mutex_unlock(guardimagemutex);
266 #endif
267  if (dFrameCounter_ < dMinWeight_)
268  return -1;
269  else
270  return 0;
271 }
272 
273 template <class StorageType>
276  if (dFrameCounter_ < dMinWeight_)
277  return -1;
278  unsigned char **visu = differenceVisu_.GetImageDataArray();
279 
280 #ifdef BIAS_HAVE_PTHREADS
281  pthread_mutex_lock(guardimagemutex);
282 #endif
283  unsigned char **idaD = differenceSave_.GetImageDataArray();
284  for (unsigned int y=0;y<height_;y++) {
285  for (unsigned int x=0;x<width_;x++) {
286  for (unsigned int c=0;c<3;c++) {
287  visu[y][x*3+c] = idaD[y][x];
288  }
289  }
290  }
291 #ifdef BIAS_HAVE_PTHREADS
292  pthread_mutex_unlock(guardimagemutex);
293 #endif
294  if(!blobDetectorRan_){
295  blobDetector_.Detect(differenceSave_, corners_);
296  blobDetectorRan_ = true;
297  }
298  blobDetector_.DrawInImage(differenceVisu_);
299 
300  guiImage = differenceVisu_;
301  return 0;
302 }
303 
304 template <class StorageType>
306 GetBoundingBoxes(std::vector<BIAS::BIASBlob> &corners) {
307  if (corners_.size()>0) {
308  corners = corners_;
309  return 0;
310  }
311  else
312  return -1;
313 }
314 
315 template <class StorageType>
318  if(!blobDetectorRan_){
319  blobDetector_.Detect(differenceSave_, corners_);
320  blobDetectorRan_ = true;
321  }
322  return blobDetector_.GetLargestBoundingBox(corners);
323 }
324 
325 template <class StorageType>
327 GetCurrentDistributions(std::vector<Image<float> > &distributionImages) {
328  distributionImages.clear();
329  distributionImages.resize(dCurDistributions_);
330 
331  float **idaGuess = guess_.GetImageDataArray();
332 
333  for (unsigned int i=0; i<dCurDistributions_;i++) {
334  if (!distributionImages[i].IsEmpty())
335  distributionImages[i].Release();
336  distributionImages[i].Init(width_, height_, channels_);
337  float **idaD = distributionImages[i].GetImageDataArray();
338  for (unsigned int y=0; y<height_; y++) {
339  for (unsigned int x=0; x<width_; x++) {
340  for (unsigned int c=0; c<channels_; c++) {
341  idaD[y][x*channels_+c] = idaGuess[y][(x*channels_+c)*dDistributions_+i];
342  //idaD[y][x*channels_+c] = idaCov[y][(x*channels_+c)*dDistributions_+i];
343  //idaD[y][x*channels_+c] = idaWeight[y][(x*channels_+c)*dDistributions_+i];
344  }
345  }
346  }
347  }
348  return 0;
349 }
350 
351 // Protected
352 
353 template <class StorageType>
356  height_ = in.GetHeight();
357  width_= in.GetWidth();
358 
359  if (in.GetStorageType() == ImageBase::ST_float) {
360  out = in;
361  } else {
363  }
364 
365  float **idaFL = out.GetImageDataArray();
366  channels_ = in.GetChannelCount();
367  unsigned int depthChannel =0;
368  switch(colorModel_){
369  //first normal RGB
370  case MOG_RGB:
371  case MOG_RGBD:
372  depthChannel = 3;
373 #ifdef BIAS_HAVE_OPENMP
374 #pragma omp parallel for
375 #endif
376  for (int y=0;y<(int)height_;y++) {
377  for (int x=0;x<(int)width_;x++) {
378  for (unsigned c=0;c<channels_;c++) {
379  if(c==depthChannel) //depth channel
380  idaFL[y][x*channels_+c] /= maxDepth_;
381  else
382  idaFL[y][x*channels_+c] /= 255.0f;
383  }
384  }
385  }
386  break;
387 
388  case MOG_HS:
389  case MOG_HSD:{
390  depthChannel = 2;
391  if(colorModel_== MOG_HS ) channels_ = 2; //HS
392  else if(colorModel_== MOG_HSD ) channels_ = 3; //HSD
393 
394 #ifdef BIAS_HAVE_OPENMP
395 #pragma omp parallel for
396 #endif
397  for (int y=0;y<(int)height_;y++) {
398  for (int x=0;x<(int)width_;x++) {
399  for (unsigned c=0;c<channels_;c++) {
400  if(c==depthChannel) //depth channel
401  idaFL[y][x*channels_+c] /= maxDepth_;
402  else
403  idaFL[y][x*channels_+c] /= 255.0f;
404  }
405  }
406  }
407  }
408  break;
409  case MOG_NRGB:
410  case MOG_NRGBD:{
411  depthChannel = 3;
412 #ifdef BIAS_HAVE_OPENMP
413 #pragma omp parallel for
414 #endif
415  for (int y=0;y<(int)height_;y++) {
416  for (int x=0;x<(int)width_;x++) {
417  //calculate normalized
418  float norm = 0;
419  for(int c =0;c<(int)channels_;c++){
420  if(c<3) norm += (idaFL[y][x*channels_+c])*(idaFL[y][x*channels_+c]);
421  }
422  norm = (float) sqrt(norm);
423  // Safeguard, we do not want to divide by something < 5 (why not??)
424  //if (norm < 5.0f) norm = 5.0f;
425  if (norm <= 1.0f) norm = 1.0f;
426  for(unsigned c =0;c<channels_;c++) {
427  if(c==depthChannel)
428  idaFL[y][x*channels_+c] /= maxDepth_;
429  else
430  idaFL[y][x*channels_+c] /= norm;
431  }
432  }
433  }
434  }
435  break;
436  default:
437  break;
438  }
439 
440  return 0;
441 }
442 
443 template <class StorageType>
445 Init_() {
446  dCurDistributions_ = 1;
447  guess_.ReInit(width_*channels_,height_,dDistributions_,
449  cov_.ReInit(width_*channels_,height_,dDistributions_,
451  weight_.ReInit(width_*channels_,height_,dDistributions_,
453 
454  maxWeight_.ReInit(width_,height_,channels_,ImageBase::ST_float);
455 
456  matchValueImage_.ReInit(width_,height_,1,ImageBase::ST_float,false, ImageBase::CM_Grey);
457  matchValueImage_.FillImageWithConstValue(0.0f);
458  difference_.ReInit(width_,height_,1,ImageBase::ST_unsignedchar,false, ImageBase::CM_Grey);
459  differenceSave_.ReInit(width_,height_,1,ImageBase::ST_unsignedchar,false, ImageBase::CM_Grey);
460  differenceSmooth_.ReInit(width_,height_,1,ImageBase::ST_unsignedchar,false, ImageBase::CM_Grey);
461  differenceVisu_.ReInit(width_,height_,3,ImageBase::ST_unsignedchar,false, ImageBase::CM_RGB);
462 
463 
464  float **idaImage = workImage_.GetImageDataArray();
465  float **idaWeight = weight_.GetImageDataArray();
466  float **idaGuess= guess_.GetImageDataArray();
467  float **idaCov = cov_.GetImageDataArray();;
468 
469  //fill guesses and covariances
470  for (unsigned int c=0;c<channels_;c++) {
471  for (unsigned int y=0;y<height_;y++) {
472  for (unsigned int x=0;x<width_;x++) {
473  float valGuess = 0;
474  int cntPix = 0;
475  for (unsigned int yw=y-dWindow_;yw<y+dWindow_;yw++) {
476  for (unsigned int xw=x-dWindow_;xw<x+dWindow_;xw++) {
477  if (yw<0 || xw<0 || yw>=height_ || xw >= width_)
478  continue;
479  valGuess += idaImage[yw][xw*channels_+c];
480 
481  cntPix++;
482  }
483  }
484  if (cntPix != 0){
485  valGuess /= (float)cntPix;
486  }
487  else{
488  valGuess = 0;
489  }
490  idaGuess[y][(x*channels_+c)*dDistributions_] = valGuess;
491  }
492  }
493  }
494  //fill covariances
495  int xc = 0;
496  for (unsigned int c=0;c<channels_;c++) {
497  for (unsigned int y=0;y<height_;y++) {
498  for (unsigned int x=0;x<width_;x++) {
499  float val = 0;
500  int cntPix = 0;
501  for (unsigned int yw=y-dWindow_;yw<y+dWindow_;yw++) {
502  for (unsigned int xw=x-dWindow_;xw<x+dWindow_;xw++) {
503  if (yw<0 || xw<0 || yw>=height_ || xw >= width_)
504  continue;
505  val += (idaImage[yw][xw*channels_+c] - idaGuess[yw][(xw*channels_+c)*dDistributions_])
506  * (idaImage[yw][xw*channels_+c] - idaGuess[yw][(xw*channels_+c)*dDistributions_]);
507  cntPix++;
508  }
509  }
510  if (cntPix!=0)
511  val /= (float)(cntPix*cntPix);
512  else
513  val = 1;
514  idaCov[y][(x*channels_+c)*dDistributions_] = val;
515  }
516  }
517  }
518 
519  //reset Guess, Cov and Weight
520  for (unsigned int y=0;y<height_;y++) {
521  for (unsigned int x=0;x<width_*channels_;x++) {
522  for (unsigned int i=1;i<dDistributions_;i++) {
523  xc = x*dDistributions_+i;
524  idaWeight[y][xc] = -1;
525  idaGuess[y][xc] = -1;
526  idaCov[y][xc] = -1;
527  }
528  }
529  }
530  bInited_ = true;
531  return 0;
532 }
533 
534 template <class StorageType>
536 InitOnePixel_(unsigned int x,unsigned int y,unsigned int c,unsigned int distrib) {
537  float val = 0;
538  int xc = 0;
539  int cntPix = 0;
540  float **idaImage = workImage_.GetImageDataArray();
541  float **idaGuess = guess_.GetImageDataArray();
542  float **idaCov = cov_.GetImageDataArray();
543  float **idaWeight = weight_.GetImageDataArray();
544 
545  for (unsigned int yw=y-dWindow_;yw<y+dWindow_;yw++) {
546  for (unsigned int xw=x-dWindow_;xw<x+dWindow_;xw++) {
547  if (yw<0 || xw<0 || yw>=height_ || xw >= width_)
548  continue;
549  val += idaImage[yw][xw*channels_+c];
550  cntPix++;
551  }
552  }
553  if (cntPix!=0)
554  val /= (float)cntPix;
555  else
556  val = 0;
557  xc = (x*channels_+c)*dDistributions_+distrib;
558 
559 // cout << idaGuess[y][xc] << " " << idaCov[y][xc];
560 
561  idaGuess[y][xc] = val;
562 
563  val = 0;
564  cntPix = 0;
565  for (unsigned int yw=y-dWindow_;yw<y+dWindow_;yw++) {
566  for (unsigned int xw=x-dWindow_;xw<x+dWindow_;xw++) {
567  if (yw<0 || xw<0 || yw>=height_ || xw >= width_)
568  continue;
569  xc = (xw*channels_+c)*dDistributions_+distrib;
570  val += (idaImage[yw][xw*channels_+c] - idaGuess[yw][xc]) *
571  (idaImage[yw][xw*channels_+c] - idaGuess[yw][xc]);
572  cntPix++;
573  }
574  }
575  if (cntPix!=0)
576  val /= (float)(cntPix*cntPix);
577  else
578  val = 1;
579  xc = (x*channels_+c)*dDistributions_+distrib;
580  idaCov[y][xc] = val;
581  idaWeight[y][xc] = 1;
582 // cout << " " << idaGuess[y][xc] << " " << idaCov[y][xc] << endl;
583  return 0;
584 }
585 
586 template <class StorageType>
589  // fill difference image white (matched pixel will be set to black,
590  // so changes are white in the result)
591  difference_.FillImageWithConstValue((unsigned char)255);
592 
593  float **idaImage = workImage_.GetImageDataArray();
594  float **idaWeight = weight_.GetImageDataArray();
595  float **idaGuess= guess_.GetImageDataArray();
596  float **idaCov = cov_.GetImageDataArray();;
597  float **idaMaxWeight = maxWeight_.GetImageDataArray();;
598  float **idaMatchValue = matchValueImage_.GetImageDataArray();
599  unsigned char **idaDiff = difference_.GetImageDataArray();
600 
601  // iterate through whole picture
602  //int x=0,y=0,c=0,i=0;
603  for (int y=(int)roiULy_ ; y<(int)roiLRy_ ; y++) {
604  int xc = 0; bool matched=false;
605 //#ifdef BIAS_HAVE_OPENMP
606 //#pragma omp parallel for //private(y,x,c,i)
607 //#endif
608  for (int x=(int)roiULx_;x<(int)roiLRx_;x++) {
609  unsigned int timesMatched_=0;
610  float matchValue_=0.0f;
611  unsigned distCount =0;
612  //////////////////CHANNELS/////////////////////////////
613  for (int c=0;c<(int)channels_;c++) {
614  // initialized with large number
615  float min_weight = 10000;
616  // initialized with small number
617  float max_weight = -10000;
618  // worst distribution (i.e. matched minimal times)
619  unsigned int min_distrib = 0;
620  // best distribution (i.e. matched maximal times)
621  //unsigned int max_distrib = 0;
622 
623  // find min/max distribs
624  for (int i=0;i<(int)dDistributions_;i++) {
625  xc = (x*channels_+c)*dDistributions_+i;
626  // find distribution with maximal weight
627  if (idaWeight[y][xc] > max_weight) {
628  max_weight = idaWeight[y][xc];
629  //max_distrib = i;
630  }
631  // find distribution with minimal weight
632  if (idaWeight[y][xc] < min_weight) {
633  min_weight = idaWeight[y][xc];
634  min_distrib = i;
635  }
636  if (idaWeight[y][xc] < 0)
637  break;
638  }
639 
640  matched = false;
641  // value in orig image
642  float val = idaImage[y][x*channels_+c];
643  ///////////////////DISTRIBUTIONS///////////////////////////////
644  // check for match in all distributions
645  for (int i=0;i<(int)dCurDistributions_;i++) {
646  xc = (x*channels_+c)*dDistributions_+i;
647  // guess and covariance in this distribution
648  float guess = idaGuess[y][xc];
649  if (guess < 0) continue;
650  float cov = idaCov[y][xc];
651  float absdiff = abs(val - guess);
652  matchValue_ += absdiff;
653  distCount++;
654  float absdiffSquared = absdiff*absdiff;
655  ////////////////////MATCH////////////////////////////
656  if (!matched && absdiffSquared < fError_*cov) {
657  // match! weight is increased
658  if (idaWeight[y][xc] <= dMaxWeight_)
659  idaWeight[y][xc]++;
660  // guess and covariance get updated
661  float myCovTest=0.0f,myGuessTest =0.0f;
662 
663  myGuessTest = (1.0f-fUpdateFactor_)*guess + fUpdateFactor_*val;
664  myCovTest = (1.0f-fUpdateFactor_)*cov + fUpdateFactor_*absdiffSquared;
665 
666  if (myCovTest < 1e-5) {
667  idaCov[y][xc] = 1e-5f;
668  } else if (myCovTest > 0.05) {
669  idaCov[y][xc] = 0.05f;
670  }
671 
672  idaGuess[y][xc] = myGuessTest;
673 
674  timesMatched_++;
675  matched = true;
676  }// end if (!matched && absdiff*absdiff < fError_*cov)
677  ///////////////////END MATCH /////////////////////////////
678  ///////////////////NO MATCH /////////////////////////////
679  else { // no match! decrease weight
680  if (bAllowNewDistributionCreation_) {
681  if (idaWeight[y][xc] > dMinWeight_)
682  idaWeight[y][xc]--;
683  }
684  }//end else
685  } //end going over distributions
686  /////////////////END DISTRIBUTIONS////////////////////////////
687  // if no match is found, overwrite least matched distribution
688  //with newly initialized values
689  if (!matched && bAllowNewDistributionCreation_) {
690  InitOnePixel_(x,y,c,min_distrib);
691  if (min_distrib >= dCurDistributions_) {
692  dCurDistributions_ = min_distrib +1;
693  }
694  }
695  // update max weight image (only for vis)
696  idaMaxWeight[y][x] = max_weight;
697  } //channels
698  ///////////////////END CHANNELS////////////////////////
699  //if matched on all channels
700  if (timesMatched_ == channels_) {
701  idaDiff[y][x] = 0; //diff is black
702  } else {
703  idaDiff[y][x] = 255; //else diff white
704  }
705 
706  if (matchValue_ <= 0) {
707  idaMatchValue[y][x] = 0;
708  } else {
709  idaMatchValue[y][x] = matchValue_ / (float)(distCount);
710  }
711  }//x
712  }//y
713  differenceSave_.CopyIn_NoInit(difference_.GetImageData());
714  return 0;
715 }
716 
717 namespace BIAS{
718 template class MixtureOfGaussians<unsigned char>;
719 template class MixtureOfGaussians<float>;
720 }
int GetMaxWeightImage(BIAS::Image< float > &weight)
get image with current max weights, only interesting for visualisation
int GetNormalizedImage(BIAS::Image< float > &normalized)
get normalized rgb image
gray values, 1 channel
Definition: ImageBase.hh:130
void SetSmoothing(const bool smooth)
void GetCorners(unsigned &UpperLeftX, unsigned &UpperLeftY, unsigned &LowerRightX, unsigned &LowerRightY) const
Return the region of interest, by saving the coordinates within the variables defined by the paramete...
Definition: ROI.hh:443
bool IsEmpty() const
check if ImageData_ points to allocated image buffer or not
Definition: ImageBase.hh:245
void SetHalfWinSize(const int hws, bool AdjustSigma=true)
define the half win size of the kernel, if AdjustSigma is true sigma is computed according to the cut...
Definition: Gauss.hh:173
int GetCurrentDistributions(std::vector< Image< float > > &distributionImages)
get vector of images containing current guesses (distributions)
float image storage type
Definition: ImageBase.hh:118
int GetWeightImage(BIAS::Image< float > &weights)
get image with current weights and distributions
int InitOnePixel_(unsigned int x, unsigned int y, unsigned int c, unsigned int distrib)
int GetBoundingBoxes(std::vector< BIAS::BIASBlob > &corners)
get vector of corners for each bounding box of detected changes
unsigned int GetWidth() const
Definition: ImageBase.hh:312
int InitWeights(const int maxWeight, const int minWeight, const float errorMargin)
init weights for background/object distinction
Helper class to store blob corners.
void SetColorModel(MoGColorModel model)
set the used color model note that the images have to be given in the correct model no conversion wil...
int GetMatchValueImage(BIAS::Image< float > &match)
ROI * GetROI()
Returns a pointer to the roi object.
Definition: ImageBase.hh:615
Erosion operator for binary images (black and white)
Definition: Erosion.hh:40
static int ConvertST(const BIAS::ImageBase &source, BIAS::ImageBase &dest, ImageBase::EStorageType targetST)
Function to convert the storage type of images e.g.
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
Definition: ImageBase.hh:382
color values, 3 channels, order: red,green,blue
Definition: ImageBase.hh:131
static std::string LeadingZeroString(const int &n, const unsigned int &digits=DEFAULT_LEADING_ZEROS)
Create a string with leading zeroes from number.
unsigned int GetHeight() const
Definition: ImageBase.hh:319
void SetSigma(const double si)
Definition: Gauss.hh:162
int Erode3Fast(const Image< InputStorageType > &src, Image< OutputStorageType > &dest, bool Neighbor4=false)
Very fast erode with 3x3 mask, all values, which are not not zero, are treated as foreground...
Definition: Erosion.cpp:80
void FillImageWithConstValue(StorageType Value)
fill grey images
Definition: Image.cpp:456
The image template class for specific storage types.
Definition: Image.hh:78
int GetLargestBoundingBox(BIAS::BIASBlob &corners)
get largest bounding box of detected changes
static int Save(const std::string &filename, const ImageBase &img, const enum TFileFormat FileFormat=FF_auto, const bool sync=BIAS_DEFAULT_SYNC, const int c_jpeg_quality=BIAS_DEFAULT_IMAGE_QUALITY, const bool forceNewID=BIAS_DEFAULT_FORCENEWID, const bool &writeMetaData=true)
Export image as file using extrnal libs.
Definition: ImageIO.cpp:725
int CreateNormalizedImage_(const BIAS::Image< StorageType > &in, BIAS::Image< float > &out)
virtual int Filter(const Image< InputStorageType > &src, Image< OutputStorageType > &dst)
sets gauss kernel if params changed and calls convolution or fast grey implementation if possible ...
Definition: Gauss.cpp:89
void Init(unsigned int Width, unsigned int Height, unsigned int channels=1, enum EStorageType storageType=ST_unsignedchar, const bool interleaved=true)
calls Init from ImageBase storageType is ignored, just dummy argument
Definition: Image.cpp:421
int GetDifferenceImage(BIAS::Image< unsigned char > &diff)
get image of detected scene changes.
MixtureOfGaussians(const unsigned int numDistributions, const unsigned int sizeWindow=3, const float updateFactor=0.1, const MoGColorModel colorModel=MOG_NRGB)
constructor
enum EStorageType GetStorageType() const
Definition: ImageBase.hh:414
(8bit) unsigned char image storage type
Definition: ImageBase.hh:112
int GetDifferenceImageWithVisuals(BIAS::Image< unsigned char > &guiImage)
get image of detected scene changes with visualisations of detection
int Apply(BIAS::Image< StorageType > &in)
update calculations with new image the image has to be formatted correctly, e.g for MoG on HSL images...
class TimeMeasure contains functions for timing real time and cpu time.
Definition: TimeMeasure.hh:111
const StorageType ** GetImageDataArray() const
overloaded GetImageDataArray() from ImageBase
Definition: Image.hh:153