aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pix_opencv_bgstats-help.pd121
-rw-r--r--pix_opencv_bgstats.cc290
-rwxr-xr-xpix_opencv_bgstats.h99
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