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