converted some more samples to C++
[profile/ivi/opencv.git] / samples / c / motempl.c
1 #include "opencv2/video/tracking.hpp"
2 #include "opencv2/imgproc/imgproc.hpp"
3 #include "opencv2/highgui/highgui.hpp"
4 #include <time.h>
5
6 // various tracking parameters (in seconds)
7 const double MHI_DURATION = 1;
8 const double MAX_TIME_DELTA = 0.5;
9 const double MIN_TIME_DELTA = 0.05;
10 // number of cyclic frame buffer used for motion detection
11 // (should, probably, depend on FPS)
12 const int N = 4;
13
14 // ring image buffer
15 IplImage **buf = 0;
16 int last = 0;
17
18 // temporary images
19 IplImage *mhi = 0; // MHI
20 IplImage *orient = 0; // orientation
21 IplImage *mask = 0; // valid orientation mask
22 IplImage *segmask = 0; // motion segmentation map
23 CvMemStorage* storage = 0; // temporary storage
24
25 // parameters:
26 //  img - input video frame
27 //  dst - resultant motion picture
28 //  args - optional parameters
29 void  update_mhi( IplImage* img, IplImage* dst, int diff_threshold )
30 {
31     double timestamp = (double)clock()/CLOCKS_PER_SEC; // get current time in seconds
32     CvSize size = cvSize(img->width,img->height); // get current frame size
33     int i, idx1 = last, idx2;
34     IplImage* silh;
35     CvSeq* seq;
36     CvRect comp_rect;
37     double count;
38     double angle;
39     CvPoint center;
40     double magnitude;
41     CvScalar color;
42
43     // allocate images at the beginning or
44     // reallocate them if the frame size is changed
45     if( !mhi || mhi->width != size.width || mhi->height != size.height ) {
46         if( buf == 0 ) {
47             buf = (IplImage**)malloc(N*sizeof(buf[0]));
48             memset( buf, 0, N*sizeof(buf[0]));
49         }
50
51         for( i = 0; i < N; i++ ) {
52             cvReleaseImage( &buf[i] );
53             buf[i] = cvCreateImage( size, IPL_DEPTH_8U, 1 );
54             cvZero( buf[i] );
55         }
56         cvReleaseImage( &mhi );
57         cvReleaseImage( &orient );
58         cvReleaseImage( &segmask );
59         cvReleaseImage( &mask );
60
61         mhi = cvCreateImage( size, IPL_DEPTH_32F, 1 );
62         cvZero( mhi ); // clear MHI at the beginning
63         orient = cvCreateImage( size, IPL_DEPTH_32F, 1 );
64         segmask = cvCreateImage( size, IPL_DEPTH_32F, 1 );
65         mask = cvCreateImage( size, IPL_DEPTH_8U, 1 );
66     }
67
68     cvCvtColor( img, buf[last], CV_BGR2GRAY ); // convert frame to grayscale
69
70     idx2 = (last + 1) % N; // index of (last - (N-1))th frame
71     last = idx2;
72
73     silh = buf[idx2];
74     cvAbsDiff( buf[idx1], buf[idx2], silh ); // get difference between frames
75
76     cvThreshold( silh, silh, diff_threshold, 1, CV_THRESH_BINARY ); // and threshold it
77     cvUpdateMotionHistory( silh, mhi, timestamp, MHI_DURATION ); // update MHI
78
79     // convert MHI to blue 8u image
80     cvCvtScale( mhi, mask, 255./MHI_DURATION,
81                 (MHI_DURATION - timestamp)*255./MHI_DURATION );
82     cvZero( dst );
83     cvMerge( mask, 0, 0, 0, dst );
84
85     // calculate motion gradient orientation and valid orientation mask
86     cvCalcMotionGradient( mhi, mask, orient, MAX_TIME_DELTA, MIN_TIME_DELTA, 3 );
87
88     if( !storage )
89         storage = cvCreateMemStorage(0);
90     else
91         cvClearMemStorage(storage);
92
93     // segment motion: get sequence of motion components
94     // segmask is marked motion components map. It is not used further
95     seq = cvSegmentMotion( mhi, segmask, storage, timestamp, MAX_TIME_DELTA );
96
97     // iterate through the motion components,
98     // One more iteration (i == -1) corresponds to the whole image (global motion)
99     for( i = -1; i < seq->total; i++ ) {
100
101         if( i < 0 ) { // case of the whole image
102             comp_rect = cvRect( 0, 0, size.width, size.height );
103             color = CV_RGB(255,255,255);
104             magnitude = 100;
105         }
106         else { // i-th motion component
107             comp_rect = ((CvConnectedComp*)cvGetSeqElem( seq, i ))->rect;
108             if( comp_rect.width + comp_rect.height < 100 ) // reject very small components
109                 continue;
110             color = CV_RGB(255,0,0);
111             magnitude = 30;
112         }
113
114         // select component ROI
115         cvSetImageROI( silh, comp_rect );
116         cvSetImageROI( mhi, comp_rect );
117         cvSetImageROI( orient, comp_rect );
118         cvSetImageROI( mask, comp_rect );
119
120         // calculate orientation
121         angle = cvCalcGlobalOrientation( orient, mask, mhi, timestamp, MHI_DURATION);
122         angle = 360.0 - angle;  // adjust for images with top-left origin
123
124         count = cvNorm( silh, 0, CV_L1, 0 ); // calculate number of points within silhouette ROI
125
126         cvResetImageROI( mhi );
127         cvResetImageROI( orient );
128         cvResetImageROI( mask );
129         cvResetImageROI( silh );
130
131         // check for the case of little motion
132         if( count < comp_rect.width*comp_rect.height * 0.05 )
133             continue;
134
135         // draw a clock with arrow indicating the direction
136         center = cvPoint( (comp_rect.x + comp_rect.width/2),
137                           (comp_rect.y + comp_rect.height/2) );
138
139         cvCircle( dst, center, cvRound(magnitude*1.2), color, 3, CV_AA, 0 );
140         cvLine( dst, center, cvPoint( cvRound( center.x + magnitude*cos(angle*CV_PI/180)),
141                 cvRound( center.y - magnitude*sin(angle*CV_PI/180))), color, 3, CV_AA, 0 );
142     }
143 }
144
145
146 int main(int argc, char** argv)
147 {
148     IplImage* motion = 0;
149     CvCapture* capture = 0;
150
151     if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
152         capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - '0' : 0 );
153     else if( argc == 2 )
154         capture = cvCaptureFromFile( argv[1] );
155
156     if( capture )
157     {
158         cvNamedWindow( "Motion", 1 );
159
160         for(;;)
161         {
162             IplImage* image = cvQueryFrame( capture );
163             if( !image )
164                 break;
165
166             if( !motion )
167             {
168                 motion = cvCreateImage( cvSize(image->width,image->height), 8, 3 );
169                 cvZero( motion );
170                 motion->origin = image->origin;
171             }
172
173             update_mhi( image, motion, 30 );
174             cvShowImage( "Motion", motion );
175
176             if( cvWaitKey(10) >= 0 )
177                 break;
178         }
179         cvReleaseCapture( &capture );
180         cvDestroyWindow( "Motion" );
181     }
182
183     return 0;
184 }
185
186 #ifdef _EiC
187 main(1,"motempl.c");
188 #endif