some samples updated according to new CommandLineParser class
[profile/ivi/opencv.git] / samples / c / bgfg_codebook.cpp
1 // Background average sample code done with averages and done with codebooks
2 // (adapted from the OpenCV book sample)
3 // 
4 // NOTE: To get the keyboard to work, you *have* to have one of the video windows be active
5 //       and NOT the consule window.
6 //
7 // Gary Bradski Oct 3, 2008.
8 // 
9 /* *************** License:**************************
10    Oct. 3, 2008
11    Right to use this code in any way you want without warrenty, support or any guarentee of it working.
12
13    BOOK: It would be nice if you cited it:
14    Learning OpenCV: Computer Vision with the OpenCV Library
15      by Gary Bradski and Adrian Kaehler
16      Published by O'Reilly Media, October 3, 2008
17  
18    AVAILABLE AT: 
19      http://www.amazon.com/Learning-OpenCV-Computer-Vision-Library/dp/0596516134
20      Or: http://oreilly.com/catalog/9780596516130/
21      ISBN-10: 0596516134 or: ISBN-13: 978-0596516130    
22 ************************************************** */
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <ctype.h>
27
28 #include <opencv2/core/core.hpp>
29 #include <opencv2/video/background_segm.hpp>
30 #include <opencv2/imgproc/imgproc_c.h>
31 #include <opencv2/highgui/highgui.hpp>
32
33 using namespace std;
34 using namespace cv;
35
36 //VARIABLES for CODEBOOK METHOD:
37 CvBGCodeBookModel* model = 0;
38 const int NCHANNELS = 3;
39 bool ch[NCHANNELS]={true,true,true}; // This sets what channels should be adjusted for background bounds
40
41 void help(void)
42 {
43     printf("\nLearn background and find foreground using simple average and average difference learning method:\n"
44                 "Originally from the book: Learning OpenCV by O'Reilly press\n"
45             "\nUSAGE:\n"
46             "./bgfg_codebook [--nframes=300] \n"
47             "   [--input = movie filename or camera index]\n"
48             "***Keep the focus on the video windows, NOT the consol***\n\n"
49             "INTERACTIVE PARAMETERS:\n"
50             "\tESC,q,Q  - quit the program\n"
51             "\th        - print this help\n"
52             "\tp        - pause toggle\n"
53             "\ts        - single step\n"
54             "\tr        - run mode (single step off)\n"
55             "=== AVG PARAMS ===\n"
56             "\t-    - bump high threshold UP by 0.25\n"
57             "\t=    - bump high threshold DOWN by 0.25\n"
58             "\t[    - bump low threshold UP by 0.25\n"
59             "\t]    - bump low threshold DOWN by 0.25\n"
60             "=== CODEBOOK PARAMS ===\n"
61             "\ty,u,v- only adjust channel 0(y) or 1(u) or 2(v) respectively\n"
62             "\ta        - adjust all 3 channels at once\n"
63             "\tb        - adjust both 2 and 3 at once\n"
64             "\ti,o      - bump upper threshold up,down by 1\n"
65             "\tk,l      - bump lower threshold up,down by 1\n"
66             "\tSPACE - reset the model\n"
67         );
68 }
69
70 //
71 //USAGE:  ch9_background startFrameCollection# endFrameCollection# [movie filename, else from camera]
72 //If from AVI, then optionally add HighAvg, LowAvg, HighCB_Y LowCB_Y HighCB_U LowCB_U HighCB_V LowCB_V
73 //
74 int main(int argc, const char** argv)
75 {
76     help();
77
78     CommandLineParser parser(argc, argv);
79
80     string inputName = parser.get<string>("input", "0");
81     int nframesToLearnBG = parser.get<int>("nframes", 300);
82
83     IplImage* rawImage = 0, *yuvImage = 0; //yuvImage is for codebook method
84     IplImage *ImaskCodeBook = 0,*ImaskCodeBookCC = 0;
85     CvCapture* capture = 0;
86     int c, n, nframes = 0;
87
88
89     model = cvCreateBGCodeBookModel();
90     
91     //Set color thresholds to default values
92     model->modMin[0] = 3;
93     model->modMin[1] = model->modMin[2] = 3;
94     model->modMax[0] = 10;
95     model->modMax[1] = model->modMax[2] = 10;
96     model->cbBounds[0] = model->cbBounds[1] = model->cbBounds[2] = 10;
97
98     bool pause = false;
99     bool singlestep = false;
100
101     if( inputName.empty() || (isdigit(inputName.c_str()[0]) && inputName.c_str()[1] == '\0') )
102     {
103         printf("Capture from camera\n");
104         capture = cvCaptureFromCAM( inputName.empty() ? 0 : inputName.c_str()[0] - '0' );
105         int c = inputName.empty() ? 0 : inputName.c_str()[0] - '0' ;
106         if( !capture)
107         {
108             printf ("Capture from CAM %d", c);
109             printf (" didn't work\n");
110         }
111     }
112         else
113         {
114             printf("Capture from file %s\n",inputName.c_str());
115             capture = cvCreateFileCapture(inputName.c_str());
116             if( !capture)
117             {
118                 printf ("Capture from file %s", inputName.c_str());
119                 printf (" didn't work\n");
120                 help();
121                 return -1;
122             }
123
124         }
125
126     //MAIN PROCESSING LOOP:
127     for(;;)
128     {
129         if( !pause )
130         {
131             rawImage = cvQueryFrame( capture );
132             ++nframes;
133             if(!rawImage) 
134                 break;
135         }
136         if( singlestep )
137             pause = true;
138         
139         //First time:
140         if( nframes == 1 && rawImage )
141         {
142             // CODEBOOK METHOD ALLOCATION
143             yuvImage = cvCloneImage(rawImage);
144             ImaskCodeBook = cvCreateImage( cvGetSize(rawImage), IPL_DEPTH_8U, 1 );
145             ImaskCodeBookCC = cvCreateImage( cvGetSize(rawImage), IPL_DEPTH_8U, 1 );
146             cvSet(ImaskCodeBook,cvScalar(255));
147             
148             cvNamedWindow( "Raw", 1 );
149             cvNamedWindow( "ForegroundCodeBook",1);
150             cvNamedWindow( "CodeBook_ConnectComp",1);
151         }
152
153         // If we've got an rawImage and are good to go:                
154         if( rawImage )
155         {
156             cvCvtColor( rawImage, yuvImage, CV_BGR2YCrCb );//YUV For codebook method
157             //This is where we build our background model
158             if( !pause && nframes-1 < nframesToLearnBG  )
159                 cvBGCodeBookUpdate( model, yuvImage );
160
161             if( nframes-1 == nframesToLearnBG  )
162                 cvBGCodeBookClearStale( model, model->t/2 );
163             
164             //Find the foreground if any
165             if( nframes-1 >= nframesToLearnBG  )
166             {
167                 // Find foreground by codebook method
168                 cvBGCodeBookDiff( model, yuvImage, ImaskCodeBook );
169                 // This part just to visualize bounding boxes and centers if desired
170                 cvCopy(ImaskCodeBook,ImaskCodeBookCC);  
171                 cvSegmentFGMask( ImaskCodeBookCC );
172             }
173             //Display
174             cvShowImage( "Raw", rawImage );
175             cvShowImage( "ForegroundCodeBook",ImaskCodeBook);
176             cvShowImage( "CodeBook_ConnectComp",ImaskCodeBookCC);
177         }
178
179         // User input:
180         c = cvWaitKey(10)&0xFF;
181         c = tolower(c);
182         // End processing on ESC, q or Q
183         if(c == 27 || c == 'q')
184             break;
185         //Else check for user input
186         switch( c )
187         {
188         case 'h':
189             help();
190             break;
191         case 'p':
192             pause = !pause;
193             break;
194         case 's':
195             singlestep = !singlestep;
196             pause = false;
197             break;
198         case 'r':
199             pause = false;
200             singlestep = false;
201             break;
202         case ' ':
203             cvBGCodeBookClearStale( model, 0 );
204             nframes = 0;
205             break;
206             //CODEBOOK PARAMS
207         case 'y': case '0':
208         case 'u': case '1':
209         case 'v': case '2':
210         case 'a': case '3':
211         case 'b': 
212             ch[0] = c == 'y' || c == '0' || c == 'a' || c == '3';
213             ch[1] = c == 'u' || c == '1' || c == 'a' || c == '3' || c == 'b';
214             ch[2] = c == 'v' || c == '2' || c == 'a' || c == '3' || c == 'b';
215             printf("CodeBook YUV Channels active: %d, %d, %d\n", ch[0], ch[1], ch[2] );
216             break;
217         case 'i': //modify max classification bounds (max bound goes higher)
218         case 'o': //modify max classification bounds (max bound goes lower)
219         case 'k': //modify min classification bounds (min bound goes lower)
220         case 'l': //modify min classification bounds (min bound goes higher)
221             {
222             uchar* ptr = c == 'i' || c == 'o' ? model->modMax : model->modMin;
223             for(n=0; n<NCHANNELS; n++)
224             {
225                 if( ch[n] )
226                 {
227                     int v = ptr[n] + (c == 'i' || c == 'l' ? 1 : -1);
228                     ptr[n] = cv::saturate_cast<uchar>(v);
229                 }
230                 printf("%d,", ptr[n]);
231             }
232             printf(" CodeBook %s Side\n", c == 'i' || c == 'o' ? "High" : "Low" );
233             }
234             break;
235         }
236     }           
237     
238     cvReleaseCapture( &capture );
239     cvDestroyWindow( "Raw" );
240     cvDestroyWindow( "ForegroundCodeBook");
241     cvDestroyWindow( "CodeBook_ConnectComp");
242     return 0;
243 }