--- /dev/null
+// Background average sample code done with averages and done with codebooks
+// (adapted from the OpenCV book sample)
+//
+// NOTE: To get the keyboard to work, you *have* to have one of the video windows be active
+// and NOT the consule window.
+//
+// Gary Bradski Oct 3, 2008.
+//
+/* *************** License:**************************
+ Oct. 3, 2008
+ Right to use this code in any way you want without warrenty, support or any guarentee of it working.
+
+ BOOK: It would be nice if you cited it:
+ Learning OpenCV: Computer Vision with the OpenCV Library
+ by Gary Bradski and Adrian Kaehler
+ Published by O'Reilly Media, October 3, 2008
+
+ AVAILABLE AT:
+ http://www.amazon.com/Learning-OpenCV-Computer-Vision-Library/dp/0596516134
+ Or: http://oreilly.com/catalog/9780596516130/
+ ISBN-10: 0596516134 or: ISBN-13: 978-0596516130
+************************************************** */
+
+#include "cvaux.h"
+#include "cxmisc.h"
+#include "highgui.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+//VARIABLES for CODEBOOK METHOD:
+CvBGCodeBookModel* model = 0;
+const int NCHANNELS = 3;
+bool ch[NCHANNELS]={true,true,true}; // This sets what channels should be adjusted for background bounds
+
+void help(void)
+{
+ printf("\nLearn background and find foreground using simple average and average difference learning method:\n"
+ "\nUSAGE:\nbgfg_codebook [--nframes=300] [movie filename, else from camera]\n"
+ "***Keep the focus on the video windows, NOT the consol***\n\n"
+ "INTERACTIVE PARAMETERS:\n"
+ "\tESC,q,Q - quit the program\n"
+ "\th - print this help\n"
+ "\tp - pause toggle\n"
+ "\ts - single step\n"
+ "\tr - run mode (single step off)\n"
+ "=== AVG PARAMS ===\n"
+ "\t- - bump high threshold UP by 0.25\n"
+ "\t= - bump high threshold DOWN by 0.25\n"
+ "\t[ - bump low threshold UP by 0.25\n"
+ "\t] - bump low threshold DOWN by 0.25\n"
+ "=== CODEBOOK PARAMS ===\n"
+ "\ty,u,v- only adjust channel 0(y) or 1(u) or 2(v) respectively\n"
+ "\ta - adjust all 3 channels at once\n"
+ "\tb - adjust both 2 and 3 at once\n"
+ "\ti,o - bump upper threshold up,down by 1\n"
+ "\tk,l - bump lower threshold up,down by 1\n"
+ "\tSPACE - reset the model\n"
+ );
+}
+
+//
+//USAGE: ch9_background startFrameCollection# endFrameCollection# [movie filename, else from camera]
+//If from AVI, then optionally add HighAvg, LowAvg, HighCB_Y LowCB_Y HighCB_U LowCB_U HighCB_V LowCB_V
+//
+int main(int argc, char** argv)
+{
+ const char* filename = 0;
+ IplImage* rawImage = 0, *yuvImage = 0; //yuvImage is for codebook method
+ IplImage *ImaskCodeBook = 0,*ImaskCodeBookCC = 0;
+ CvCapture* capture = 0;
+
+ int c, n, nframes = 0;
+ int nframesToLearnBG = 300;
+
+ model = cvCreateBGCodeBookModel();
+
+ //Set color thresholds to default values
+ model->modMin[0] = 3;
+ model->modMin[1] = model->modMin[2] = 3;
+ model->modMax[0] = 10;
+ model->modMax[1] = model->modMax[2] = 10;
+ model->cbBounds[0] = model->cbBounds[1] = model->cbBounds[2] = 10;
+
+ bool pause = false;
+ bool singlestep = false;
+
+ for( n = 1; n < argc; n++ )
+ {
+ static const char* nframesOpt = "--nframes=";
+ if( strncmp(argv[n], nframesOpt, strlen(nframesOpt))==0 )
+ {
+ if( sscanf(argv[n] + strlen(nframesOpt), "%d", &nframesToLearnBG) == 0 )
+ {
+ help();
+ return -1;
+ }
+ }
+ else
+ filename = argv[n];
+ }
+
+ if( !filename )
+ {
+ printf("Capture from camera\n");
+ capture = cvCaptureFromCAM( 0 );
+ }
+ else
+ {
+ printf("Capture from file %s\n",filename);
+ capture = cvCreateFileCapture( filename );
+ }
+
+ if( !capture )
+ {
+ printf( "Can not initialize video capturing\n\n" );
+ help();
+ return -1;
+ }
+
+ //MAIN PROCESSING LOOP:
+ for(;;)
+ {
+ if( !pause )
+ {
+ rawImage = cvQueryFrame( capture );
+ ++nframes;
+ if(!rawImage)
+ break;
+ }
+ if( singlestep )
+ pause = true;
+
+ //First time:
+ if( nframes == 1 && rawImage )
+ {
+ // CODEBOOK METHOD ALLOCATION
+ yuvImage = cvCloneImage(rawImage);
+ ImaskCodeBook = cvCreateImage( cvGetSize(rawImage), IPL_DEPTH_8U, 1 );
+ ImaskCodeBookCC = cvCreateImage( cvGetSize(rawImage), IPL_DEPTH_8U, 1 );
+ cvSet(ImaskCodeBook,cvScalar(255));
+
+ cvNamedWindow( "Raw", 1 );
+ cvNamedWindow( "ForegroundCodeBook",1);
+ cvNamedWindow( "CodeBook_ConnectComp",1);
+ }
+
+ // If we've got an rawImage and are good to go:
+ if( rawImage )
+ {
+ cvCvtColor( rawImage, yuvImage, CV_BGR2YCrCb );//YUV For codebook method
+ //This is where we build our background model
+ if( !pause && nframes-1 < nframesToLearnBG )
+ cvBGCodeBookUpdate( model, yuvImage );
+
+ if( nframes-1 == nframesToLearnBG )
+ cvBGCodeBookClearStale( model, model->t/2 );
+
+ //Find the foreground if any
+ if( nframes-1 >= nframesToLearnBG )
+ {
+ // Find foreground by codebook method
+ cvBGCodeBookDiff( model, yuvImage, ImaskCodeBook );
+ // This part just to visualize bounding boxes and centers if desired
+ cvCopy(ImaskCodeBook,ImaskCodeBookCC);
+ cvSegmentFGMask( ImaskCodeBookCC );
+ }
+ //Display
+ cvShowImage( "Raw", rawImage );
+ cvShowImage( "ForegroundCodeBook",ImaskCodeBook);
+ cvShowImage( "CodeBook_ConnectComp",ImaskCodeBookCC);
+ }
+
+ // User input:
+ c = cvWaitKey(10)&0xFF;
+ c = tolower(c);
+ // End processing on ESC, q or Q
+ if(c == 27 || c == 'q')
+ break;
+ //Else check for user input
+ switch( c )
+ {
+ case 'h':
+ help();
+ break;
+ case 'p':
+ pause = !pause;
+ break;
+ case 's':
+ singlestep = !singlestep;
+ pause = false;
+ break;
+ case 'r':
+ pause = false;
+ singlestep = false;
+ break;
+ case ' ':
+ cvBGCodeBookClearStale( model, 0 );
+ nframes = 0;
+ break;
+ //CODEBOOK PARAMS
+ case 'y': case '0':
+ case 'u': case '1':
+ case 'v': case '2':
+ case 'a': case '3':
+ case 'b':
+ ch[0] = c == 'y' || c == '0' || c == 'a' || c == '3';
+ ch[1] = c == 'u' || c == '1' || c == 'a' || c == '3' || c == 'b';
+ ch[2] = c == 'v' || c == '2' || c == 'a' || c == '3' || c == 'b';
+ printf("CodeBook YUV Channels active: %d, %d, %d\n", ch[0], ch[1], ch[2] );
+ break;
+ case 'i': //modify max classification bounds (max bound goes higher)
+ case 'o': //modify max classification bounds (max bound goes lower)
+ case 'k': //modify min classification bounds (min bound goes lower)
+ case 'l': //modify min classification bounds (min bound goes higher)
+ {
+ uchar* ptr = c == 'i' || c == 'o' ? model->modMax : model->modMin;
+ for(n=0; n<NCHANNELS; n++)
+ {
+ if( ch[n] )
+ {
+ int v = ptr[n] + (c == 'i' || c == 'l' ? 1 : -1);
+ ptr[n] = CV_CAST_8U(v);
+ }
+ printf("%d,", ptr[n]);
+ }
+ printf(" CodeBook %s Side\n", c == 'i' || c == 'o' ? "High" : "Low" );
+ }
+ break;
+ }
+ }
+
+ cvReleaseCapture( &capture );
+ cvDestroyWindow( "Raw" );
+ cvDestroyWindow( "ForegroundCodeBook");
+ cvDestroyWindow( "CodeBook_ConnectComp");
+ return 0;
+}