Move the sources to trunk
[opencv] / samples / c / camshiftdemo.c
1 #ifdef _CH_
2 #pragma package <opencv>
3 #endif
4
5 #ifndef _EiC
6 #include "cv.h"
7 #include "highgui.h"
8 #include <stdio.h>
9 #include <ctype.h>
10 #endif
11
12 IplImage *image = 0, *hsv = 0, *hue = 0, *mask = 0, *backproject = 0, *histimg = 0;
13 CvHistogram *hist = 0;
14
15 int backproject_mode = 0;
16 int select_object = 0;
17 int track_object = 0;
18 int show_hist = 1;
19 CvPoint origin;
20 CvRect selection;
21 CvRect track_window;
22 CvBox2D track_box;
23 CvConnectedComp track_comp;
24 int hdims = 16;
25 float hranges_arr[] = {0,180};
26 float* hranges = hranges_arr;
27 int vmin = 10, vmax = 256, smin = 30;
28
29 void on_mouse( int event, int x, int y, int flags, void* param )
30 {
31     if( !image )
32         return;
33
34     if( image->origin )
35         y = image->height - y;
36
37     if( select_object )
38     {
39         selection.x = MIN(x,origin.x);
40         selection.y = MIN(y,origin.y);
41         selection.width = selection.x + CV_IABS(x - origin.x);
42         selection.height = selection.y + CV_IABS(y - origin.y);
43         
44         selection.x = MAX( selection.x, 0 );
45         selection.y = MAX( selection.y, 0 );
46         selection.width = MIN( selection.width, image->width );
47         selection.height = MIN( selection.height, image->height );
48         selection.width -= selection.x;
49         selection.height -= selection.y;
50     }
51
52     switch( event )
53     {
54     case CV_EVENT_LBUTTONDOWN:
55         origin = cvPoint(x,y);
56         selection = cvRect(x,y,0,0);
57         select_object = 1;
58         break;
59     case CV_EVENT_LBUTTONUP:
60         select_object = 0;
61         if( selection.width > 0 && selection.height > 0 )
62             track_object = -1;
63         break;
64     }
65 }
66
67
68 CvScalar hsv2rgb( float hue )
69 {
70     int rgb[3], p, sector;
71     static const int sector_data[][3]=
72         {{0,2,1}, {1,2,0}, {1,0,2}, {2,0,1}, {2,1,0}, {0,1,2}};
73     hue *= 0.033333333333333333333333333333333f;
74     sector = cvFloor(hue);
75     p = cvRound(255*(hue - sector));
76     p ^= sector & 1 ? 255 : 0;
77
78     rgb[sector_data[sector][0]] = 255;
79     rgb[sector_data[sector][1]] = 0;
80     rgb[sector_data[sector][2]] = p;
81
82     return cvScalar(rgb[2], rgb[1], rgb[0],0);
83 }
84
85 int main( int argc, char** argv )
86 {
87     CvCapture* capture = 0;
88     
89     if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
90         capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - '0' : 0 );
91     else if( argc == 2 )
92         capture = cvCaptureFromAVI( argv[1] ); 
93
94     if( !capture )
95     {
96         fprintf(stderr,"Could not initialize capturing...\n");
97         return -1;
98     }
99
100     printf( "Hot keys: \n"
101         "\tESC - quit the program\n"
102         "\tc - stop the tracking\n"
103         "\tb - switch to/from backprojection view\n"
104         "\th - show/hide object histogram\n"
105         "To initialize tracking, select the object with mouse\n" );
106
107     cvNamedWindow( "Histogram", 1 );
108     cvNamedWindow( "CamShiftDemo", 1 );
109     cvSetMouseCallback( "CamShiftDemo", on_mouse, 0 );
110     cvCreateTrackbar( "Vmin", "CamShiftDemo", &vmin, 256, 0 );
111     cvCreateTrackbar( "Vmax", "CamShiftDemo", &vmax, 256, 0 );
112     cvCreateTrackbar( "Smin", "CamShiftDemo", &smin, 256, 0 );
113
114     for(;;)
115     {
116         IplImage* frame = 0;
117         int i, bin_w, c;
118
119         frame = cvQueryFrame( capture );
120         if( !frame )
121             break;
122
123         if( !image )
124         {
125             /* allocate all the buffers */
126             image = cvCreateImage( cvGetSize(frame), 8, 3 );
127             image->origin = frame->origin;
128             hsv = cvCreateImage( cvGetSize(frame), 8, 3 );
129             hue = cvCreateImage( cvGetSize(frame), 8, 1 );
130             mask = cvCreateImage( cvGetSize(frame), 8, 1 );
131             backproject = cvCreateImage( cvGetSize(frame), 8, 1 );
132             hist = cvCreateHist( 1, &hdims, CV_HIST_ARRAY, &hranges, 1 );
133             histimg = cvCreateImage( cvSize(320,200), 8, 3 );
134             cvZero( histimg );
135         }
136
137         cvCopy( frame, image, 0 );
138         cvCvtColor( image, hsv, CV_BGR2HSV );
139
140         if( track_object )
141         {
142             int _vmin = vmin, _vmax = vmax;
143
144             cvInRangeS( hsv, cvScalar(0,smin,MIN(_vmin,_vmax),0),
145                         cvScalar(180,256,MAX(_vmin,_vmax),0), mask );
146             cvSplit( hsv, hue, 0, 0, 0 );
147
148             if( track_object < 0 )
149             {
150                 float max_val = 0.f;
151                 cvSetImageROI( hue, selection );
152                 cvSetImageROI( mask, selection );
153                 cvCalcHist( &hue, hist, 0, mask );
154                 cvGetMinMaxHistValue( hist, 0, &max_val, 0, 0 );
155                 cvConvertScale( hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0 );
156                 cvResetImageROI( hue );
157                 cvResetImageROI( mask );
158                 track_window = selection;
159                 track_object = 1;
160
161                 cvZero( histimg );
162                 bin_w = histimg->width / hdims;
163                 for( i = 0; i < hdims; i++ )
164                 {
165                     int val = cvRound( cvGetReal1D(hist->bins,i)*histimg->height/255 );
166                     CvScalar color = hsv2rgb(i*180.f/hdims);
167                     cvRectangle( histimg, cvPoint(i*bin_w,histimg->height),
168                                  cvPoint((i+1)*bin_w,histimg->height - val),
169                                  color, -1, 8, 0 );
170                 }
171             }
172
173             cvCalcBackProject( &hue, backproject, hist );
174             cvAnd( backproject, mask, backproject, 0 );
175             cvCamShift( backproject, track_window,
176                         cvTermCriteria( CV_TERMCRIT_EPS | CV_TERMCRIT_ITER, 10, 1 ),
177                         &track_comp, &track_box );
178             track_window = track_comp.rect;
179             
180             if( backproject_mode )
181                 cvCvtColor( backproject, image, CV_GRAY2BGR );
182             if( !image->origin )
183                 track_box.angle = -track_box.angle;
184             cvEllipseBox( image, track_box, CV_RGB(255,0,0), 3, CV_AA, 0 );
185         }
186         
187         if( select_object && selection.width > 0 && selection.height > 0 )
188         {
189             cvSetImageROI( image, selection );
190             cvXorS( image, cvScalarAll(255), image, 0 );
191             cvResetImageROI( image );
192         }
193
194         cvShowImage( "CamShiftDemo", image );
195         cvShowImage( "Histogram", histimg );
196
197         c = cvWaitKey(10);
198         if( (char) c == 27 )
199             break;
200         switch( (char) c )
201         {
202         case 'b':
203             backproject_mode ^= 1;
204             break;
205         case 'c':
206             track_object = 0;
207             cvZero( histimg );
208             break;
209         case 'h':
210             show_hist ^= 1;
211             if( !show_hist )
212                 cvDestroyWindow( "Histogram" );
213             else
214                 cvNamedWindow( "Histogram", 1 );
215             break;
216         default:
217             ;
218         }
219     }
220
221     cvReleaseCapture( &capture );
222     cvDestroyWindow("CamShiftDemo");
223
224     return 0;
225 }
226
227 #ifdef _EiC
228 main(1,"camshiftdemo.c");
229 #endif