diff options
author | N.N. <sevyves@users.sourceforge.net> | 2009-08-30 21:59:11 +0000 |
---|---|---|
committer | N.N. <sevyves@users.sourceforge.net> | 2009-08-30 21:59:11 +0000 |
commit | a267847def9a900fa0634f59a34bae96183bdbca (patch) | |
tree | 93e56d362fca06bce3f792933bf5dccdf0c1c67e | |
parent | 99b36c757a80e6cafaea21f40b31455065bb4590 (diff) |
added statistical foreground extraction
svn path=/trunk/externals/pix_opencv/; revision=12151
-rw-r--r-- | pix_opencv_bgstats-help.pd | 121 | ||||
-rw-r--r-- | pix_opencv_bgstats.cc | 290 | ||||
-rwxr-xr-x | pix_opencv_bgstats.h | 99 |
3 files changed, 510 insertions, 0 deletions
diff --git a/pix_opencv_bgstats-help.pd b/pix_opencv_bgstats-help.pd new file mode 100644 index 0000000..6b35001 --- /dev/null +++ b/pix_opencv_bgstats-help.pd @@ -0,0 +1,121 @@ +#N canvas 153 45 1070 675 10; +#X obj 407 -28 gemhead; +#X obj 365 487 pix_texture; +#X obj 365 515 square 2; +#X obj 20 165 cnv 15 220 70 empty empty empty 20 12 0 14 -195568 -66577 +0; +#N canvas 0 22 454 304 gemwin 0; +#X obj 67 89 outlet; +#X obj 67 10 inlet; +#X obj 67 41 route create; +#X msg 67 70 set destroy; +#X msg 182 68 set create; +#N canvas 87 154 247 179 Gem.init 0; +#X obj 118 46 loadbang; +#X msg 118 81 reset; +#X obj 118 113 outlet; +#X connect 0 0 1 0; +#X connect 1 0 2 0; +#X restore 289 80 pd Gem.init; +#X obj 192 276 gemwin; +#X msg 191 223 create \, 1; +#X msg 267 224 destroy; +#X msg 313 196 frame 15; +#X obj 194 186 t b b b; +#X connect 1 0 2 0; +#X connect 2 0 3 0; +#X connect 2 0 10 0; +#X connect 2 1 4 0; +#X connect 2 1 8 0; +#X connect 3 0 0 0; +#X connect 4 0 0 0; +#X connect 7 0 6 0; +#X connect 8 0 6 0; +#X connect 9 0 6 0; +#X connect 10 0 7 0; +#X connect 10 2 9 0; +#X restore 25 209 pd gemwin; +#X msg 25 185 destroy; +#X text 21 165 Create window and render; +#X obj 200 368 pix_texture; +#X obj 200 396 square 2; +#X obj 266 167 translateXYZ -2 0 0; +#X obj 367 224 separator; +#X obj 346 281 cnv 15 550 200 empty empty empty 20 12 0 14 -24198 -66577 +0; +#X obj 511 -66 bng 25 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 524 128 unpack 0 0 0; +#X floatatom 514 151 5 0 0 3 length - -; +#X floatatom 563 151 5 0 0 3 width - -; +#X floatatom 613 151 5 0 0 3 height - -; +#X obj 568 109 bng 15 250 50 0 empty empty end_reached 20 7 0 10 -262144 +-1 -1; +#X floatatom 550 74 5 0 10000 1 frame# - -; +#X obj 511 -37 openpanel; +#X msg 511 -17 open \$1; +#X obj 499 92 pix_film; +#X msg 517 26 auto \$1; +#X obj 517 8 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 364 259 translateXYZ 4 0 0; +#X text 24 67 Comments and support @ ydegoyon.gmail.com; +#X text 24 -2 Objects disappear from the foreground after a certain +amount of time after they disappeared ( delta ) and make noise filtering +using erosion and dilation steps ( erode paramater ). It also eliminates +from the foreground object that are less than minarea parameter.; +#X text 26 -47 pix_opencv_bgstats : foreground extraction using a statitical +method.; +#X obj 363 452 pix_opencv_bgstats; +#X msg 406 300 delta \$1; +#X obj 467 300 / 100; +#X floatatom 508 302 5 0 0 0 - - -; +#X floatatom 472 336 5 0 0 0 - - -; +#X msg 411 335 erode \$1; +#X floatatom 495 373 5 0 0 0 - - -; +#X msg 425 371 minarea \$1; +#X text 539 378 ( default : 10x10 ); +#X msg 447 405 reset; +#X text 549 294 amount of time after which an object is deleted from +the foreground ( default : 0.1 seconds ); +#X text 511 327 number of iterations of the erode-dilate filter; +#X text 512 337 to eliminate small forms and noise; +#X text 542 367 minimum size of foreground objects; +#X text 491 406 resetting the background; +#X text 512 348 ( default : 2 ); +#X msg 561 47 colorspace RGBA; +#X obj 584 20 loadbang; +#X connect 0 0 21 0; +#X connect 1 0 2 0; +#X connect 4 0 5 0; +#X connect 5 0 4 0; +#X connect 7 0 8 0; +#X connect 9 0 7 0; +#X connect 9 0 10 0; +#X connect 10 0 24 0; +#X connect 12 0 19 0; +#X connect 13 0 14 0; +#X connect 13 1 15 0; +#X connect 13 2 16 0; +#X connect 17 0 18 0; +#X connect 18 0 21 1; +#X connect 19 0 20 0; +#X connect 20 0 21 0; +#X connect 21 0 9 0; +#X connect 21 1 13 0; +#X connect 21 2 17 0; +#X connect 22 0 21 0; +#X connect 23 0 22 0; +#X connect 24 0 28 0; +#X connect 28 0 1 0; +#X connect 29 0 28 0; +#X connect 30 0 29 0; +#X connect 31 0 30 0; +#X connect 31 0 30 1; +#X connect 32 0 33 0; +#X connect 33 0 28 0; +#X connect 34 0 35 0; +#X connect 35 0 28 0; +#X connect 37 0 28 0; +#X connect 44 0 21 0; +#X connect 45 0 44 0; diff --git a/pix_opencv_bgstats.cc b/pix_opencv_bgstats.cc new file mode 100644 index 0000000..639e44c --- /dev/null +++ b/pix_opencv_bgstats.cc @@ -0,0 +1,290 @@ +//////////////////////////////////////////////////////// +// +// GEM - Graphics Environment for Multimedia +// +// zmoelnig@iem.kug.ac.at +// +// Implementation file +// +// Copyright (c) 1997-2000 Mark Danks. +// Copyright (c) Günther Geiger. +// Copyright (c) 2001-2002 IOhannes m zmoelnig. forum::für::umläute. IEM +// Copyright (c) 2002 James Tittle & Chris Clepper +// For information on usage and redistribution, and for a DISCLAIMER OF ALL +// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution. +// +///////////////////////////////////////////////////////// + +#include "pix_opencv_bgstats.h" + +CPPEXTERN_NEW(pix_opencv_bgstats) + +///////////////////////////////////////////////////////// +// +// pix_opencv_bgstats +// +///////////////////////////////////////////////////////// +// Constructor +// +///////////////////////////////////////////////////////// +pix_opencv_bgstats :: pix_opencv_bgstats() +{ + comp_xsize=320; + comp_ysize=240; + + x_erode = 2; + x_minarea = 10*10; + x_delta = 0.1; // 0.1 seconds + x_frames = 0; + + foreground = cvCreateImage(cvSize(comp_xsize,comp_ysize), IPL_DEPTH_8U, 3); + incoming = cvCreateImage(cvSize(comp_xsize,comp_ysize), IPL_DEPTH_8U, 3); + rgba = cvCreateImage(cvSize(comp_xsize,comp_ysize), IPL_DEPTH_8U, 4); + rgb = cvCreateImage(cvSize(comp_xsize,comp_ysize), IPL_DEPTH_8U, 3); + gray = cvCreateImage(cvSize(comp_xsize,comp_ysize), IPL_DEPTH_8U, 1); + x_model = NULL; + +} + +///////////////////////////////////////////////////////// +// Destructor +// +///////////////////////////////////////////////////////// +pix_opencv_bgstats :: ~pix_opencv_bgstats() +{ + //Destroy cv_images to clean memory + cvReleaseImage(&rgba); + cvReleaseImage(&rgb); + cvReleaseImage(&gray); + cvReleaseImage(&foreground); + cvReleaseImage(&incoming); +} + +///////////////////////////////////////////////////////// +// processImage +// +///////////////////////////////////////////////////////// +void pix_opencv_bgstats :: processRGBAImage(imageStruct &image) +{ + + if ((this->comp_xsize!=image.xsize)||(this->comp_ysize!=image.ysize)||(!rgba)) { + + this->comp_xsize = image.xsize; + this->comp_ysize = image.ysize; + x_frames = 0; + + //Destroy cv_images to clean memory + cvReleaseImage(&rgba); + cvReleaseImage(&rgb); + cvReleaseImage(&gray); + cvReleaseImage(&foreground); + cvReleaseImage(&incoming); + + //create the orig image with new size + rgba = cvCreateImage(cvSize(image.xsize,image.ysize), IPL_DEPTH_8U, 4); + rgb = cvCreateImage(cvSize(image.xsize,image.ysize), IPL_DEPTH_8U, 3); + gray = cvCreateImage(cvSize(image.xsize,image.ysize), IPL_DEPTH_8U, 1); + + incoming = cvCreateImage(cvSize(image.xsize,image.ysize), IPL_DEPTH_8U, 3); + foreground = cvCreateImage(cvSize(image.xsize,image.ysize), IPL_DEPTH_8U, 3); + + cvReleaseBGStatModel( &x_model ); + x_model = NULL; + + } + memcpy( rgba->imageData, image.data, image.xsize*image.ysize*4 ); + cvCvtColor(rgba, incoming, CV_BGRA2BGR); + + if ( x_model == NULL ) + { + x_modelparams.Lc = CV_BGFG_FGD_LC; + x_modelparams.N1c = CV_BGFG_FGD_N1C; + x_modelparams.N2c = CV_BGFG_FGD_N2C; + x_modelparams.Lcc = CV_BGFG_FGD_LCC; + x_modelparams.N1cc = CV_BGFG_FGD_N1CC; + x_modelparams.N2cc = CV_BGFG_FGD_N2CC; + x_modelparams.is_obj_without_holes = 1; + x_modelparams.alpha1 = CV_BGFG_FGD_ALPHA_1; + x_modelparams.alpha2 = CV_BGFG_FGD_ALPHA_2; + x_modelparams.alpha3 = CV_BGFG_FGD_ALPHA_3; + x_modelparams.T = CV_BGFG_FGD_T; + x_modelparams.perform_morphing = x_erode; + x_modelparams.minArea = x_minarea; + x_modelparams.delta = x_delta; + x_model = cvCreateFGDStatModel( incoming, &x_modelparams ); + } + else if ( x_frames == 5 ) + { + // strange model stabilize after a few frames + cvReleaseBGStatModel( &x_model ); + x_model = cvCreateFGDStatModel( incoming, &x_modelparams ); + } + else + { + cvUpdateBGStatModel( incoming, x_model ); + } + + x_frames++; + cvCvtColor(x_model->foreground, rgba, CV_GRAY2BGRA); + + memcpy( image.data, rgba->imageData, image.xsize*image.ysize*4 ); +} + +void pix_opencv_bgstats :: processRGBImage(imageStruct &image) +{ + + if ((this->comp_xsize!=image.xsize)||(this->comp_ysize!=image.ysize)||(!rgba)) { + + this->comp_xsize = image.xsize; + this->comp_ysize = image.ysize; + x_frames = 0; + + //Destroy cv_images to clean memory + cvReleaseImage(&rgba); + cvReleaseImage(&rgb); + cvReleaseImage(&gray); + cvReleaseImage(&foreground); + cvReleaseImage(&incoming); + + //create the orig image with new size + rgba = cvCreateImage(cvSize(image.xsize,image.ysize), IPL_DEPTH_8U, 4); + rgb = cvCreateImage(cvSize(image.xsize,image.ysize), IPL_DEPTH_8U, 3); + gray = cvCreateImage(cvSize(image.xsize,image.ysize), IPL_DEPTH_8U, 1); + + incoming = cvCreateImage(cvSize(image.xsize,image.ysize), IPL_DEPTH_8U, 3); + foreground = cvCreateImage(cvSize(image.xsize,image.ysize), IPL_DEPTH_8U, 3); + + cvReleaseBGStatModel( &x_model ); + x_model = NULL; + } + memcpy( rgb->imageData, image.data, image.xsize*image.ysize*3 ); + memcpy( incoming->imageData, image.data, image.xsize*image.ysize*3 ); + + if ( x_model == NULL ) + { + x_modelparams.Lc = CV_BGFG_FGD_LC; + x_modelparams.N1c = CV_BGFG_FGD_N1C; + x_modelparams.N2c = CV_BGFG_FGD_N2C; + x_modelparams.Lcc = CV_BGFG_FGD_LCC; + x_modelparams.N1cc = CV_BGFG_FGD_N1CC; + x_modelparams.N2cc = CV_BGFG_FGD_N2CC; + x_modelparams.is_obj_without_holes = 1; + x_modelparams.alpha1 = CV_BGFG_FGD_ALPHA_1; + x_modelparams.alpha2 = CV_BGFG_FGD_ALPHA_2; + x_modelparams.alpha3 = CV_BGFG_FGD_ALPHA_3; + x_modelparams.T = CV_BGFG_FGD_T; + x_modelparams.perform_morphing = x_erode; + x_modelparams.minArea = x_minarea; + x_modelparams.delta = x_delta; + x_model = cvCreateFGDStatModel( incoming, &x_modelparams ); + } + else if ( x_frames == 5 ) + { + // strange model stabilize after a few frames + cvReleaseBGStatModel( &x_model ); + x_model = cvCreateFGDStatModel( incoming, &x_modelparams ); + } + else + { + cvUpdateBGStatModel( incoming, x_model ); + } + + x_frames++; + cvCvtColor(x_model->foreground, rgb, CV_GRAY2BGR); + + memcpy( image.data, rgb->imageData, image.xsize*image.ysize*3 ); + +} + +void pix_opencv_bgstats :: processYUVImage(imageStruct &image) +{ + post( "pix_opencv_bgstats : yuv format not supported" ); +} + +void pix_opencv_bgstats :: processGrayImage(imageStruct &image) +{ + post( "pix_opencv_bgstats : gray format not supported" ); +} + +///////////////////////////////////////////////////////// +// floatThreshMess +// +///////////////////////////////////////////////////////// +void pix_opencv_bgstats :: floatMinAreaMess (float minarea) +{ + if ( ( (int)minarea>0 ) && ( x_model != NULL ) ) + { + x_minarea = minarea; + x_modelparams.minArea = minarea; + cvReleaseBGStatModel( &x_model ); + x_model = cvCreateFGDStatModel( incoming, &x_modelparams ); + } +} + +void pix_opencv_bgstats :: floatErodeMess(float erode) +{ + if ( ( (int)erode>0 ) && ( x_model != NULL ) ) + { + x_erode = (int)erode; + x_modelparams.perform_morphing = (int)erode; + cvReleaseBGStatModel( &x_model ); + x_model = cvCreateFGDStatModel( incoming, &x_modelparams ); + } +} + +void pix_opencv_bgstats :: floatDeltaMess(float delta) +{ + if ( ( delta>0.0 ) && ( x_model != NULL ) ) + { + x_delta = delta; + x_modelparams.delta = delta; + cvReleaseBGStatModel( &x_model ); + x_model = cvCreateFGDStatModel( incoming, &x_modelparams ); + } +} + +void pix_opencv_bgstats :: resetMess () +{ + if ( x_model != NULL ) + { + cvReleaseBGStatModel( &x_model ); + x_model = cvCreateFGDStatModel( incoming, &x_modelparams ); + } +} + +///////////////////////////////////////////////////////// +// static member function +// +///////////////////////////////////////////////////////// +void pix_opencv_bgstats :: obj_setupCallback(t_class *classPtr) +{ + class_addmethod(classPtr, (t_method)&pix_opencv_bgstats::floatMinAreaMessCallback, + gensym("minarea"), A_FLOAT, A_NULL); + class_addmethod(classPtr, (t_method)&pix_opencv_bgstats::floatErodeMessCallback, + gensym("erode"), A_FLOAT, A_NULL); + class_addmethod(classPtr, (t_method)&pix_opencv_bgstats::floatDeltaMessCallback, + gensym("delta"), A_FLOAT, A_NULL); + class_addmethod(classPtr, (t_method)&pix_opencv_bgstats::resetMessCallback, + gensym("reset"), A_NULL); + +} + +void pix_opencv_bgstats :: floatMinAreaMessCallback(void *data, t_floatarg minarea) +{ + GetMyClass(data)->floatMinAreaMess((float)minarea); +} + +void pix_opencv_bgstats :: floatErodeMessCallback(void *data, t_floatarg erode) +{ + GetMyClass(data)->floatErodeMess((float)erode); +} + +void pix_opencv_bgstats :: floatDeltaMessCallback(void *data, t_floatarg delta) +{ + GetMyClass(data)->floatDeltaMess((float)delta); +} + +void pix_opencv_bgstats :: resetMessCallback(void *data) +{ + GetMyClass(data)->resetMess(); +} diff --git a/pix_opencv_bgstats.h b/pix_opencv_bgstats.h new file mode 100755 index 0000000..9d1aff3 --- /dev/null +++ b/pix_opencv_bgstats.h @@ -0,0 +1,99 @@ +/*----------------------------------------------------------------- +LOG + GEM - Graphics Environment for Multimedia + + Change pix to greyscale + + Copyright (c) 1997-1999 Mark Danks. mark@danks.org + Copyright (c) Günther Geiger. geiger@epy.co.at + Copyright (c) 2001-2002 IOhannes m zmoelnig. forum::für::umläute. IEM. zmoelnig@iem.kug.ac.at + Copyright (c) 2002 James Tittle & Chris Clepper + For information on usage and redistribution, and for a DISCLAIMER OF ALL + WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution. + +-----------------------------------------------------------------*/ + +#ifndef INCLUDE_PIX_OPENCV_BGSUBSTRACT_H_ +#define INCLUDE_PIX_OPENCV_BGSUBSTRACT_H_ + +#include "Base/GemPixObj.h" + +#ifndef _EiC +#include "cv.h" +#include "cvaux.h" +#endif + +/*----------------------------------------------------------------- +------------------------------------------------------------------- +CLASS + pix_opencv_bgstats + + Statistical background substraction + +KEYWORDS + pix + +DESCRIPTION + +-----------------------------------------------------------------*/ +class GEM_EXTERN pix_opencv_bgstats : public GemPixObj +{ + CPPEXTERN_HEADER(pix_opencv_bgstats, GemPixObj) + + public: + + ////////// + // Constructor + pix_opencv_bgstats(); + + protected: + + ////////// + // Destructor + virtual ~pix_opencv_bgstats(); + + ////////// + // Do the processing + virtual void processRGBAImage(imageStruct &image); + virtual void processRGBImage(imageStruct &image); + virtual void processYUVImage(imageStruct &image); + virtual void processGrayImage(imageStruct &image); + + ////////// + // Set the new edge threshold + void floatMinAreaMess(float minarea); + void floatErodeMess(float erode); + void floatDeltaMess(float delta); + void resetMess(void); + + // The new threshold + int x_erode; + float x_minarea; + float x_delta; + int x_frames; + + // to detect changes in the image size + int comp_xsize; + int comp_ysize; + + private: + + ////////// + // Static member functions + static void floatMinAreaMessCallback(void *data, float minarea); + static void floatErodeMessCallback(void *data, float erode); + static void floatDeltaMessCallback(void *data, float delta); + static void resetMessCallback(void *data); + + ///////// + // IplImage needed + IplImage *rgba, *rgb, *gray; + IplImage *foreground, *incoming; + + // Stat background model data + CvBGStatModel *x_model; + CvFGDStatModelParams x_modelparams; + +}; + +#endif // for header file |